我有两个按钮( wgtbtnA & wgtbtnB )放在两个不同的页面上( page1 和 page2 ,分别)在父对象内(objectName: stackedWidget )。我的困境是这样的:当我运行代码时,箭头不会显示在PyQt中。为什么?如何从第1页到第2页交替,反之亦然?
这是运行时的图像,它传达了我的要求:
Qt Designer:
我想保留那些小箭头。
以下是我的代码:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'stackedWidget.ui'
#
# Created by: PyQt4 UI code generator 4.11.4
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
import sys
import os
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(512, 304)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.stackedWidget = QtGui.QStackedWidget(self.centralwidget)
self.stackedWidget.setGeometry(QtCore.QRect(150, 60, 161, 121))
self.stackedWidget.setObjectName(_fromUtf8("stackedWidget"))
self.page = QtGui.QWidget()
self.page.setObjectName(_fromUtf8("page"))
self.wgtMainWindow = QtGui.QPushButton(self.page)
self.wgtMainWindow.setGeometry(QtCore.QRect(50, 50, 75, 23))
self.wgtMainWindow.setObjectName(_fromUtf8("wgtMainWindow"))
self.stackedWidget.addWidget(self.page)
self.page_2 = QtGui.QWidget()
self.page_2.setObjectName(_fromUtf8("page_2"))
self.wgtbtnB = QtGui.QPushButton(self.page_2)
self.wgtbtnB.setGeometry(QtCore.QRect(50, 50, 75, 23))
self.wgtbtnB.setObjectName(_fromUtf8("wgtbtnB"))
self.stackedWidget.addWidget(self.page_2)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 512, 21))
self.menubar.setObjectName(_fromUtf8("menubar"))
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(MainWindow)
self.statusbar.setObjectName(_fromUtf8("statusbar"))
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
self.stackedWidget.setCurrentIndex(1)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
self.wgtMainWindow.setText(_translate("MainWindow", "Widget A", None))
self.wgtbtnB.setText(_translate("MainWindow", "Widget B", None))
class ControlMainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(ControlMainWindow, self).__init__(parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
mySW = ControlMainWindow()
mySW.show()
sys.exit(app.exec_())
答案 0 :(得分:2)
您可以使用按钮更改页面:{your QPushButton}.clicked.connect(lambda: {your QStackedWidget}.setCurrentIndex({another page}))
通过示例:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'stackedWidget.ui'
#
# Created by: PyQt4 UI code generator 4.11.4
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
import sys
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(512, 304)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.stackedWidget = QtGui.QStackedWidget(self.centralwidget)
self.stackedWidget.setGeometry(QtCore.QRect(150, 60, 161, 121))
self.stackedWidget.setObjectName(_fromUtf8("stackedWidget"))
self.page = QtGui.QWidget()
self.page.setObjectName(_fromUtf8("page"))
self.wgtMainWindow = QtGui.QPushButton(self.page)
self.wgtMainWindow.setGeometry(QtCore.QRect(50, 50, 75, 23))
self.wgtMainWindow.setObjectName(_fromUtf8("wgtMainWindow"))
self.stackedWidget.addWidget(self.page)
self.page_2 = QtGui.QWidget()
self.page_2.setObjectName(_fromUtf8("page_2"))
self.wgtbtnB = QtGui.QPushButton(self.page_2)
self.wgtbtnB.setGeometry(QtCore.QRect(50, 50, 75, 23))
self.wgtbtnB.setObjectName(_fromUtf8("wgtbtnB"))
self.stackedWidget.addWidget(self.page_2)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 512, 21))
self.menubar.setObjectName(_fromUtf8("menubar"))
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(MainWindow)
self.statusbar.setObjectName(_fromUtf8("statusbar"))
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
self.stackedWidget.setCurrentIndex(1)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
self.wgtMainWindow.setText(_translate("MainWindow", "Widget A", None))
self.wgtbtnB.setText(_translate("MainWindow", "Widget B", None))
class ControlMainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(ControlMainWindow, self).__init__(parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.wgtbtnB.clicked.connect(lambda : self.ui.stackedWidget.setCurrentIndex(0))
self.ui.wgtMainWindow.clicked.connect(lambda : self.ui.stackedWidget.setCurrentIndex(1))
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
mySW = ControlMainWindow()
mySW.show()
sys.exit(app.exec_())
启动应用:
单击按钮后:
点击另一个按钮后:
答案 1 :(得分:1)
您在设计师中看到的两个箭头(在下面的信息中)不会延续到您的应用程序,它是设计师的一项功能,因此您可以轻松地在它们之间切换
答案 2 :(得分:0)
您的ControlMainWindow
课程中没有逻辑可以在您的小部件之间切换。 (我也没有看到任何用于切换的箭头小部件)你需要在主类的QTbuttons
中添加一个监听器,如下所示,以执行你的逻辑:
yourQTbutton.itemClicked.connect(self.functioWithUIchangingLogic)
答案 3 :(得分:0)
要将箭头从一个屏幕实现到另一个屏幕,您只需要传播这些箭头以确保它们出现在每个视图中即可-现在可以通过代码轻松完成此操作,而不必说出设计者的难度。这是一个示例,它可以完成您想要的事情。
from sys import exit as sysExit
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class Win1Disply(QFrame):
def __init__(self, parent):
QFrame.__init__(self)
self.setFrameShape(QFrame.StyledPanel)
self.setLineWidth(0.2)
# -------
self.Cntnr = QVBoxLayout()
self.Cntnr.addWidget(QTextEdit('This is Window 1 with whatever contents you want'))
self.Win1Btn = QPushButton('>>')
self.Win1Btn.clicked.connect(parent.RightArrow)
self.Cntnr.addWidget(self.Win1Btn)
self.Cntnr.addStretch(1)
# -------
self.setLayout(self.Cntnr)
class Win2Disply(QFrame):
def __init__(self, parent):
QFrame.__init__(self)
self.setFrameShape(QFrame.StyledPanel)
self.setLineWidth(0.2)
# -------
self.Cntnr = QVBoxLayout()
self.Cntnr.addWidget(QTextEdit('This is Window 2 with whatever contents you want'))
self.Win1Btn = QPushButton('>>')
self.Win1Btn.clicked.connect(parent.RightArrow)
self.Cntnr.addWidget(self.Win1Btn)
self.Cntnr.addStretch(1)
# -------
self.setLayout(self.Cntnr)
class OptionButtons(QToolButton):
# Class OptionButtons ("Text", Connector) inherits from QToolButton
def __init__(self, Text, Connector):
QToolButton.__init__(self)
self.setText(Text)
self.setStyleSheet("font: bold;color: blue;height: 55px;width: 55px;")
self.setIconSize(QSize(32,32))
self.clicked.connect(Connector)
############################## Settings Class ##############################
class OptionSettings(QDialog):
def __init__(self, parent):
QDialog.__init__(self, parent)
line = QFrame()
line.setFrameShape(QFrame.HLine)
line.setFrameShadow(QFrame.Sunken)
self.btnWin1 = OptionButtons('Win One', self.ShowWindow1)
self.btnWin2 = OptionButtons('Win Two', self.ShowWindow2)
# Vertical Box for Buttons *************************************
self.UpLeft = QVBoxLayout()
self.UpLeft.addWidget(self.btnWin1)
self.UpLeft.addWidget(self.btnWin2)
self.UpLeft.addStretch(1)
# Display Area on Right
# Widget Flip Display ******************************************
self.UpRite = QHBoxLayout()
self.Contents = QStackedWidget()
self.Contents.addWidget(QTextEdit('Nothing Selected'))
self.Contents.addWidget(Win1Disply(self))
self.Contents.addWidget(Win2Disply(self))
self.Contents.addWidget(QTextEdit('Settings Saved'))
self.Contents.setCurrentIndex(0)
self.UpRite.addWidget(self.Contents)
# Button and Display Area on Top
self.Upper = QHBoxLayout()
self.Upper.addLayout(self.UpLeft)
self.Upper.addLayout(self.UpRite)
# Save and Cancel Area on Bottom
self.btnSave = QPushButton("Save")
self.btnSave.clicked.connect(self.SaveSettings)
self.btnCncl = QPushButton("Cancel")
self.btnCncl.clicked.connect(self.close)
self.Lower = QHBoxLayout()
self.Lower.addStretch(1)
self.Lower.addWidget(self.btnSave)
self.Lower.addWidget(self.btnCncl)
# Entire Options Window Layout
self.OuterBox = QVBoxLayout()
self.OuterBox.addLayout(self.Upper)
self.OuterBox.addLayout(self.Lower)
self.setLayout(self.OuterBox)
self.setWindowTitle('Settings')
#Geometry(Left, Top, Width, Hight)
self.setGeometry(250, 250, 550, 450)
self.setModal(True)
self.exec()
def ShowWindow1(self):
self.Contents.setCurrentIndex(1)
def ShowWindow2(self):
self.Contents.setCurrentIndex(2)
def SaveSettings(self):
self.Contents.setCurrentIndex(3)
def RightArrow(self):
if self.Contents.currentIndex() == 1:
self.Contents.setCurrentIndex(2)
else:
self.Contents.setCurrentIndex(1)
class CenterPanel(QWidget):
def __init__(self, MainWin):
QWidget.__init__(self)
CntrPane = QTextEdit('Center Panel is Placed Here')
hbox = QHBoxLayout(self)
hbox.addWidget(CntrPane)
self.setLayout(hbox)
class MenuToolBar(QDockWidget):
def __init__(self, MainWin):
QDockWidget.__init__(self)
self.MainWin = MainWin
self.MainMenu = MainWin.menuBar()
self.WndowMenu = self.MainMenu.addMenu('Windows')
self.OptnAct = QAction('Options', self)
self.OptnAct.setStatusTip('Open the Options Window')
self.OptnAct.triggered.connect(MainWin.ShowOptions)
self.WndowMenu.addAction(self.OptnAct)
self.InitToolBar(MainWin)
def InitToolBar(self, MainWin):
self.mainToolBar = MainWin.addToolBar("Quick Access")
self.mainToolBar.addAction(self.OptnAct)
class UI_MainWindow(QMainWindow):
def __init__(self):
super(UI_MainWindow, self).__init__()
self.setWindowTitle('Main Window')
# Left, Top, Width, Height
self.setGeometry(200, 200, 550, 550)
self.CenterPane = CenterPanel(self)
self.setCentralWidget(self.CenterPane)
self.MenuToolBar = MenuToolBar(self)
def ShowOptions(self):
self.Options = OptionSettings(self)
if __name__ == '__main__':
MainApp = QApplication([])
MainGui = UI_MainWindow()
MainGui.show()
sysExit(MainApp.exec_())
答案 4 :(得分:0)
如果堆叠的窗口小部件中确实需要箭头,则另一种解决方案是实现自己的“ Promoted Widget”:它允许您使用自定义窗口小部件来创建设计,这可能会扩展Qt提供的基本窗口小部件。您将无法与Designer中自己的实现进行交互,但是一旦运行程序,您将获得结果。
这是过程:创建要扩展的窗口小部件的自己的子类,定义您的自定义方法或覆盖现有方法(请记住,某些私有方法需要特定的返回值类型,请查阅文档)。 通常最好将创建的子类保存在单独的文件中。 然后,在Designer中添加所需的小部件(在本例中为StackedWidget),右键单击它并选择“ Promote to ...”。在将显示的对话框中,在“ Promoted class name”字段中键入您创建的子类名称(在下面的示例中,它将是“ StackedWidgetWithArrowButtons”),并在“ header file”字段中包含它的文件:将被视为python导入,因此请勿添加结尾的“ .py”,并请记住,如果将其保存在子目录中,则需要完整的“模块”路径,例如“ mysubclasses” .customstackwidget”,如果文件是“ mysubclasses”目录中的“ customstackwidget”。 保存ui,进行编译并运行程序。
class StackedWidgetWithArrowButtons(QtWidgets.QStackedWidget):
def __init__(self, *args, **kwargs):
QtWidgets.QStackedWidget.__init__(self, *args, **kwargs)
self.backwardButton = QtWidgets.QToolButton(self)
self.backwardButton.setIcon(self.style().standardIcon(QtWidgets.QStyle.SP_ArrowLeft))
self.backwardButton.setMaximumSize(24, 24)
self.backwardButton.setFocusPolicy(QtCore.Qt.NoFocus)
self.forwardButton = QtWidgets.QToolButton(self)
self.forwardButton.setIcon(self.style().standardIcon(QtWidgets.QStyle.SP_ArrowRight))
self.forwardButton.setMaximumSize(24, 24)
self.forwardButton.setFocusPolicy(QtCore.Qt.NoFocus)
self.currentChanged.connect(self.checkSwitchButtons)
def checkSwitchButtons(self):
self.forwardButton.setEnabled(self.currentIndex() < self.count() - 1)
self.backwardButton.setEnabled(self.currentIndex() > 0)
def addWidget(self, widget):
# this is a private method of QStackedWidget that is called when
# the ui is being built by the program, we just implement it
# to ensure that the buttons are correctly enabled;
# the index *has* to be returned
index = QtWidgets.QStackedWidget.addWidget(self, widget)
self.checkSwitchButtons()
return index
def removeWidget(self, widget):
# not necessary, but in case you want to remove widgets in the
# future, it will check buttons again
index = QtWidgets.QStackedWidget.removeWidget(self, widget)
self.checkSwitchButtons()
return index
def mousePressEvent(self, event):
# due to the way QStackedWidget is implemented, children widgets
# that are not in its layout might not receive mouse events,
# but we just need to track clicks so this is enough
if event.button() == QtCore.Qt.LeftButton:
if event.pos() in self.backwardButton.geometry():
self.setCurrentIndex(self.currentIndex() - 1)
elif event.pos() in self.forwardButton.geometry():
self.setCurrentIndex(self.currentIndex() + 1)
def resizeEvent(self, event):
# the base class resizeEvent *has* to be called, otherwise
# you could encounter problems with children widgets
QtWidgets.QStackedWidget.resizeEvent(self, event)
# now ensure that the buttons are always placed on the top
# right corner; this positioning is completely manual and you
# have to take button sizes in consideration to avoid
# overlapping buttons; obviously you can place them wherever
# you want.
self.forwardButton.move(self.rect().right() - self.forwardButton.width(), 0)
self.backwardButton.move(self.forwardButton.x() - self.backwardButton.width(), 0)
如果您不希望按钮(或者您不喜欢按钮的显示方式),则可以实现自己的paintEvent。在这种情况下,我使用QPolygons创建了小三角形。
class StackedWidgetWithTriangles(QtWidgets.QStackedWidget):
def __init__(self, *args, **kwargs):
QtWidgets.QStackedWidget.__init__(self, *args, **kwargs)
self.backwardRect = QtCore.QRect(0, 0, 16, 16)
self.forwardRect = QtCore.QRect(0, 0, 16, 16)
self.forwardArrow = QtGui.QPolygon([QtCore.QPoint(-6, -6), QtCore.QPoint(6, 0), QtCore.QPoint(-6, 6)])
self.backwardArrow = QtGui.QPolygon([QtCore.QPoint(6, -6), QtCore.QPoint(-6, 0), QtCore.QPoint(6, 6)])
def mousePressEvent(self, event):
if event.button() == QtCore.Qt.LeftButton:
if event.pos() in self.backwardRect:
self.setCurrentIndex(self.currentIndex() - 1)
elif event.pos() in self.forwardRect:
self.setCurrentIndex(self.currentIndex() + 1)
def resizeEvent(self, event):
QtWidgets.QStackedWidget.resizeEvent(self, event)
self.forwardRect.moveLeft(self.rect().right() - self.forwardRect.width())
self.backwardRect.moveLeft(self.forwardRect.x() - self.forwardRect.width())
def paintEvent(self, event):
qp = QtGui.QPainter(self)
qp.setRenderHints(qp.Antialiasing)
# set colors according to the possibility of going back or forward,
# showing a "disabled" arrow whenever it's not possible
if self.currentIndex() > 0:
qp.setPen(QtCore.Qt.darkGray)
qp.setBrush(QtCore.Qt.black)
else:
qp.setPen(QtCore.Qt.lightGray)
qp.setBrush(QtCore.Qt.transparent)
qp.drawPolygon(self.backwardArrow.translated(self.backwardRect.center()))
if self.currentIndex() < self.count() - 1:
qp.setPen(QtCore.Qt.darkGray)
qp.setBrush(QtCore.Qt.black)
else:
qp.setPen(QtCore.Qt.lightGray)
qp.setBrush(QtCore.Qt.transparent)
qp.drawPolygon(self.forwardArrow.translated(self.forwardRect.center()))