python - QCoreApplication.postEvent(receiver, event) 仅使用输入功能才能提供良好的结果
问题描述
对代码的以下部分执行单一测试(我用...
替换不必要的东西来简化)
from PyQt5.QtWidgets import QWidget, QLineEdit
// ...
class Controller(QWidget):
def __init__(self, ...)
// ...
self.line_edit_name = QLineEdit()
// ...
def display_parameters(self, name, ...)
self.line_edit_name.setText(name)
self.line_edit_name.setReadOnly(False)
self.line_edit_name.returnPressed.connect(
partial(self.update_name, ...))
def update_name(self, ...):
// ...
我将这段代码用于使用 unittest 进行测试:
from PyQt5 import QtCore, QtGui
from PyQt5.QtCore import QCoreApplication, QEvent
// ...
a = Controller()
a.line_edit_name.setText("Shakespeare")
keyEvent = QtGui.QKeyEvent(QtCore.QEvent.KeyPress, QtCore.Qt.Key_Return, QtCore.Qt.NoModifier)
QCoreApplication.postEvent(a.line_edit_name, keyEvent)
// ...
它在调试阶段工作得非常好(我经常使用 input('foo') 来反省并逐步查看发生了什么)...
但是如果我删除了输入函数,它就不再起作用了!!!!
总之:以下脚本给出了正确的结果
a = Controller()
a.line_edit_name.setText("Shakespeare")
keyEvent = QtGui.QKeyEvent(QtCore.QEvent.KeyPress, QtCore.Qt.Key_Return, QtCore.Qt.NoModifier)
QCoreApplication.postEvent(a.line_edit_name, keyEvent)
input("foo")
//...
以下不是
a = Controller()
a.line_edit_name.setText("Shakespeare")
keyEvent = QtGui.QKeyEvent(QtCore.QEvent.KeyPress, QtCore.Qt.Key_Return, QtCore.Qt.NoModifier)
QCoreApplication.postEvent(a.line_edit_name, keyEvent)
// ...
因为单元测试是在持续集成期间自动完成的,所以我们不能使用输入函数。为什么这个结果以及没有输入功能怎么办?
编辑:通过进行各种测试,我认为 input() 函数只允许进程在下一个命令之前完成。我试过之后QCoreApplication.postEvent(a.line_edit_name, keyEvent)
,代替input("foo")
, threading.Event().wait(1)
或者time.sleep(1)
没有成功......
解决方案
在 Qt 中,发送事件和调用与信号相关的槽的任务是异步的,所以不要期望立即得到响应,而是必须等待。在这种情况下,您必须使用 QTest.qWait。
由于您不提供 MRE,因此我将仅展示一个简单的演示:
from functools import partial
from PyQt5.QtCore import QCoreApplication, QEvent, Qt
from PyQt5.QtGui import QKeyEvent
from PyQt5.QtWidgets import QApplication, QFormLayout, QLineEdit, QWidget
from PyQt5.QtTest import QTest
class Controller(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.current_name = ""
self.line_edit_name = QLineEdit()
lay = QFormLayout(self)
lay.addRow("name", self.line_edit_name)
def display_parameters(self, name):
self.line_edit_name.setText(name)
self.line_edit_name.setReadOnly(False)
self.line_edit_name.returnPressed.connect(partial(self.update_name, name))
def update_name(self, name):
self.current_name = name
def test_controller():
app = QApplication([])
a = Controller()
a.display_parameters("Foo")
assert a.current_name != "Foo"
keyEvent = QKeyEvent(QEvent.KeyPress, Qt.Key_Return, Qt.NoModifier)
QCoreApplication.postEvent(a.line_edit_name, keyEvent)
# QTest.keyClick(a.line_edit_name, Qt.Key_Return)
QTest.qWait(1000)
assert a.current_name == "Foo"
test_controller()
另一方面,如果你想做测试,那么最好使用 QtTest 子模块,它已经有几个简化的功能,除了你可以使用 pytest-qt。
推荐阅读
- c# - 如何使用 CMake 定义 C# 单元测试项目?
- java - Java - 反射。在 setter 方法中设置 Value 动态创建的多参数类对象
- swift - 无法在视图控制器上创建 UIBarButtonItem
- java - Home screen shortcut wont add
- java - 如何在 oracle 查询中将所有相似的行数据视为一个?
- google-maps - 谷歌地图地址地理编码 API 不起作用
- machine-learning - 如何获得随机森林算法在自变量上使用的最终方程来预测因变量?
- r - 如何在 MATLAB(当前为 R)中编写这行代码?
- wordpress - htaccess 用下划线合并 2 个段
- javascript - 等待 curl_exec 得到响应时显示 Gif