QCoreApplication.postEvent(receiver, event) 只用输入函数给出好的结果
QCoreApplication.postEvent(receiver, event) give good result only with input function
对一段代码后面的部分进行单体测试(我用...
替换掉不需要的东西来简化)
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') 来反省并逐步查看发生了什么)...
但是如果我删除 input 函数它不再起作用了!!!!
总结:
以下脚本给出了正确的结果
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()
另一方面,如果你想做测试,那么除了你可以使用 pytest-qt 之外,最好使用已经有几个简化功能的 QtTest 子模块。
对一段代码后面的部分进行单体测试(我用...
替换掉不需要的东西来简化)
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') 来反省并逐步查看发生了什么)...
但是如果我删除 input 函数它不再起作用了!!!!
总结: 以下脚本给出了正确的结果
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()
另一方面,如果你想做测试,那么除了你可以使用 pytest-qt 之外,最好使用已经有几个简化功能的 QtTest 子模块。