了解 Qt5 / PyQt5 焦点行为
Understanding Qt5 / PyQt5 focus behavior
我有一个非常简单的测试应用程序:
from PyQt5.QtWidgets import *
import sys
import time
class Example(QWidget):
def __init__(self):
super().__init__()
self.pbar = QProgressBar(self)
self.pbar.setGeometry(30, 40, 200, 25)
self.btn = QPushButton('Start', self)
self.btn.move(40, 80)
self.btn.clicked.connect(self.do_action)
self.txt = QLineEdit('Some info goes here', self)
self.txt.setReadOnly(True)
self.txt.move(40, 120)
self.setGeometry(300, 300, 280, 170)
self.setWindowTitle("Python")
self.show()
def do_action(self):
# setting for loop to set value of progress bar
self.btn.setDisabled(True)
for i in range(101):
time.sleep(0.05)
self.pbar.setValue(i)
self.btn.setEnabled(True)
if __name__ == '__main__':
App = QApplication(sys.argv)
window = Example()
sys.exit(App.exec())
这段代码有两个可能相关的问题:
- 如果我点击
btn
它尽职尽责地开始 QProgressBar
更新并自行禁用,但是如果我点击它两次我将看到 两次 迭代pbar
;不应该忽略对已禁用的小部件的点击吗?
- 一旦
btn
被禁用 txt
内容被选中,尽管它是只读的;有什么方法可以防止这种“关注下一个”行为吗?最好在下次点击之前让所有内容都不集中。
这种行为被认为是“正常”的吗?
第一个问题是由于您在 ui 框架等事件驱动系统中使用了阻塞函数(永远不会 发生)。发生的事情是带有睡眠函数的 for 循环阻止 Qt 正确处理事件,包括输入事件:你的第二次点击被“排队”并且只能在控制返回到事件管理器后立即处理(当函数最终returns),因为此时您已重新启用该按钮,只有到那时才最终处理之前的排队事件(并再次调用该函数)。
解决方法很简单:避免这种情况,如果需要基于时间的迭代,使用QTimer,如果需要并行和非阻塞处理,使用QThread。
我有一个非常简单的测试应用程序:
from PyQt5.QtWidgets import *
import sys
import time
class Example(QWidget):
def __init__(self):
super().__init__()
self.pbar = QProgressBar(self)
self.pbar.setGeometry(30, 40, 200, 25)
self.btn = QPushButton('Start', self)
self.btn.move(40, 80)
self.btn.clicked.connect(self.do_action)
self.txt = QLineEdit('Some info goes here', self)
self.txt.setReadOnly(True)
self.txt.move(40, 120)
self.setGeometry(300, 300, 280, 170)
self.setWindowTitle("Python")
self.show()
def do_action(self):
# setting for loop to set value of progress bar
self.btn.setDisabled(True)
for i in range(101):
time.sleep(0.05)
self.pbar.setValue(i)
self.btn.setEnabled(True)
if __name__ == '__main__':
App = QApplication(sys.argv)
window = Example()
sys.exit(App.exec())
这段代码有两个可能相关的问题:
- 如果我点击
btn
它尽职尽责地开始QProgressBar
更新并自行禁用,但是如果我点击它两次我将看到 两次 迭代pbar
;不应该忽略对已禁用的小部件的点击吗? - 一旦
btn
被禁用txt
内容被选中,尽管它是只读的;有什么方法可以防止这种“关注下一个”行为吗?最好在下次点击之前让所有内容都不集中。
这种行为被认为是“正常”的吗?
第一个问题是由于您在 ui 框架等事件驱动系统中使用了阻塞函数(永远不会 发生)。发生的事情是带有睡眠函数的 for 循环阻止 Qt 正确处理事件,包括输入事件:你的第二次点击被“排队”并且只能在控制返回到事件管理器后立即处理(当函数最终returns),因为此时您已重新启用该按钮,只有到那时才最终处理之前的排队事件(并再次调用该函数)。
解决方法很简单:避免这种情况,如果需要基于时间的迭代,使用QTimer,如果需要并行和非阻塞处理,使用QThread。