문제

I have a wizard created using PyWizardPage. It starts with a main page, and then the user is brought through several more pages asking him for input information. On one of these pages, I've created a Browse button which ask the user to select a file. Then, on the next page, I have a "Verify Details" thing which displays a box containing all the inputs that the user selected through the Wizard and asks him to make sure that the information is correct before continuing.

My problem is, I can't get any of the user input on previous pages to be passed into my "Verify Details" page.

For my setup, I have a WizardPage class that I call to create each page in my wizard.

mywizard.py

import wx
import wx.wizard

class WizardPage(wx.wizard.PyWizardPage):
    def __init__(self, parent, title):
        wx.wizard.PyWizardPage.__init__(self, parent)
        self.next = None
        self.prev = None
        self.initializeUI(title)

    def initializeUI(self, title):      
        # create grid layout manager    
        self.sizer = wx.GridBagSizer()
        self.SetSizerAndFit(self.sizer)

    def addWidget(self, widget, pos, span): 
        self.sizer.Add(widget, pos, span, wx.EXPAND)

    # getters and setters 
    def SetPrev(self, prev):
        self.prev = prev

    def SetNext(self, next):
        self.next = next

    def GetPrev(self):
        return self.prev

    def GetNext(self):
        return self.next

Then, in a separate file, I have a function to create each page. The function for the first page calls the functions to create the other pages. I also use helper functions called "browse1" and "browse2" to open a wx.FileDialog and such.

pages.py

import wx
from mywizard import * 

#### HELPER FUNCTIONS ####
def browse1(event, parent_page):
    wildcards = ...
    dlg = wx.FileDialog(parent_page, "Blahblah", "", "",
                            wildcards, wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)

    if dlg.ShowModal() == wx.ID_OK:
        global x1
        global bro1
        x1.SetValue(dlg.GetDirectory() + "\\" + dlg.GetFilename())
        bro1 = x1.GetValue()

def browse2(event, parent_page):
    wildcards = ...
    dlg = wx.FileDialog(parent_page, "Select new certificate", "", "",
                            wildcards, wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)

    if dlg.ShowModal() == wx.ID_OK:
        global x2
        global bro2
        x2.SetValue(dlg.GetDirectory() + "\\" + dlg.GetFilename())
        bro2 = x2.GetValue()

#### END HELPER FUNCTIONS ####

def create_page1(wizard):
    page1 = WizardPage(wizard, "Page 1")
    d = wx.StaticText(...)
    page1.addWidget(d, (2, 1), (1,5))

    page2 = create_update_certs_page2(wizard)
    page3 = create_update_certs_page3(wizard)

    # Set links
    page2.SetPrev(page1)
    page1.SetNext(page2)
    page3.SetPrev(page2)
    page2.SetNext(page3)

    return page1

def create_page2(wizard):
    page2 = WizardPage(wizard, "Page 2")

    b1 = wx.Button(page2, -1, "Browse...", wx.DefaultPosition, (85, 23))
    b1.Bind(wx.EVT_BUTTON, lambda evt: browse1(evt, page2)) 

    global x1
    x1 = wx.TextCtrl(...) # the text area where the Browse path is populated

    b2 = wx.Button(page2, -1, "Browse...", wx.DefaultPosition, (85, 23))
    b2.Bind(wx.EVT_BUTTON, lambda evt: browse2(evt, page2)) 

    global x2
    x2 = wx.TextCtrl(...) # the text area where the Browse path is populated

    page2.addWidget(b1, ..., ...)
    page2.addWidget(b2, ..., ...)
    page2.addWidget(x1, ..., ...)
    page2.addWidget(x2, ..., ...)

    return page2

def create_page3(wizard):
    print "bro1 is" + bro1 # these print empty strings
    print "bro2 is" + bro2 # not, the browse path and file that should be populated

Basically, the x1 and x2 refer to wx.TextCtrl widgets which I made global so I could populate them in the browse1 and browse2 functions. Now, I want to access their populated values in the bro1 and bro2 variables in the create_page3 function but nothing shows up.

And the main code in pages.py is:

app = wx.App(redirect = False)
wizard = wx.wizard.Wizard(None, -1, "Some Title")
wizard.SetPageSize((500, 350))

mypage1 = create_page1(wizard)

# Let's go!
wizard.RunWizard(mypage1)

Any help would be greatly appreciated.

도움이 되었습니까?

해결책

You could pass the values around as msvalkon mentioned. However I think subclassing wx.wizard.Wizard would be simpler. Then you can just create the various widgets inside the class and the their parents to different pages. This allows you to access the variables across pages rather easily. Here's an expansion on the answer I gave to your last question:

import wx
import wx.wizard

class WizardPage(wx.wizard.PyWizardPage):
    def __init__(self, parent, title):
        wx.wizard.PyWizardPage.__init__(self, parent)
        self.next = None
        self.prev = None
        self.initializeUI(title)

    def initializeUI(self, title):      
        # create grid layout manager    
        self.sizer = wx.GridBagSizer()
        self.SetSizerAndFit(self.sizer)

    def addWidget(self, widget, pos, span): 
        self.sizer.Add(widget, pos, span, wx.EXPAND)

    # getters and setters 
    def SetPrev(self, prev):
        self.prev = prev

    def SetNext(self, next):
        self.next = next

    def GetPrev(self):
        return self.prev

    def GetNext(self):
        return self.next

########################################################################
class MyWizard(wx.wizard.Wizard):
    """"""

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.wizard.Wizard.__init__(self, None, -1, "Some Title")
        self.SetPageSize((500, 350))

        mypage1 = self.create_page1()

        forward_btn = self.FindWindowById(wx.ID_FORWARD) 
        forward_btn.Disable()

        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.onUpdate, self.timer)
        self.timer.Start(1)

        self.RunWizard(mypage1)

    #----------------------------------------------------------------------
    def create_page1(self):
        page1 = WizardPage(self, "Page 1")
        d = wx.StaticText(page1, label="test")
        page1.addWidget(d, (2, 1), (1,5))

        self.text1 = wx.TextCtrl(page1)
        page1.addWidget(self.text1, (3,1), (1,5))

        self.text2 = wx.TextCtrl(page1)
        page1.addWidget(self.text2, (4,1), (1,5))

        page2 = WizardPage(self, "Page 2")
        page2.SetName("page2")
        self.text3 = wx.TextCtrl(page2)
        self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.onPageChanged)
        page3 = WizardPage(self, "Page 3")

        # Set links
        page2.SetPrev(page1)
        page1.SetNext(page2)
        page3.SetPrev(page2)
        page2.SetNext(page3)

        return page1

    #----------------------------------------------------------------------
    def onPageChanged(self, event):
        """"""
        page = event.GetPage()
        print
        if page.GetName() == "page2":
            self.text3.SetValue(self.text2.GetValue())

    #----------------------------------------------------------------------
    def onUpdate(self, event):
        """
        Enables the Next button if both text controls have values
        """
        value_one = self.text1.GetValue()
        value_two = self.text2.GetValue()
        if value_one and value_two:
            forward_btn = self.FindWindowById(wx.ID_FORWARD) 
            forward_btn.Enable()
            self.timer.Stop()

#----------------------------------------------------------------------
def main():
    """"""
    wizard = MyWizard()

#----------------------------------------------------------------------
if __name__ == "__main__":
    app = wx.App(False)
    main()
    app.MainLoop()

The idea here is to give each page a unique name and then catch the EVT_WIZARD_PAGE_CHANGED. In the handler, you can check what page you're on and update its contents accordingly.

다른 팁

I'm not entirely sure what the most idiomatic way of doing it is but here's how I've dealt with this previously.

Subclass the wx.wizard.Wizard-class and bind the wx events wx.wizard.EVT_WIZARD_ON_PAGE_CHANGING and wx.wizard.EVT_WIZARD_ON_PAGE_CHANGED to methods of your class which make sure that data is consistently transferred back and forth pages.

The wx.wizard.EVT_WIZARD_ON_PAGE_CHANGING will be triggered when you press next. The method which handles this event is responsible for saving the current pages data.

The wx.wizard.EVT_WIZARD_ON_PAGE_CHANGED will trigger when the page has actually changed. The method which handles this event is responsible for populating the data from the previous page to the current pages fields or do whatever it is that you want to do with it.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top