panel绑定主体错误导致事件无法触发问题记录(尺寸异常)

发布时间 2023-06-25 17:52:23作者: No九五二七9527

代码实例

#coding:utf-8
#!/usr/bin/env python
#@author: 9527 

import wx

class DelayStatisticalPanel(wx.Panel):
    '''
    @function: 背景板(BOOK)
    @By: 9527
    '''
    def __init__(self,parent):
        super().__init__(parent)  
        self.parent = parent
        
        self.Mainpanel= wx.Panel(self)
        self.Bind(wx.EVT_SIZE, self.on_size) 
        self.Mainpanel.SetBackgroundColour("yellow")
        
        
        self.InfoBook = wx.Notebook(self.Mainpanel, style=wx.BK_DEFAULT|wx.NB_FIXEDWIDTH)
        self.InfoBook.SetBackgroundColour("pink")
        
        vsizer = wx.BoxSizer(wx.VERTICAL)
        vsizer.Add(self.InfoBook, 1, wx.EXPAND)
        self.Mainpanel.SetSizer(vsizer)
        
        
        
        self.page_SCB = StatisticalChartBoard(self.InfoBook)
        self.page_DDL = DetailDataList(self.InfoBook)
        
        self.InfoBook.AddPage(self.page_SCB, u"延期统计")
        self.InfoBook.AddPage(self.page_DDL, u"详细数据")
def on_size(self, event):
        #重绘窗口尺寸(跟随主panel)
        self.Mainpanel.SetSize(self.parent.GetSize())    
        
        self.Mainpanel.Layout()

class StatisticalChartBoard(wx.Panel):
    '''
    @function: 统计图面板
    @By: 9527
    '''
    def __init__(self,parent):
        super().__init__(parent)
        self.parent = parent
        self.SCB_panel1 = wx.ScrolledWindow( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
  
        self.SCB_panel1.SetBackgroundColour("red")
        self.Bind(wx.EVT_SIZE, self.on_size) 
        
        self.SCB_panel1.SetScrollbars(1, 1, 1, 1)# 必须设置滚动条大小,否则无法显示
        
        self.SCB_panel1.Layout()
    
    def on_size(self, event):
        #重绘窗口尺寸(跟随主panel)

        self.SCB_panel1.SetSize(self.parent.GetSize())
        
        self.SCB_panel1.Layout()    
        
class DetailDataList(wx.Panel):
    '''
    @function: 详细数据面板
    @By: 9527
    '''
    def __init__(self,parent):
        super().__init__(parent)  
        self.parent = parent
        self.DDL_panel1 = wx.ScrolledWindow( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
      
       
        self.DDL_panel1.SetBackgroundColour("blue")
        self.Bind(wx.EVT_SIZE, self.on_size) 
        
        self.DDL_panel1.SetScrollbars(1, 1, 1, 1)# 必须设置滚动条大小,否则无法显示
    
        self.DDL_panel1.Layout() 
    
    def on_size(self, event):
        #重绘窗口尺寸(跟随主panel)
    
        self.DDL_panel1.SetSize(self.parent.GetSize()) 
        
        self.DDL_panel1.Layout() 
            

 

注意这里 self.Bind(wx.EVT_SIZE, self.on_size)  绑定在主体self上,而不是类中的某个panel上。这一点很重要,直接决定事件wx.EVT_SIZE会不会触发。

如果像这样self.DDL_panel1.Bind(wx.EVT_SIZE, self.on_size)、self.SCB_panel1.Bind(wx.EVT_SIZE, self.on_size)直接把尺寸改变的事件绑定到类里面的实例上,就会导致事件无法触发,原因可能是实例的父级是当前实例所在的类,而本地类的父级才是变化的面板panel(这里的就是self.InfoBook)。所以无论是DelayStatisticalPanel还是StatisticalChartBoard、DetailDataList都需要用最外层的类上,self.Bind(wx.EVT_SIZE, self.on_size) ,才能使事件发生后触发,并调用on_size函数。

(在wxPython中,当一个事件被触发时,它会被发送到相应的控件。然后,事件将被传递给控件的父级,直到找到处理该事件的处理程序或顶级窗口。)

可以简单的认为,事件的变化结果是逐级传递的,DelayStatisticalPanel→StatisticalChartBoard→panel、DelayStatisticalPanel→DetailDataList→panel。如果不绑定在DelayStatisticalPanel还是StatisticalChartBoard、DetailDataList本身上,就会导致传递断层。