小部件可见性更改时在 MacOS 中呈现 Qt 错误表单
Posted
技术标签:
【中文标题】小部件可见性更改时在 MacOS 中呈现 Qt 错误表单【英文标题】:Qt buggy form rendering in MacOS when widget visibility changes 【发布时间】:2019-04-17 09:53:34 【问题描述】:我在表单上有几个单选按钮和 2 行输入。 根据选中的选项,我只希望其中一个输入可见。
所以,每次用户点击时,我都会通过 setVisible() 函数。
它在 Windows 上运行良好,但在 MacOS 上我看到了伪像。在可见的 lineedit 后面,我看到了隐藏 lineedit 的“残余”:
在 mac os 上是否有任何 hack 来解决这个问题?
PyQt 版本 5
编辑:
根据要求,下面是验证示例。在 MacOS 中使用 python 3 运行它。
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtWidgets import QApplication
import sys
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.verticalLayout = QtWidgets.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
self.radioButton = QtWidgets.QRadioButton(self.centralwidget)
self.radioButton.setObjectName("radioButton")
self.verticalLayout.addWidget(self.radioButton)
self.radioButton_2 = QtWidgets.QRadioButton(self.centralwidget)
self.radioButton_2.setObjectName("radioButton_2")
self.verticalLayout.addWidget(self.radioButton_2)
self.verticalLayout_3.addLayout(self.verticalLayout)
self.verticalLayout_2 = QtWidgets.QVBoxLayout()
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.setVisible(False)
self.lineEdit.setObjectName("lineEdit")
self.lineEdit.setPlaceholderText("LineEdit 1")
self.horizontalLayout.addWidget(self.lineEdit)
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setVisible(False)
self.pushButton.setObjectName("pushButton")
self.horizontalLayout.addWidget(self.pushButton)
self.verticalLayout_2.addLayout(self.horizontalLayout)
self.lineEdit_2 = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit_2.setVisible(False)
self.lineEdit_2.setObjectName("lineEdit_2")
self.lineEdit_2.setPlaceholderText("LineEdit 2")
self.verticalLayout_2.addWidget(self.lineEdit_2)
self.verticalLayout_3.addLayout(self.verticalLayout_2)
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout_3.addItem(spacerItem)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 22))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.radioButton.setText(_translate("MainWindow", "Option 1"))
self.radioButton_2.setText(_translate("MainWindow", "Option 2"))
self.pushButton.setText(_translate("MainWindow", "PushButton"))
class App:
def __init__(self):
self.app = QApplication(sys.argv)
self.window = QMainWindow()
self.ui = Ui_MainWindow()
self.ui.setupUi(self.window)
self.ui.radioButton.clicked.connect(self.update_visibility)
self.ui.radioButton_2.clicked.connect(self.update_visibility)
def update_visibility(self):
self.ui.lineEdit.setVisible(self.ui.radioButton.isChecked())
self.ui.lineEdit_2.setVisible(self.ui.radioButton_2.isChecked())
def exec(self):
self.window.show()
sys.exit(self.app.exec_())
def main():
a = App()
a.exec()
if __name__ == "__main__":
main()
【问题讨论】:
添加示例。 为什么不使用 QStackedWidget 来切换 QLineEdits 的可见性? 你能举个例子吗? 谢谢。堆叠小部件绝对是更好的解决方案。 【参考方案1】:可能发出信号的错误是 Qt 错误或某些驱动程序不兼容。
我的解决方案朝着另一个方向发展,您可以使用 QButtonGroup 旁边的 QStackedWidget 来设置 QLineEdits 的可见性,而不是隐藏 QLineEdits。
from PyQt5 import QtCore, QtGui, QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.import_radiobutton = QtWidgets.QRadioButton(
"import from file", checked=True
)
self.download_radiobutton = QtWidgets.QRadioButton(
"Download via magnet link"
)
self.import_lineedit = QtWidgets.QLineEdit(
placeholderText="LineEdit 1"
)
self.download_lineedit = QtWidgets.QLineEdit(
placeholderText="LineEdit 2"
)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
lay = QtWidgets.QVBoxLayout(central_widget)
lay.addWidget(self.import_radiobutton)
lay.addWidget(self.download_radiobutton)
stacked = QtWidgets.QStackedWidget()
stacked.setSizePolicy(
QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Maximum
)
lay.addWidget(stacked)
lay.addStretch()
buttongroup = QtWidgets.QButtonGroup(self)
buttongroup.buttonClicked[int].connect(stacked.setCurrentIndex)
for button, lineedit in zip(
(self.import_radiobutton, self.download_radiobutton),
(self.import_lineedit, self.download_lineedit),
):
ix = stacked.addWidget(lineedit)
buttongroup.addButton(button, ix)
self.resize(640, 480)
def main():
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
【讨论】:
【参考方案2】:好的,临时解决方案是每次在窗口或每个有问题的元素上调用 repaint()。然而,它看起来生涩。有更好的解决方案吗?
【讨论】:
以上是关于小部件可见性更改时在 MacOS 中呈现 Qt 错误表单的主要内容,如果未能解决你的问题,请参考以下文章