当小部件可见性发生变化时,MacOS 中的 Qt 错误表单渲染
Qt buggy form rendering in MacOS when widget visibility changes
我在表单上有几个单选按钮和 2 个线路输入。
根据选中的选项,我只希望 those 输入之一可见。
因此,每次用户点击时,我都会通过以下方式设置两个行编辑的可见性
setVisible() 函数。
它在 Windows 上工作得很好,但在 MacOS 上我看到了瑕疵。在可见的 lineedit 后面,我看到隐藏的 lineedit "remains":
在 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()
好的,临时解决方案是每次在 window 或每个错误元素上调用 repaint()。然而它看起来生涩。有更好的解决方案吗?
发出信号的错误可能是 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 个线路输入。 根据选中的选项,我只希望 those 输入之一可见。
因此,每次用户点击时,我都会通过以下方式设置两个行编辑的可见性 setVisible() 函数。
它在 Windows 上工作得很好,但在 MacOS 上我看到了瑕疵。在可见的 lineedit 后面,我看到隐藏的 lineedit "remains":
在 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()
好的,临时解决方案是每次在 window 或每个错误元素上调用 repaint()。然而它看起来生涩。有更好的解决方案吗?
发出信号的错误可能是 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()