0

I wrote a python GUI program consisting of two separate files; One is for logic code and the other for GUI using PyQt4. The behaviour of some objects (buttons, text fields ...) changes throughout the code and I need to reset everything to its original status by clicking on a QAction class menu item. How can I do that?

EDIT: the function that supposed to reset the GUI to the original status:

def newSession(self):
        self.ui.setupUi(self)
        self.filename = ""
        self.paramsSplitted = []
        self.timestep = None
        self.index = None
        self.selectedParam = None
        self.selectedMethod = None

        --Snip--
gnome
  • 573
  • 1
  • 6
  • 19
  • May be you can look it here : https://stackoverflow.com/questions/4528347/clear-all-widgets-in-a-layout-in-pyqt – nanithehaddock Nov 08 '17 at 11:02
  • @nanithehaddock: I checked the link but it discussed about deleting widgets not resetting them. – gnome Nov 08 '17 at 11:06
  • Did you use Qt Designer for generating your GUI? If you did so, your main class of the GUI has the method `self.setupUi`. You could connect the signal `triggered` of the QAcion to this method. Then the GUI will be set to the initial state. I did not check that - so no guarantee... – Sven-Eric Krüger Nov 08 '17 at 13:06
  • @Sven: Yes I used Qt Designer and it has self.seupUi method. I also tried your suggestion before but the problem is that one of buttons that opens a QFileDialog does nothing after calling it again through a function. I edited my post and added the section regarding the procedure. any idea? – gnome Nov 08 '17 at 14:31
  • @gnome. You shouldn't call `setupUi` in `newSession`, because it will recreate all the widgets, layouts, etc and disconnect all your signals. The `setupUi` should go in `__init__`, along with all the signal connections and any other initialisation that you only want to execute *once*, when the application starts. The `newSession` method should then only contain whatever is needed to reset state variables and put the relevant widgets back to their starting state. This method should be called at the end of `__init__`, and then whenever you need to reset the gui. – ekhumoro Nov 08 '17 at 14:45
  • @ekhumoro: Good point at the signal connection. @gnome: Try to wrap the standard signal connections done in the constructor in an explicit function and call that in `newSession` as well as in the constructor. Together with a function which disconnects all signals. That might produce shorter code than calling all widgets and put them to the initial state "manually". – Sven-Eric Krüger Nov 09 '17 at 10:26
  • @SvenKrüger: Would you please tell me exactly how to do that? I mean in a schematic way. – gnome Nov 11 '17 at 08:28

2 Answers2

0

What you could do:

  • Define a ResetHandler(QtCore.QObject) object with a reset_everything signal
  • During startup create an instance and set it on the globally available QApplication like qapplication.reset_handler = ResetHandler()
  • Every UI element that needs to update itself defines a on_reset_everything_triggered() slot. (Optional: You could also just use update for example).
  • When You create UI elements that are supposed to update, connect them to the globally available reset_everything signal from the handler on the QApplication.
  • Connect your QAction.triggered with the ResetHandler.reset_everything signal.
  • Now every time you press the QAction the reset_everything signal is invoked, and all UI elements that you connected will update themself.
timmwagener
  • 2,368
  • 2
  • 19
  • 27
  • Is it the easiest way? I'm not so good at Python programming, would you please tell me how to convert these steps into lines of code? – gnome Nov 08 '17 at 11:39
0

Like you requested in your comment here is a schematic way of utilizing a function to connect all signals and the method setupUi.

class MainWindow(QtGui.QMainWindow) :
    def __init__(self) :
        QtGui.QMainWindow.__init__(self)
        self.ui.setupUi(self)

        # Some code

        self.connectAllSignals()

    def connectAllSignals(self) :
        self.someWidget.clicked.connect(self.someFunction)
        self.someAction.triggered.connect(self.otherFunction)

        # All the other signals

    def disconnectAllSignals(self) :
        try :
            self.someWidget.clicked.disconnect()
            self.someAction.triggered.disconnect()

            # All the other signals

        except :
            print("Something went wrong. Check your code.")
            pass

    def newSession(self) :
        self.ui.setupUi(self)
        self.disconnectAllSignals()
        self.connectAllSignals()

        # Do whatever it takes

By this you ensure you have only the initial settings for your signals and all dynamically added connections are broken. In the method disconnectAllSignals be sure all widgets exist and all signals have at least one connection by the time you call it. If you have new widgets invoked dynamically you should consider deleting them in th method newSession after calling connectAllSignals.

Sven-Eric Krüger
  • 1,277
  • 12
  • 19
  • Don't call `setupUi()`. What this function does is create the widget tree. Since PyQt has Qt C++ underneath this would mean that you will be allocating more and more memory every time a new session is created (just to make sure test with Valgrind if you are on Linux or the alternative for Windows/MacOS). Even if this doesn't happen and you just recreate the existing widget tree by disposing of the previous one it's still very poor from a performance standpoint. – rbaleksandar Nov 14 '17 at 11:23