Многоокно 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)
...
ОБНОВЛЕНИЕ:
Стек-виджет будет переопределять любые добавленные в него виджеты, чтобы он стал родительским. Есть способы обойти это, но я думаю, что реальная проблема с вашим кодом в том, что у вас есть структура в обратном направлении. Кнопки, которые устанавливают текущий виджет, должны управляться главным окном, и виджеты в стеке должны работать независимо от этого.