Многоокно PySide, заставить работать QStackWidget

Мне нужно создать многооконный графический интерфейс, сначала я попробовал его с QWidgets, но, наконец, я обнаружил инструмент QStackWidget, который мне нужно использовать. Так что я пытаюсь, но у меня есть некоторые проблемы. Спасибо за ваше время.

class MainWindow(QMainWindow):

    def __init__(self):

        super(MainWindow,self).__init__()

        self.mainWidget = MainWidget()
        self.searchWidget = SearchWidget()
        self.sWidget = QStackedWidget()
        self.sWidget.addWidget(self.mainWidget)
        self.sWidget.addWidget(self.searchWidget)

        self.initUI() 

и вызов setCurrentWidget из класса sub_widget:

class MainWidget(QWidget):

    def __init__(self, parent=MainWindow):

        super(MainWidget,self).__init__()
        self.initUI()

    def initUI(self):

        searchButton = QPushButton('searchButton',self)
        optionButton = QPushButton('optionButton',self)
        quitButton = QPushButton('quitButton',self)
        listButton = QPushButton('listButton',self)

        searchButton.clicked.connect(self.goSearch)

        hbox = QHBoxLayout()
        hbox.addWidget(listButton)
        hbox.addWidget(quitButton)

        vbox = QVBoxLayout()
        vbox.addStretch(1)
        vbox.addWidget(searchButton)
        vbox.addWidget(optionButton)
        vbox.addLayout(hbox)

        self.setLayout(vbox)

    def goSearch(self):
        self.parent().sWidget.setCurrentWidget(self.parent().searchWidget)

Я получил это сообщение от IDE:

  self.parent().sWidget.setCurrentWidget(self.parent().searchWidget)
  AttributeError: 'PySide.QtGui.QStackedWidget' object has no attribute 'sWidget'

Что я делаю неправильно?

2 ответа

Решение

Я собираюсь прокомментировать код, который вы разместили здесь: http://pastebin.com/fBfS1X5m

Важно знать, что вы можете размещать виджеты внутри виджетов и так далее. Например:

class Widget(QWidget):
    def __init__(self, parent=None):
        layout = QVBoxLayout(self)
        childWidget = QWidget(parent=self)
        layout.addWidget(childWidget)

Просто быстрое примечание: вам не нужно setLayout если вы пройдете self в основной конструктор макетов - через документы.

В любом случае, я пытаюсь проиллюстрировать, что QStackedWidget и SearchWidget на самом деле не должно быть частью MainWindow, но должен жить внутри собственного соответствующего виджета, который будет обрабатывать переключение между QStackedWidget страницы.

Например, MainWindow.__init__ будет выглядеть только так:

class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()

        self.mainWidget = MainWidget(self)
        self.setCentralWidget(self.mainWidget)

        self.initUI()

Ваш MainWidget будет выглядеть примерно так:

class MainWidget(QtGui.QWidget):
    ...

    def initUI(self):
        ...

        self.stack = QtGui.QStackedWidget(parent=self)

        self.searchWidget = SearchWidget(parent=self)
        self.searchWidget.searchButton.clicked.connect(self.goSearch)
        self.backWidget = BackWidget(parent=self)
        self.backWidget.backButton.clicked.connect(self.goBack)

        ...

    def goSearch(self):
        self.stack.setCurrentWidget(self.backWidget)

    def goBack(self):
        self.stack.setCurrentWidget(self.searchWidget)

Я переименовал некоторые имена классов, чтобы сделать их более понятными (по крайней мере, для меня). SearchWidget был твой старый MainWidget, BackWidget был твой старый SearchWidget, После этих изменений SearchWidget будет выглядеть так же, как ваш старый MainWidget с одним исключением - мы сохраняем ссылку на кнопку поиска, чтобы получить к ней доступ в MainWidget класс, как видно выше (когда мы подключаем их сигналы к нашим слотам). Мы делаем то же самое для кнопки в BackWidget,

Два переименованных "дочерних" виджета:

class SearchWidget(QtGui.QWidget):
    ...

    def initUI(self):
        self.searchButton = QtGui.QPushButton('searchButton', parent=self)
        optionButton = QtGui.QPushButton('optionButton', parent=self)
        quitButton = QtGui.QPushButton('quitButton', parent=self)
        listButton = QtGui.QPushButton('listButton', parent=self)

        vbox = QtGui.QVBoxLayout(self)
        vbox.addStretch(1)
        vbox.addWidget(self.searchButton)
        vbox.addWidget(optionButton)

        hbox = QtGui.QHBoxLayout()
        hbox.addWidget(listButton)
        hbox.addWidget(quitButton)

        vbox.addLayout(hbox)

class BackWidget(QtGui.QWidget):
    ...

    def initUI(self):
        self.backButton = QtGui.QPushButton('GoBack', parent=self)

Так что теперь у нас есть что-то вроде:

MainWindow  
   |---MainWidget  
          |---QStackedWidget  
                 |---SearchWidget  
                 |---BackWidget  

Вы можете найти полный рабочий код здесь.

Эта строка:

    def __init__(self, parent=MainWindow):

устанавливает MainWindow Класс в качестве аргумента по умолчанию, когда вам действительно нужен экземпляр. Но даже если это был экземпляр, в следующей строке вы также не можете передать его в базовый класс:

    super(MainWidget,self).__init__()

Вместо этого вам нужно сделать что-то вроде этого:

class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow,self).__init__()
        # pass an instance of MainWindow here
        self.mainWidget = MainWidget(self)
        ...

class MainWidget(QWidget):
    def __init__(self, parent):
        # pass the parent to the base-class
        super(MainWidget, self).__init__(parent)
        ...

ОБНОВЛЕНИЕ:

Стек-виджет будет переопределять любые добавленные в него виджеты, чтобы он стал родительским. Есть способы обойти это, но я думаю, что реальная проблема с вашим кодом в том, что у вас есть структура в обратном направлении. Кнопки, которые устанавливают текущий виджет, должны управляться главным окном, и виджеты в стеке должны работать независимо от этого.

Другие вопросы по тегам