首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用鼠标或键盘单击按钮时,PyQt小部件刷新行为不同

使用鼠标或键盘单击按钮时,PyQt小部件刷新行为不同
EN

Stack Overflow用户
提问于 2020-06-23 08:46:47
回答 1查看 732关注 0票数 0

我刚开始使用PyQt;我正在尝试设置一个非常简单的MainWindow,其中包含3个行编辑和1个按钮。

以下是我想要得到的行为:

当两个第一个按钮的内容变得有效时,按钮就启用了。

当单击按钮时,将第二行编辑的内容重置为空刺,并禁用按钮。

下面是代码-视图代码是使用Qt和pyuic5生成的。

一切似乎都很好,除了用鼠标单击按钮时--行编辑的内容显示为未擦除(实际上是),而按钮看起来是启用的(实际上是禁用的)。如果触发窗口刷新(即最小化和恢复),则将正确显示窗口小部件。当使用键盘单击按钮时,将正确刷新所有内容。

我不知道是什么原因造成了这个奇怪的艺术品..。任何帮助都将不胜感激。

编辑我刚刚发现,只有当用enter键“单击”按钮时,它才能正常工作,如果使用空格,注意到同样有缺陷的行为.这让我想知道"enter“和任何其他点击的意思有什么区别?

提前谢谢你

主要python代码:

代码语言:javascript
复制
from PyQt5 import QtWidgets, QtCore
import sys

import view1


class Model(QtCore.QObject):
    text1_changed = QtCore.pyqtSignal(str)
    text2_changed = QtCore.pyqtSignal(str)
    text3_changed = QtCore.pyqtSignal(str)
    canprocess_changed = QtCore.pyqtSignal(bool)

    def __init__(self):
        super().__init__()
        self._text1 = ''
        self._text2 = ''
        self._text3 = ''
        self._canprocess = False

    @property
    def text1(self):
        return self._text1

    @text1.setter
    def text1(self, value):
        self._text1 = value
        self.text1_changed.emit(value)

    @property
    def text2(self):
        return self._text2

    @text2.setter
    def text2(self, value):
        self._text2 = value
        self.text2_changed.emit(value)

    @property
    def text3(self):
        return self._text3

    @text3.setter
    def text3(self, value):
        self._text3 = value
        self.text3_changed.emit(value)

    @property
    def canprocess(self):
        return self._canprocess

    @canprocess.setter
    def canprocess(self, value):
        self._canprocess = value
        self.canprocess_changed.emit(value)


class Controller(QtCore.QObject):
    def __init__(self, model: Model):
        super().__init__()
        self._model = model
        self._text1valid = False
        self._text2valid = False

    def istext1valid(self, text) -> bool:
        return text[:3] == 'abc'

    def istext2valid(self, text) -> bool:
        return text[:3] == 'def'

    def _validity_update(self):
        self._model.canprocess = self._text1valid and self._text2valid

    @QtCore.pyqtSlot(str)
    def change_text1(self, text):
        self._text1valid = self.istext1valid(text)
        self._validity_update()
        if self._text1valid:
            self._model.text1 = text

    @QtCore.pyqtSlot(str)
    def change_text2(self, text):
        self._text2valid = self.istext2valid(text)
        self._validity_update()
        if self._text2valid:
            self._model.text2 = text

    @QtCore.pyqtSlot(str)
    def change_text3(self, text):
        self._model.text3 = text

    @QtCore.pyqtSlot()
    def process(self):
        # do real stuff
        self._text2valid = False
        self._validity_update()
        self._model.text2 = ''

    def init_view(self):
        self._text1valid = False
        self._text2valid = False
        self._validity_update()
        self._model.text1=''
        self._model.text2=''
        self._model.text3='an init value'



class MainAppWindow(QtWidgets.QMainWindow, view1.Ui_MainWindow):
    def __init__(self, model: Model, controller: Controller):
        super().__init__()
        self._model = model
        self._controller = controller
        self.setupUi(self)

    def setupUi(self, window):
        super().setupUi(self)
        self.bProceed.clicked.connect(self._controller.process)
        self.ledit1.editingFinished.connect(lambda: self._controller.change_text1(self.ledit1.text()))
        self.ledit2.editingFinished.connect(lambda: self._controller.change_text2(self.ledit2.text()))
        self.ledit3.editingFinished.connect(lambda: self._controller.change_text3(self.ledit3.text()))

        self._model.text1_changed.connect(self.ledit1.setText)
        self._model.text2_changed.connect(self.ledit2.setText)
        self._model.text3_changed.connect(self.ledit3.setText)
        self._model.canprocess_changed.connect(self.bProceed.setEnabled)

        self._controller.init_view()


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    mainmodel = Model()
    maincontroller = Controller(mainmodel)
    MainWindow = MainAppWindow(mainmodel, maincontroller)
    MainWindow.show()
    sys.exit(app.exec_())

生成的UI:

代码语言:javascript
复制
from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(435, 204)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.formLayout = QtWidgets.QFormLayout(self.centralwidget)
        self.formLayout.setObjectName("formLayout")
        self.label_2 = QtWidgets.QLabel(self.centralwidget)
        self.label_2.setObjectName("label_2")
        self.formLayout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.label_2)
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setObjectName("label")
        self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label)
        self.ledit1 = QtWidgets.QLineEdit(self.centralwidget)
        self.ledit1.setObjectName("ledit1")
        self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.ledit1)
        self.ledit2 = QtWidgets.QLineEdit(self.centralwidget)
        self.ledit2.setObjectName("ledit2")
        self.formLayout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.ledit2)
        self.bProceed = QtWidgets.QPushButton(self.centralwidget)
        self.bProceed.setFocusPolicy(QtCore.Qt.StrongFocus)
        self.bProceed.setDefault(True)
        self.bProceed.setObjectName("bProceed")
        self.formLayout.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.bProceed)
        self.ledit3 = QtWidgets.QLineEdit(self.centralwidget)
        self.ledit3.setObjectName("ledit3")
        self.formLayout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.ledit3)
        self.label_3 = QtWidgets.QLabel(self.centralwidget)
        self.label_3.setObjectName("label_3")
        self.formLayout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.label_3)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 435, 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)
        MainWindow.setTabOrder(self.ledit1, self.ledit2)
        MainWindow.setTabOrder(self.ledit2, self.bProceed)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.label_2.setText(_translate("MainWindow", "Text2"))
        self.label.setText(_translate("MainWindow", "Text1"))
        self.bProceed.setText(_translate("MainWindow", "Proceed"))
        self.label_3.setText(_translate("MainWindow", "Text3"))
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-06-28 07:39:41

从Mac的版本5.10开始,它就已经成为了PyQt5的一个已知缺陷,它影响到几乎所有内容以编程方式更改的小部件。

解决方案是对任何内容被更改的小部件进行子类,并显式调用repaint()。

举个例子,下面是我为按钮使用的代码:

代码语言:javascript
复制
class OSxPushButton(QtWidgets.QPushButton):
"""
A class to correct an OSX bug affecting widgets update when attributes are
programmatically modified.
"""
def __init__(self, parent=None):
    super().__init__(parent)

def setEnabled(self, a0: bool) -> None:
    super().setEnabled(a0)
    self.repaint()
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62530793

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档