PyQT:PushButton 在禁用时接收命令

Posted

技术标签:

【中文标题】PyQT:PushButton 在禁用时接收命令【英文标题】:PyQT: PushButton receives commands while disabled 【发布时间】:2016-09-09 10:58:11 【问题描述】:

我遇到了这个问题,并试图将其分解为我能想象到的最简单的代码:我使用 Qt Designer V4.8.7 创建了一个 GUI,它只包含一个具有所有默认设置的按钮。它被称为“Test2.ui”。当按下按钮时,它应该被禁用,在终端中打印一些东西,然后再次启用。发生的情况是我能够单击禁用的按钮,并且它会重复所有打印,就像我单击一样多次。当我将按钮设置为不可见而不是禁用它时,这甚至可以工作。我在互联网上发现了类似的问题,但似乎没有一个解决方案对我有用——这让我发疯。有人有想法吗?

from __future__ import division, print_function
import sys
from PyQt4 import QtCore, QtGui, uic
from PyQt4.QtCore import QTimer
from time import sleep

qtCreatorFile = "Test2.ui" # Enter file here.

Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile)


class MyApp(QtGui.QMainWindow, Ui_MainWindow):

    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        Ui_MainWindow.__init__(self)
        self.setupUi(self)
        self.pushButton.pressed.connect(self.Test_Function)


    def Test_Function(self):
        self.pushButton.setEnabled(False)
        QtGui.QApplication.processEvents()
        print('Test 1')
        sleep(1)
        print('Test 2')
        sleep(1)
        self.pushButton.setEnabled(True)

if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    window = MyApp()
    window.show()
    sys.exit(app.exec_())

这是'Test2.ui'的代码

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>445</width>
    <height>393</height>
   </rect>
  </property>
  <property name="mouseTracking">
   <bool>false</bool>
  </property>
  <property name="focusPolicy">
   <enum>Qt::ClickFocus</enum>
  </property>
  <property name="acceptDrops">
   <bool>false</bool>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QPushButton" name="pushButton">
    <property name="enabled">
     <bool>true</bool>
    </property>
    <property name="geometry">
     <rect>
      <x>160</x>
      <y>150</y>
      <width>75</width>
      <height>23</height>
     </rect>
    </property>
    <property name="text">
     <string>Test</string>
    </property>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>445</width>
     <height>22</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

【问题讨论】:

这可能不是 python:但在 c++ Qt 中这是故意的:doc.qt.io/qt-5/qabstractbutton.html 启用的按钮仍然接收鼠标事件。您应该为此检查 python 文档。似乎您需要检查单击处理程序中是否启用了按钮。 能否提供Test2.ui的代码?这将使测试更容易。 我添加了 .ui 文件的代码。用 .setDown 替换 .setEnabled 命令会导致同样的问题。 【参考方案1】:

您的示例代码将无法运行,因为测试功能会阻塞 gui。虽然它处于阻塞状态,但按钮的禁用状态没有正确更新,因此仍然可以发出 clicked 信号。避免阻塞 gui 的最佳方法是在单独的线程中完成工作:

class Worker(QtCore.QObject):
    finished = QtCore.pyqtSignal()

    def run(self):
        print('Test 1')
        sleep(1)
        print('Test 2')
        sleep(1)
        self.finished.emit()

class MyApp(QtGui.QMainWindow, Ui_MainWindow):
    def __init__(self):
        ...

        self.pushButton.pressed.connect(self.handleButton)

        self.thread = QtCore.QThread(self)
        self.worker = Worker()
        self.worker.moveToThread(self.thread)
        self.worker.finished.connect(self.handleFinished)
        self.thread.started.connect(self.worker.run)

    def handleButton(self):
        self.pushButton.setEnabled(False)
        self.thread.start()

    def handleFinished(self):
        self.thread.quit()
        self.thread.wait()
        self.pushButton.setEnabled(True)

【讨论】:

非常感谢。这两天我想不通! 倒数第二行'self.thread.wait()'的意义何在? @Delf。调用quit() 会告诉线程退出它的事件循环,但这只有在没有任何阻塞的情况下才会发生。因此有必要wait() 直到控制返回到事件循环,以确保线程已完全完成。不要仅仅因为它在本示例中似乎没有任何效果而试图将其忽略 - 通常,它始终是必需的。

以上是关于PyQT:PushButton 在禁用时接收命令的主要内容,如果未能解决你的问题,请参考以下文章

pyqt5中的信号槽的使用

PyQt5 PushButton 未显示

pyqt中pushbutton中的属性都有哪些

Pyqt5 输入信息 pushbutton 与 键盘上Enter绑定

在编译或运行 PyQT4 GUI 应用程序时排除(或禁用)log4cplus 警告?

pyQt点击事件和数据传输