Sharing variable between QWizard pages in Pyside/P

2019-05-10 20:30发布

问题:

I am building a QWidget in PySide, and running into an issue when trying to share data between pages.

To summarize I utilize user inputs from earlier pages to construct a list of custom objects, which I need to share with the following page.

At the beginning of my code I construct a custom object, with an attribute called .name (among other attributes)

class MyCustomClass():

    def __init__(self, name, other_attributes)
        self.name = name

        ...set other attributes

In my QWizard I open a file and make a list of names to match with another list of MyCustomClass objects. I then display the names alongside the matched name of the corresponding MyCustomClass object and prompt the user to confirm (or change), before moving to the next page.

Each match is stored as a tuple(name, MyCustomClass) and added to a list. I then wish to read this list from the next page in order to perform more operations. I'm trying to use .registerField, but I'm unsure of how to properly do so. My attempt is below.

First I make a QWizardPage, perform some code and then construct my matches. I made a function to return the value and used this for the .registerField

class ConfirmMatches(QWizardPage):

    def __init__(self):
        ...

    def initializePage(self):

        # Code to make display and operations and make list of matches
        ...
        self.matches = matches

        self.registerField("matches", self, "get_matches")

    def get_matches(self):
        return self.matches

Then from my next page, I try to call the field, but I only return a None object.

class NextPage(QWizardPage):

    def __init__(self):
        ...

    def initializePage(self):

        # Get relevant fields from past pages

        past_matches = self.field("matches")

type(past_matches) is None, even though when I print self.matches in the previous page it clearly displays them all.

  1. What am I doing wrong with the registerField?

  2. Is there an easier way to share this type of data between pages?

回答1:

If you want to explicitly set the value of the field matches in your ConfirmMatches page, you would need to do one of a few things:

  1. Make an explicit call to self.setField any time your matches change.
  2. Emit a signal every time your matches are changed after registering the property
  3. Store your matches in one of the standard Qt inputs, like QLineEdit, and use that widget in the registerField call.

If you check the docs for QWizardPage.registerField, what it does is register to grab the named property of the passed in widget when the widget's signal is emitted. The way your code is now, you would need to add a signal to your ConfirmMatches page that would be emitted whenever your matches variable changes. Otherwise, your page doesn't know when the field should be updated.



回答2:

I actually solved it myself. I was on the right track, just missing a few things, but I'll catalog here for anyone else with similar problems.

Like I said I have a list of matched objects, where each match is a list of a name, and the object that was found to correspond to that name, i.e. match = [name, MyCustomClass]

class ConfirmMatches(QWizardPage):

   # Function to change list
   def setList(self, new_list):

       self.list_val = new_list

       if self.list_val != []:
           self.list_changed.emit()

   # Function to return list
   def readList(self):

       return self.list_val

   def __init__(self):

       self.list_val = [] # Create initial value

       # Code to initialize displays/buttons, and generate matches
       ...

       # Here I assign the matches I made "matches", to the QProperty "match_list"
       self.setList(matches)

       # Then register field here.
       # Instead of the read function, I call the object itself (not sure why, but it works)
       self.registerField("registered_list", self, "match_list")

   # Define "match_list" as a QProperty with read and write functions, and a signal (not used)
   match_list = Property(list, readList, setList)
   listChanged = Signal()            

I made the list a QProperty and wrote the Read and Write functions, as well as a Signal (not used). Then, when registering the field, instead of putting the Read function (readList), I put the QProperty itself (match_list). Not sure why it works, but this conceivable could be used to register other custom objects.