【问题标题】:pass information among panels in wxpython在 wxpython 中的面板之间传递信息
【发布时间】:2018-01-12 00:37:57
【问题描述】:

我有一个非常复杂的 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”)。同样,由于“模式页面”也调用了“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()

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

【问题讨论】:

  • 将您的代码编辑到相关部分,这样您就不会冒着压死无辜旁观者的风险。
  • 我也不明白你在问什么....试着解释得更好?即 searchcondition 面板中有 50 项内容……您如何处理其他输入? ....(顺便说一句,我认为有一个 wx.DatePickerCtrl)
  • 嗨,我已经修改了我的代码(函数“ResultTablePanel”和“analysisOrder”),以及我的最后一段,希望这会让我的问题更清楚。由于我有不同笔记本的不同页面导入的“ResultTablePanel”和“SearchConditionPanel”,我的问题是如何在笔记本的任何特定页面中将变量从“SearchConditionPanel”传递到“ResultTablePanel”。谢谢。

标签: python python-2.7 wxpython


【解决方案1】:

我通常建议使用 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()

这里有一些额外的信息:

【讨论】:

  • Mike 可能是世界上最了解 wxPython 的人(包括 Robin Dunn:P(尽管我确信 Robin 对实现细节了解更多:P)我会听他的话
  • 哈哈!罗宾比我知道得多。他拥有广博的记忆力,几乎可以回答我当场问他的任何问题。
  • 嗨,迈克,它就像魔术一样工作,除了我要解决的一个问题:如果我有一个面板被笔记本中的不同页面调用,我该怎么做面板为不同的页面显示不同的东西?或者我应该为每个页面创建面板?例如,在我的示例中,“ResultTablePanel”和“SearchConditionPanel”是笔记本所有页面调用的两个面板,但每个页面都有自己的条件从“SearchConditionPanel”传递到“ResultTablePanel”。我不知道如何使这项工作。谢谢。
  • 为什么不修改您的 SearchConditionPanel 以采用附加参数,即关联的 ResultTablePanel。然后在事件处理程序中,您可以直接调用 ResultTablePanel 中的函数。
  • 您可以使用 pubsub 传递整个对象,或者只是传递某种参数,告诉您的代码显示不同的页面或其他内容。
【解决方案2】:

你提到了三种传递信息的方式,但我不得不承认我不明白你在说什么(而且我写了很多 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 的组件可以根据需要处理这些事件以重绘任何受影响的小部件。

【讨论】:

  • 我也写了很多wx程序,但不明白问题是什么:P
  • 也可能值得一提 wx.lib.pubsub(虽然自定义事件大部分涵盖了这一点)+1
  • 嗨,我已经修改了我的代码(函数“ResultTablePanel”和“analysisOrder”),以及我的最后一段,希望这会让我的问题更清楚。由于我有不同笔记本的不同页面导入的“ResultTablePanel”和“SearchConditionPanel”,我的问题是如何在笔记本的任何特定页面中将变量从“SearchConditionPanel”传递到“ResultTablePanel”。对于我提到的 3 种方式,一种方式是调用其父类。另一种方法是使用 event.GetId() 检查 event_ID。我所说的第三种方式是 wx.lib.pubsub。我很困惑如何使用它们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-24
  • 2012-01-25
  • 1970-01-01
相关资源
最近更新 更多