在 WxPython 中的面板之间传递信息



我有一个非常复杂的wxpython应用程序,它有嵌套的笔记本和面板。基本上结构是在我的主框架中我有一个笔记本(假设笔记本 1,在笔记本的一页中我有两个面板(上部和下部)。在下面的面板中,我有另一个笔记本(假设笔记本 2)。所以问题是我如何在这两个笔记本页面之间传递信息,并传递到上面的面板。

我知道基本上有三种传递信息的方式:按事件 ID、按发布者、按 .parent 和 .child。但是,我对这三种方法的区别以及何时使用它们感到非常困惑。

我附上了我的代码,如下所示。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import datetime, time
import wx, sys, wx.grid
import xlrd
import pandas as pd
import numpy as np
import wx.lib.scrolledpanel as scrolled
EVEN_ROW_COLOUR = '#CCE6FF'
GRID_LINE_COLOUR = '#ccc'
import pandas as pd
import numpy as np
class ResultTable(wx.grid.PyGridTableBase):
def __init__(self, data=None):
wx.grid.PyGridTableBase.__init__(self)
self.data = data
self.odd=wx.grid.GridCellAttr()
self.odd.SetBackgroundColour("sky blue")
self.odd.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD))
self.even=wx.grid.GridCellAttr()
self.even.SetBackgroundColour("sea green")
self.even.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD))
def GetNumberRows(self):
return self.data.shape[0]
def GetNumberCols(self):
return self.data.shape[1]
def GetValue(self, row, col):
return self.data.loc[row][col]
def GetColLabelValue(self, row):
return list(self.data)[row]
def SetValue(self, row, col, value):
pass
def GetAttr(self, row, col, prop):
attr = wx.grid.GridCellAttr()
if row % 2 == 1:
attr.SetBackgroundColour(EVEN_ROW_COLOUR)
return attr
class ResultTablePanel(wx.Panel):
def __init__(self, parent, id):
wx.Panel.__init__(self, parent, id, style=wx.BORDER_SUNKEN)
grid = wx.grid.Grid(self)

result = pd.DataFrame({'a' : np.random.randn(100), 'b' : np.random.randn(100), 'c' : np.random.randn(100)})
table = ResultTable(result)
grid.SetTable(table)
grid.AutoSize()
grid.AutoSizeColumns(True)
grid.SetGridLineColour(GRID_LINE_COLOUR)
grid.EnableDragGridSize( False )
grid.SetRowLabelSize( 50 )
grid.SetDefaultCellAlignment( wx.ALIGN_CENTRE, wx.ALIGN_CENTRE )
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(grid, 1, wx.ALL|wx.EXPAND)
self.SetSizer(sizer)
btn_ID = parent.GetParent().GetParent().topPanel.analysisButton.GetId()
self.Bind(wx.EVT_BUTTON, self.getResult, id = btn_ID)
def getResult(self,e):
"""
This function should get the variables passed by the analysisOrder function,
once the button on the SearchConditionPanel is clicked.
"""
fileName, start_date, end_date = parent.GetParent().GetParent().topPanel.analysisOrder
print "result get as follows:"
print fileName, start_date, end_date

class SearchConditionPanel(wx.Panel):
def __init__(self, parent, id):
wx.Panel.__init__(self, parent, id, style=wx.BORDER_SUNKEN)
# Creat input box for searching time period
nameTitleLable = wx.StaticText(self,-1, label=u"File Name:")
self.fileNameInput = wx.TextCtrl(self,-1, "20170310221612")
dateTitleLable = wx.StaticText(self,-1, label=u"Date range:")
yearLable1 = wx.StaticText(self, label=u"Year:")
monthLable1 = wx.StaticText(self,-1, label=u"Month:")
dayLable1 = wx.StaticText(self,-1, label=u"Day:")
yearLable2 = wx.StaticText(self,-1, label=u"Year:")
monthLable2 = wx.StaticText(self,-1, label=u"Month:")
dayLable2 = wx.StaticText(self,-1, label=u"Day:")
startLable = wx.StaticText(self,-1, label=u"Start Date:")
endLable = wx.StaticText(self,-1, label=u"End Date:")
self.startYearInput = wx.TextCtrl(self,1, "2016")
self.startMonthInput = wx.TextCtrl(self,-1, "10")
self.startDayInput = wx.TextCtrl(self,-1, "30")
self.endYearInput = wx.TextCtrl(self,-1, "2017")
self.endMonthInput = wx.TextCtrl(self,-1, "11")
self.endDayInput = wx.TextCtrl(self,-1, "22")
self.analysisButton = wx.Button(self, -1, label = u'Start')
exportButton = wx.Button(self, -1, label = u'Export')
exportButton.Disable()
## Set up overall layout for the panel
hbox = wx.BoxSizer(wx.HORIZONTAL)
vbox_File_button = wx.BoxSizer(wx.VERTICAL)
hbox_file = wx.BoxSizer(wx.HORIZONTAL)
vbox_date = wx.BoxSizer(wx.VERTICAL)
hbox_button = wx.BoxSizer(wx.HORIZONTAL)
hbox_startDate = wx.BoxSizer(wx.HORIZONTAL)
hbox_endDate = wx.BoxSizer(wx.HORIZONTAL)
hbox.Add(vbox_date, 0, wx.ALIGN_LEFT | wx.ALL, 5)
hbox.Add(wx.StaticLine(self, style=wx.LI_VERTICAL), 0, wx.ALL | wx.EXPAND, 5)
hbox.Add(vbox_File_button, 0, wx.ALIGN_LEFT | wx.ALL, 5)
## Setup the layout for the right side
vbox_File_button.Add(hbox_file, 0, wx.ALIGN_LEFT | wx.ALL, 5)
vbox_File_button.Add(wx.StaticLine(self), 0, wx.ALL | wx.EXPAND, 5)
vbox_File_button.Add(hbox_button, 0, wx.ALIGN_LEFT | wx.ALL, 5)
hbox_file.Add(nameTitleLable, 0, wx.TOP | wx.LEFT | wx.BOTTOM, 10)
hbox_file.Add(self.fileNameInput, 0, wx.ALL | wx.EXPAND, 5)
hbox_button.Add(self.analysisButton, 1, wx.TOP | wx.LEFT, 10)
hbox_button.Add(exportButton, 1, wx.TOP | wx.LEFT, 10)
## Setup the layout for the left side
vbox_date.Add(dateTitleLable, 0, wx.ALL, 5)
vbox_date.Add(hbox_startDate, 0, wx.ALL | wx.EXPAND, 5)
vbox_date.Add(hbox_endDate, 0, wx.ALL | wx.EXPAND, 5)
hbox_startDate.Add(startLable, 0, wx.ALL, 5)
hbox_startDate.Add(yearLable1, 0, wx.TOP | wx.LEFT | wx.BOTTOM, 5)
hbox_startDate.Add(self.startYearInput, 0, wx.ALL, 5)
hbox_startDate.Add(monthLable1, 0, wx.TOP | wx.LEFT | wx.BOTTOM, 5)
hbox_startDate.Add(self.startMonthInput, 0, wx.ALL|wx.EXPAND, 5)
hbox_startDate.Add(dayLable1, 0, wx.TOP | wx.LEFT | wx.BOTTOM, 5)
hbox_startDate.Add(self.startDayInput, 0, wx.ALL|wx.EXPAND, 5)
hbox_endDate.Add(endLable, 0, wx.LEFT | wx.RIGHT, 5)
hbox_endDate.Add(yearLable2, 0, wx.LEFT, 5)
hbox_endDate.Add(self.endYearInput, 0, wx.LEFT | wx.RIGHT, 5)
hbox_endDate.Add(monthLable2, 0, wx.LEFT, 5)
hbox_endDate.Add(self.endMonthInput, 0, wx.LEFT | wx.RIGHT, 5)
hbox_endDate.Add(dayLable2, 0, wx.LEFT, 5)
hbox_endDate.Add(self.endDayInput, 0, wx.LEFT, 5)
self.SetSizer(hbox)
self.Bind(wx.EVT_BUTTON, self.analysisOrder, id=self.analysisButton.GetId())

def analysisOrder(self,e):
fileName_temp = self.fileNameInput.GetValue().strip()
fileName = fileName_temp + '.xls'
start_date = self.startYearInput.GetValue().strip() + '-' + self.startMonthInput.GetValue().strip() + '-' + self.startDayInput.GetValue().strip()
end_date = self.endYearInput.GetValue().strip() + '-' + self.endMonthInput.GetValue().strip() + '-' + self.endDayInput.GetValue().strip()
print "analysis order button called"
return fileName, start_date, end_date

class ResultNotebook(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
# Creat notebooks for window layout
result_notebook = wx.Notebook(self)
data_page = ResultTablePanel(result_notebook, -1)
result_notebook.AddPage(data_page, u"Display Data")
# Set up a boxsizer for the tabs
result_notebook_sizer = wx.BoxSizer(wx.HORIZONTAL)
result_notebook_sizer.Add(result_notebook, 1, wx.EXPAND)
self.SetSizer(result_notebook_sizer)
class ModePage(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
# Localize all the panels
self.topPanel = SearchConditionPanel(self, -1)
self.botPanel = ResultNotebook(self)
#Set up the panels, align and position them in the right place
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(self.topPanel, 0, wx.EXPAND | wx.ALL, 5)
vbox.Add(self.botPanel, -1, wx.EXPAND | wx.ALL, 5)
self.SetSizer(vbox)
self.Centre()
self.Show(True)

class FreqPage(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
# t = wx.StaticText(self, -1, "This is a Frequency Page object", (20,20))
# Localize all the panels
topPanel = SearchConditionPanel(self, -1)
t = wx.StaticText(self, -1, "This is a Frequency Page object")
#Set up the panels, align and position them in the right place
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(topPanel, 0, wx.EXPAND | wx.ALL, 5)
vbox.Add(t, -1, wx.EXPAND | wx.ALL, 5)
self.SetSizer(vbox)
self.Centre()
self.Show(True)
class OrderPage(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
# Localize all the panels
self.topPanel = SearchConditionPanel(self, -1)
self.botPanel = ResultNotebook(self)
#Set up the panels, align and position them in the right place
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(self.topPanel, 0, wx.EXPAND | wx.ALL, 5)
vbox.Add(self.botPanel, -1, wx.EXPAND | wx.ALL, 5)
self.SetSizer(vbox)
self.Centre()
self.Show(True)

class ShopPage(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
# Creat notebooks for window layout
shop_notebook = wx.Notebook(self)
mode_page = ModePage(shop_notebook)
freq_page = FreqPage(shop_notebook)
shop_notebook.AddPage(mode_page, u"Mode Analysis")
shop_notebook.AddPage(freq_page, u"Frequency Analysis")
# Set up a boxsizer for the tabs
shop_page_sizer = wx.BoxSizer(wx.HORIZONTAL)
shop_page_sizer.Add(shop_notebook, 1, wx.EXPAND)
self.SetSizer(shop_page_sizer)

##**----------------------------------------------------------------------------------**##
##**-------------- Create a windows to display the entire system ---------------------**##    
class OrderAnalysis(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(1024, 576))
# self.Maximize(True)  # Default display to be maximized
panel = wx.Panel(self, -1)
# Creat notebooks for window layout
main_notebook = wx.Notebook(panel, style=wx.NB_LEFT)
main_notebook.SetFont(wx.Font(10, wx.FONTFAMILY_DEFAULT,
wx.FONTWEIGHT_NORMAL, 
wx.FONTSTYLE_NORMAL))
# create the page windows as children of the notebook
order_page = OrderPage(main_notebook)
shop_page = ShopPage(main_notebook)
# add the pages to the notebook with the label to show on the tab
main_notebook.AddPage(order_page, u"Order Analysis")
main_notebook.AddPage(shop_page, u"Shop Analysis")

# finally, put the notebook in a sizer for the panel to manage
# the layout
sizer = wx.BoxSizer()
sizer.Add(main_notebook, 1, wx.EXPAND)
panel.SetSizer(sizer)

self.Centre()
self.Show(True)

if __name__ == "__main__":
app = wx.App()
OrderAnalysis(None, -1, 'Order Info Analyser')
app.MainLoop()

如您所见,我有一个搜索条件面板和一个结果面板,用于不同的页面。对于每个特定页面,搜索条件和结果可能不同,并且仅适用于该页面。所以我的问题是,将搜索条件(即数据和文件名)传递到相应页面以显示结果的最佳方法是什么(即"ResultTablePanel"中的"getResult"函数不起作用)。

例如,在"订单页面"中,搜索条件面板具有用户输入的开始和结束日期以及文件名。搜索条件面板下方是结果面板,显示基于搜索条件的计算结果。单击"开始"按钮后,"开始日期","结束日期"和"文件名"变量将传递到"订单页面"中的结果面板("结果表面板")。同样,由于"模式页面"也同时调用"ResultTablePanel"和"SearchConditionPanel",因此它应该有自己的"开始日期","结束日期"和"文件名"变量(请注意,它们可以与"订单页面"中的变量相同或不同),并且它自己的结果显示在"ResultTablePanel"中。

提前感谢您抽出宝贵时间查看和回答我的问题。

==================================================================================================================================================================================================================================================

谢谢你们的帮助,我已经使用 PubSub 和 .parent 方法组合起来了。我附上了我的解决方案代码,如下所示:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import datetime, time
import wx, sys, wx.grid
import xlrd
import pandas as pd
import numpy as np
import wx.lib.scrolledpanel as scrolled
EVEN_ROW_COLOUR = '#CCE6FF'
GRID_LINE_COLOUR = '#ccc'
import pandas as pd
import numpy as np
from wx.lib.pubsub import pub 
class ResultTable(wx.grid.PyGridTableBase):
def __init__(self, data=None):
wx.grid.PyGridTableBase.__init__(self)
self.data = data
self.odd=wx.grid.GridCellAttr()
self.odd.SetBackgroundColour("sky blue")
self.odd.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD))
self.even=wx.grid.GridCellAttr()
self.even.SetBackgroundColour("sea green")
self.even.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD))
def GetNumberRows(self):
if self.data.empty:
return 5
else:
return self.data.shape[0]
def GetNumberCols(self):
if self.data.empty:
return 5
else:
return self.data.shape[1]
def GetValue(self, row, col):
if self.data.empty:
return None
else:
return self.data.loc[row][col]
def GetColLabelValue(self, row):
if self.data.empty:
return None
else:
return list(self.data)[row]
def SetValue(self, row, col, value):
pass
def GetAttr(self, row, col, prop):
attr = wx.grid.GridCellAttr()
if row % 2 == 1:
attr.SetBackgroundColour(EVEN_ROW_COLOUR)
return attr
def ResetView(self):
"""Trim/extend the control's rows and update all values"""
self.getGrid().BeginBatch()
for current, new, delmsg, addmsg in [
(self.currentRows, self.GetNumberRows(), wx.grid.GRIDTABLE_NOTIFY_ROWS_DELETED, wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED),
(self.currentColumns, self.GetNumberCols(), wx.grid.GRIDTABLE_NOTIFY_COLS_DELETED, wx.grid.GRIDTABLE_NOTIFY_COLS_APPENDED),
]:
if new < current:
msg = wx.grid.GridTableMessage(
self,
delmsg,
new,    # position
current-new,
)
self.getGrid().ProcessTableMessage(msg)
elif new > current:
msg = wx.grid.GridTableMessage(
self,
addmsg,
new-current
)
self.getGrid().ProcessTableMessage(msg)
self.UpdateValues()
self.getGrid().EndBatch()
# The scroll bars aren't resized (at least on windows)
# Jiggling the size of the window rescales the scrollbars
h,w = grid.GetSize()
grid.SetSize((h+1, w))
grid.SetSize((h, w))
grid.ForceRefresh()
def UpdateValues( self ):
"""Update all displayed values"""
msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_REQUEST_VIEW_GET_VALUES)
self.getGrid().ProcessTableMessage(msg)
class ResultTablePanel(wx.Panel):
def __init__(self, parent, id, page):
wx.Panel.__init__(self, parent, id, style=wx.BORDER_SUNKEN)
self.grid = wx.grid.Grid(self)
self.parent = parent
result = pd.DataFrame({'0' : np.random.randn(100), 'b' : np.random.randn(100), 'c' : np.random.randn(100)})
result = pd.DataFrame()
table = ResultTable(result)
self.grid.SetTable(table)
self.grid.AutoSize()
self.grid.AutoSizeColumns(True)
self.grid.SetGridLineColour(GRID_LINE_COLOUR)
self.grid.EnableDragGridSize( False )
self.grid.SetRowLabelSize( 50 )
self.grid.SetDefaultCellAlignment( wx.ALIGN_CENTRE, wx.ALIGN_CENTRE )
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.grid, 1, wx.ALL|wx.EXPAND)
self.SetSizer(sizer)
pub.subscribe(self.getResult, "panelListener")
def getResult(self, message, page):
"""
This function should get the variables passed by the analysisOrder function,
once the button on the SearchConditionPanel is clicked.
"""
result = pd.DataFrame()
if page == "Order" and self.parent.GetParent().GetParent().page_identifier == "Order":
# For test purpose only
result = pd.DataFrame({'0' : np.random.randn(100), 'b' : np.random.randn(100), 'c' : np.random.randn(100)})  ## For test only
print "Update Order page"
table = ResultTable(result)
self.grid.SetTable(table)
self.Refresh()
if page == "Mode" and self.parent.GetParent().GetParent().page_identifier == "Mode":
result = pd.DataFrame({'0' : np.random.randn(1000), 'b' : np.random.randn(1000)})  ## For test only
print "Update Mode page"
table = ResultTable(result)
self.grid.SetTable(table)
self.Refresh()
else:
pass

class SearchConditionPanel(wx.Panel):
def __init__(self, parent, id, pageID):
wx.Panel.__init__(self, parent, id, style=wx.BORDER_SUNKEN)
# Creat input box for searching time period
nameTitleLable = wx.StaticText(self,-1, label=u"File Name:")
self.fileNameInput = wx.TextCtrl(self,-1, "20170310221612")
dateTitleLable = wx.StaticText(self,-1, label=u"Date range:")
yearLable1 = wx.StaticText(self, label=u"Year:")
monthLable1 = wx.StaticText(self,-1, label=u"Month:")
dayLable1 = wx.StaticText(self,-1, label=u"Day:")
yearLable2 = wx.StaticText(self,-1, label=u"Year:")
monthLable2 = wx.StaticText(self,-1, label=u"Month:")
dayLable2 = wx.StaticText(self,-1, label=u"Day:")
startLable = wx.StaticText(self,-1, label=u"Start Date:")
endLable = wx.StaticText(self,-1, label=u"End Date:")
self.startYearInput = wx.TextCtrl(self,1, "2016")
self.startMonthInput = wx.TextCtrl(self,-1, "10")
self.startDayInput = wx.TextCtrl(self,-1, "30")
self.endYearInput = wx.TextCtrl(self,-1, "2017")
self.endMonthInput = wx.TextCtrl(self,-1, "11")
self.endDayInput = wx.TextCtrl(self,-1, "22")
self.analysisButton = wx.Button(self, -1, label = u'Start')
exportButton = wx.Button(self, -1, label = u'Export')
exportButton.Disable()
## Set up overall layout for the panel
hbox = wx.BoxSizer(wx.HORIZONTAL)
vbox_File_button = wx.BoxSizer(wx.VERTICAL)
hbox_file = wx.BoxSizer(wx.HORIZONTAL)
vbox_date = wx.BoxSizer(wx.VERTICAL)
hbox_button = wx.BoxSizer(wx.HORIZONTAL)
hbox_startDate = wx.BoxSizer(wx.HORIZONTAL)
hbox_endDate = wx.BoxSizer(wx.HORIZONTAL)
hbox.Add(vbox_date, 0, wx.ALIGN_LEFT | wx.ALL, 5)
hbox.Add(wx.StaticLine(self, style=wx.LI_VERTICAL), 0, wx.ALL | wx.EXPAND, 5)
hbox.Add(vbox_File_button, 0, wx.ALIGN_LEFT | wx.ALL, 5)
## Setup the layout for the right side
vbox_File_button.Add(hbox_file, 0, wx.ALIGN_LEFT | wx.ALL, 5)
vbox_File_button.Add(wx.StaticLine(self), 0, wx.ALL | wx.EXPAND, 5)
vbox_File_button.Add(hbox_button, 0, wx.ALIGN_LEFT | wx.ALL, 5)
hbox_file.Add(nameTitleLable, 0, wx.TOP | wx.LEFT | wx.BOTTOM, 10)
hbox_file.Add(self.fileNameInput, 0, wx.ALL | wx.EXPAND, 5)
hbox_button.Add(self.analysisButton, 1, wx.TOP | wx.LEFT, 10)
hbox_button.Add(exportButton, 1, wx.TOP | wx.LEFT, 10)
## Setup the layout for the left side
vbox_date.Add(dateTitleLable, 0, wx.ALL, 5)
vbox_date.Add(hbox_startDate, 0, wx.ALL | wx.EXPAND, 5)
vbox_date.Add(hbox_endDate, 0, wx.ALL | wx.EXPAND, 5)
hbox_startDate.Add(startLable, 0, wx.ALL, 5)
hbox_startDate.Add(yearLable1, 0, wx.TOP | wx.LEFT | wx.BOTTOM, 5)
hbox_startDate.Add(self.startYearInput, 0, wx.ALL, 5)
hbox_startDate.Add(monthLable1, 0, wx.TOP | wx.LEFT | wx.BOTTOM, 5)
hbox_startDate.Add(self.startMonthInput, 0, wx.ALL|wx.EXPAND, 5)
hbox_startDate.Add(dayLable1, 0, wx.TOP | wx.LEFT | wx.BOTTOM, 5)
hbox_startDate.Add(self.startDayInput, 0, wx.ALL|wx.EXPAND, 5)
hbox_endDate.Add(endLable, 0, wx.LEFT | wx.RIGHT, 5)
hbox_endDate.Add(yearLable2, 0, wx.LEFT, 5)
hbox_endDate.Add(self.endYearInput, 0, wx.LEFT | wx.RIGHT, 5)
hbox_endDate.Add(monthLable2, 0, wx.LEFT, 5)
hbox_endDate.Add(self.endMonthInput, 0, wx.LEFT | wx.RIGHT, 5)
hbox_endDate.Add(dayLable2, 0, wx.LEFT, 5)
hbox_endDate.Add(self.endDayInput, 0, wx.LEFT, 5)
self.SetSizer(hbox)
self.Bind(wx.EVT_BUTTON, self.analysisOrder, id=self.analysisButton.GetId())
self.page_ID = pageID
def analysisOrder(self,e):
fileName_temp = self.fileNameInput.GetValue().strip()
fileName = fileName_temp + '.xls'
start_date = self.startYearInput.GetValue().strip() + '-' + self.startMonthInput.GetValue().strip() + '-' + self.startDayInput.GetValue().strip()
end_date = self.endYearInput.GetValue().strip() + '-' + self.endMonthInput.GetValue().strip() + '-' + self.endDayInput.GetValue().strip()
print "analysis order button called"
pub.sendMessage("panelListener", message=fileName, page = self.page_ID)
return fileName, start_date, end_date

class ResultNotebook(wx.Panel):
def __init__(self, parent, pageID):
wx.Panel.__init__(self, parent)
# Creat notebooks for window layout
result_notebook = wx.Notebook(self)
self.data_page = ResultTablePanel(result_notebook, -1, page = pageID)
result_notebook.AddPage(self.data_page, u"Display Data")
# Set up a boxsizer for the tabs
result_notebook_sizer = wx.BoxSizer(wx.HORIZONTAL)
result_notebook_sizer.Add(result_notebook, 1, wx.EXPAND)
self.SetSizer(result_notebook_sizer)
class ModePage(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.page_identifier = "Mode"
# Localize all the panels
self.topPanel = SearchConditionPanel(self, -1, pageID = "Mode")
self.botPanel = ResultNotebook(self, pageID = "Mode")
#Set up the panels, align and position them in the right place
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(self.topPanel, 0, wx.EXPAND | wx.ALL, 5)
vbox.Add(self.botPanel, -1, wx.EXPAND | wx.ALL, 5)
self.SetSizer(vbox)
self.Centre()
self.Show(True)

class FreqPage(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
# t = wx.StaticText(self, -1, "This is a Frequency Page object", (20,20))
# Localize all the panels
topPanel = SearchConditionPanel(self, -1, pageID = "Frequency")
t = wx.StaticText(self, -1, "This is a Frequency Page object")
#Set up the panels, align and position them in the right place
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(topPanel, 0, wx.EXPAND | wx.ALL, 5)
vbox.Add(t, -1, wx.EXPAND | wx.ALL, 5)
self.SetSizer(vbox)
self.Centre()
self.Show(True)
class OrderPage(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.page_identifier = "Order"
# Localize all the panels
self.topPanel = SearchConditionPanel(self, -1, pageID = "Order")
self.botPanel = ResultNotebook(self, pageID = "Order")
#Set up the panels, align and position them in the right place
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(self.topPanel, 0, wx.EXPAND | wx.ALL, 5)
vbox.Add(self.botPanel, -1, wx.EXPAND | wx.ALL, 5)
self.SetSizer(vbox)
self.Centre()
self.Show(True)

class ShopPage(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
# Creat notebooks for window layout
shop_notebook = wx.Notebook(self)
mode_page = ModePage(shop_notebook)
freq_page = FreqPage(shop_notebook)
shop_notebook.AddPage(mode_page, u"Mode Analysis")
shop_notebook.AddPage(freq_page, u"Frequency Analysis")
# Set up a boxsizer for the tabs
shop_page_sizer = wx.BoxSizer(wx.HORIZONTAL)
shop_page_sizer.Add(shop_notebook, 1, wx.EXPAND)
self.SetSizer(shop_page_sizer)
##**----------------------------------------------------------------------------------**##
##**-------------- Create a windows to display the entire system ---------------------**##    
class OrderAnalysis(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(1024, 576))
# self.Maximize(True)  # Default display to be maximized
panel = wx.Panel(self, -1)
# Creat notebooks for window layout
main_notebook = wx.Notebook(panel, style=wx.NB_LEFT)
main_notebook.SetFont(wx.Font(10, wx.FONTFAMILY_DEFAULT,
wx.FONTWEIGHT_NORMAL, 
wx.FONTSTYLE_NORMAL))
# create the page windows as children of the notebook
order_page = OrderPage(main_notebook)
shop_page = ShopPage(main_notebook)
# add the pages to the notebook with the label to show on the tab
main_notebook.AddPage(order_page, u"Order Analysis")
main_notebook.AddPage(shop_page, u"Shop Analysis")

# finally, put the notebook in a sizer for the panel to manage
# the layout
sizer = wx.BoxSizer()
sizer.Add(main_notebook, 1, wx.EXPAND)
panel.SetSizer(sizer)

self.Centre()
self.Show(True)

if __name__ == "__main__":
app = wx.App()
OrderAnalysis(None, -1, 'Order Info Analyser')
app.MainLoop()

再次感谢大家!非常感谢。

我通常建议使用Pubsub来做这种事情。它非常易于实现,并且可以轻松地将消息传递给一个或多个收件人(面板)。

下面是一个简单的示例:

import wx
from wx.lib.pubsub import pub 

class OtherFrame(wx.Frame):
""""""
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, wx.ID_ANY, "Secondary Frame")
panel = wx.Panel(self)
msg = "Enter a Message to send to the main frame"
instructions = wx.StaticText(panel, label=msg)
self.msgTxt = wx.TextCtrl(panel, value="")
closeBtn = wx.Button(panel, label="Send and Close")
closeBtn.Bind(wx.EVT_BUTTON, self.onSendAndClose)
sizer = wx.BoxSizer(wx.VERTICAL)
flags = wx.ALL|wx.CENTER
sizer.Add(instructions, 0, flags, 5)
sizer.Add(self.msgTxt, 0, flags, 5)
sizer.Add(closeBtn, 0, flags, 5)
panel.SetSizer(sizer)
def onSendAndClose(self, event):
"""
Send a message and close frame
"""
msg = self.msgTxt.GetValue()
pub.sendMessage("panelListener", message=msg)
pub.sendMessage("panelListener", message="test2", arg2="2nd argument!")
self.Close()

class MyPanel(wx.Panel):
""""""
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent)
pub.subscribe(self.myListener, "panelListener")
btn = wx.Button(self, label="Open Frame")
btn.Bind(wx.EVT_BUTTON, self.onOpenFrame)
def myListener(self, message, arg2=None):
"""
Listener function
"""
print "Received the following message: " + message
if arg2:
print "Received another arguments: " + str(arg2)
def onOpenFrame(self, event):
"""
Opens secondary frame
"""
frame = OtherFrame()
frame.Show()

class MyFrame(wx.Frame):
""""""
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, title="PubSub Tutorial")
panel = MyPanel(self)
self.Show()

if __name__ == "__main__":
app = wx.App(False)
frame = MyFrame()
app.MainLoop()

以下是一些其他信息:

  • https://wxpython.org/Phoenix/docs/html/wx.lib.pubsub.html
  • https://www.blog.pythonlibrary.org/2013/09/05/wxpython-2-9-and-the-newer-pubsub-api-a-simple-tutorial/

你提到了三种传递信息的方式,但我不得不承认我不明白你在说什么(我已经写了很多wxWidget应用程序)。 处理所描述情况的一种方法是让事件处理程序调用父类中的函数,然后父类可以将信息中继到其他函数/类。 示意图:

class A:
def __init__(self):
B(self)
self.c = C(self)
def a_function(self, *data):
# do something with the data 
# you can pass the information to class C here
class B:
def __init__(self, parent):
self.parent = parent
def an_event_handler(self):
data = something
self.parent.a_function(data)
# or use wx.CallAfter for later execution
class C:
pass

另一种解决方案是 MVC 概念,其中事件处理程序将其信息传递给模型类,该模型类存储它或进一步处理它。 此模型类可以引发自定义 wx 事件,然后 UI 的组件可以根据需要处理该事件以重绘任何受影响的小组件。

最新更新