wxPython之继承

1、继承的局限

  wxPython是一个wxWidgets C++框架的封装。这种关系意味着在大多数wxPython对象里都是C++对象。由于这个,wxPython类的方法不能像普通Python对象一样重写。
  通过如何创建一个自动添加自己子窗口到其布局器Sizer的类的例子,展示什么情况下类的子类可以重写方法。

2、示例说明

  我们创建两个相似的类,用来自动添加自己子窗口到其布局器Sizer里。MyPanel继承于标准的Panel类,MyVirtualPanel则继承于PyPanel类。

#-*-coding: UTF-8 -*-
#------------------------------------------------------
#Purpose: nothing....

#Author: 阿Bin先生
#Created: 2017年5月21日
#------------------------------------------------------
import wx

class MyPanel(wx.Panel):
    def __init__(self, parent):
        super(MyPanel, self).__init__(parent)
        sizer = wx.BoxSizer()
        self.SetSizer(sizer)

    def AddChild(self, child):
        sizer = self.GetSizer()
        sizer.Add(child, 0, wx.ALIGN_LEFT|wx.ALL, 8)
        return super(MyPanel, self).AddChild(child)

class MyVirtualPanel(wx.PyPanel):
    """Class that automatically adds children
    controls to sizer layout.
    """
    def __init__(self, parent):
        super(MyVirtualPanel, self).__init__(parent)
        sizer = wx.BoxSizer()
        self.SetSizer(sizer)

    def AddChild(self, child):
        sizer = self.GetSizer()
        sizer.Add(child, 0, wx.ALIGN_LEFT|wx.ALL, 8)
        return super(MyVirtualPanel, self).AddChild(child)

class MyFrame(wx.Frame):
    def __init__(self, parent, *args, **kwargs):
        super(MyFrame, self).__init__(parent, *args, **kwargs)
        # Attributes
        self.mypanel = MyPanel(self)
        self.mypanel.SetBackgroundColour(wx.BLUE)
        self.virtpanel = MyVirtualPanel(self)

        self.virtpanel.SetBackgroundColour(wx.WHITE)
        # Setup
        self.__DoLayout()

    def __DoLayout(self):
        """Layout the window"""
        # Layout the controls using a sizer
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.mypanel, 1, wx.EXPAND)
        sizer.Add(self.virtpanel, 1, wx.EXPAND)
        self.SetSizer(sizer)
        # Create 3 children for the top panel
        for x in range(3):
            wx.Button(self.mypanel, label="MyPanel %d" % x)
        # Create 3 children for the bottom panel
        for x in range(3):
            wx.Button(self.virtpanel, label="VirtPanel %d" % x)
        self.SetInitialSize(size=(300, 200))

class MyApp(wx.App):
    def OnInit(self):
        self.frame = MyFrame(None, title="Virtualized Methods")
        self.SetTopWindow(self.frame)
        self.frame.Show()
        return True

if __name__ == "__main__":
    app = MyApp(False)
    app.MainLoop()

运行结果:

这里写图片描述

3、示例分析

  示例中创建的Panel类都重写了AddChild方法,该方法希望每次在窗口有子窗口创建时被调用。AddChild方法是在类的C++部分里被调用,因此为了能够重写该方法 ,需要类能够提供重写C++类虚方法的访问。运行结果表明,Py开个头的类暴露了很多C++类虚方法,这些方法在Python子类里被重写后,绑定到对象C++层中,被框架调用时替代基类的实现。而MyPanel的AddChild 方法从来没有被调用。

如何判断类的方法是不是以虚函数形式暴露?

有个小技巧可以帮助判断。

import wx
for method in dir(wx.PyPanel):
    if method.startswith('base_'):
        print method

dir()里插入任何类,上面代码打印出所有虚方法,方法名以base_开头,这些方法不能在代码中直接使用。

运行结果:

这里写图片描述

4、总结

  根据实际需求,决定是否继承以Py开个头的类。如果重写的方法,是在类的C++部分调用,则要考虑该方法是否以虚方法形式暴露出来。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值