3
votes

I have a main Window derived form QMainWindow that may show different Widgets, depending on the task at hand.

I created a simplified example below:

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys


class MainWindow(QMainWindow):

    def __init__(self, parent=None):
        '''
        Constructor
        '''
        QMainWindow.__init__(self, parent)
        self.central_widget = QStackedWidget()
        self.setCentralWidget(self.central_widget)
        self.start_screen = Start(self)
        self.second_screen = Second(self)
        self.central_widget.addWidget(self.start_screen)
        self.central_widget.addWidget(self.second_screen)
        self.central_widget.setCurrentWidget(self.start_screen)



class Start(QWidget):

    def __init__(self, parent=None):
        super(Start, self).__init__(parent)
        layout = QHBoxLayout()
        button = QPushButton(text=QString('Push me!'))
        layout.addWidget(button)
        self.setLayout(layout)
        self.connect(button, SIGNAL("clicked()"), self.change_widget)

    def change_widget(self):
        self.parent().setCurrentWidget(
            self.parent().parent().second_screen)


class Second(QWidget):

    def __init__(self, parent=None):
        super(Second, self).__init__(parent)
        layout = QHBoxLayout()
        button = QPushButton(text=QString('Back to Start!'))
        layout.addWidget(button)
        self.setLayout(layout)
        self.connect(button, SIGNAL("clicked()"), self.change_widget)

    def change_widget(self):
        self.parent().setCurrentWidget(
            self.parent().parent().start_screen)

app = QApplication(sys.argv)
myWindow = MainWindow(None)
myWindow.show()
app.exec_()

This toggles between two different central widgets, nevertheless I found the handling with parent() functions tedious, and I'd like to know if there is a better method to organise the widgets.

The setCurrentWidget method will probably be always accessible with one parent() statement, but if for any reasons the hierarchy-depth changes, is there a better method to access the QMainWindow than parent().parent()? Or would I just re-create the Widget every time a button is clicked (I assume, if this would be a widget with data-Input possibilities, these data would be lost, which is annoying).

I appreciate any suggestions for improvement.

1

1 Answers

4
votes

You should be using Signals. This allows any parent hierarchy and the child widgets don't have to have any knowledge of how they're being used or what order they're being displayed in. The main widget handles it all.

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys


class MainWindow(QMainWindow):

    def __init__(self, parent=None):
        '''
        Constructor
        '''
        QMainWindow.__init__(self, parent)
        self.central_widget = QStackedWidget()
        self.setCentralWidget(self.central_widget)
        self.start_screen = Start(self)
        self.second_screen = Second(self)
        self.central_widget.addWidget(self.start_screen)
        self.central_widget.addWidget(self.second_screen)
        self.central_widget.setCurrentWidget(self.start_screen)

        self.start_screen.clicked.connect(lambda: self.central_widget.setCurrentWidget(self.second_screen))
        self.second_screen.clicked.connect(lambda: self.central_widget.setCurrentWidget(self.start_screen))



class Start(QWidget):

    clicked = pyqtSignal()

    def __init__(self, parent=None):
        super(Start, self).__init__(parent)
        layout = QHBoxLayout()
        button = QPushButton(text=QString('Push me!'))
        layout.addWidget(button)
        self.setLayout(layout)
        button.clicked.connect(self.clicked.emit)


class Second(QWidget):

    clicked = pyqtSignal()

    def __init__(self, parent=None):
        super(Second, self).__init__(parent)
        layout = QHBoxLayout()
        button = QPushButton(text=QString('Back to Start!'))
        layout.addWidget(button)
        self.setLayout(layout)
        button.clicked.connect(self.clicked.emit)


app = QApplication(sys.argv)
myWindow = MainWindow(None)
myWindow.show()
app.exec_()