目的是从第二个应用程序中选择并单击Qt应用程序的小部件(就像用户可以使用TAB和SPACE键击一样)。这两个应用程序都在同一个网络上并通过QTcpSocket的方式进行“对话”,但这不是问题所在。因此,2nb应用程序可以看作应该控制第一个应用程序的3个按钮面板(TAB,shift TAB和SPACE)。第一个应用程序也可以像任何其他Qt应用程序一样直接使用。从第一个应用程序的内部,并收到一个充分的消息,我试图发送一个按键事件,但没有任何反应:
void Appli1::onAppli2_TabClickedMessage()
{
QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier);
QCoreApplication::sendEvent((QObject*)appli1.MainWindow(), &keyEvent);
}
我想这不是正确的做法。我验证了我在调试器中执行这个插槽但没有任何反应,就像事件进入无限空洞一样......
任何帮助(方法或想法)赞赏
不可思议地提到,OP打算使用UIAutomation的正确方法。 (当然,这是假设OP在MS Windows上开发,但对于其他操作系统/ Windows系统肯定有类似的解决方案。)
出于好奇,我玩了一下。
我的接收器是一个QLineEdit
和唯一的小部件 - 它在开始后获得焦点。
但是,我没有让它发挥作用。我有其他想法:
QKeyPress
和QKeyRelease
QString
中提供QKeyEvent
论证,其中OP被排除在外但这没有帮助。
最后,我用sendEvent()
替换了postEvent()
,因为我有点担心直接发送事件(除了应用程序事件循环)。令人惊讶的是,这很有效。
testQSendEvent.cc
:
#include <QtWidgets>
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QApplication app(argc, argv);
QLineEdit qEdt;
qEdt.show();
QTimer qTimer;
qTimer.setInterval(1000/*ms*/);
qTimer.start();
int i = 0;
QObject::connect(&qTimer, &QTimer::timeout,
[&]() {
qDebug() << "About to send key event for" << i;
#if 0 // 1st attempt
{ QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_0 + i, Qt::NoModifier,
QString(QChar('0' + i)));
QApplication::sendEvent(&qEdt, &keyEvent);
}
{ QKeyEvent keyEvent(QEvent::KeyRelease, Qt::Key_0 + i, Qt::NoModifier,
QString(QChar('0' + i)));
QApplication::sendEvent(&qEdt, &keyEvent);
}
#else // 2nd attempt
QApplication::postEvent(&qEdt,
new QKeyEvent(QEvent::KeyPress, Qt::Key_0 + i, Qt::NoModifier,
QString(QChar('0' + i))));
QApplication::postEvent(&qEdt,
new QKeyEvent(QEvent::KeyRelease, Qt::Key_0 + i, Qt::NoModifier,
QString(QChar('0' + i))));
#endif // 0
if (++i >= 10) i = 0;
});
return app.exec();
}
testQSendEvent.pro
:
SOURCES = testQSendEvent.cc
QT = widgets
在cygwin64编译和测试:
$ qmake-qt5 testQSendEvent.pro
$ make
$ ./testQSendEvent
Qt Version: 5.9.4
About to send key event for 0
About to send key event for 1
About to send key event for 2
About to send key event for 3
About to send key event for 4
About to send key event for 5
About to send key event for 6
About to send key event for 7
About to send key event for 8
About to send key event for 9
About to send key event for 0
About to send key event for 1
About to send key event for 2
About to send key event for 3
About to send key event for 4
About to send key event for 5
修改过的样本有两个QLineEdit
s(其中至少有一个肯定不是焦点):
#include <QtWidgets>
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QApplication app(argc, argv);
QWidget qWin;
QVBoxLayout qVBox;
QLineEdit qEdt1, qEdt2;
qVBox.addWidget(&qEdt1);
qVBox.addWidget(&qEdt2);
qWin.setLayout(&qVBox);
qWin.show();
QTimer qTimer;
qTimer.setInterval(1000/*ms*/);
qTimer.start();
int i = 0;
QObject::connect(&qTimer, &QTimer::timeout,
[&]() {
QApplication::postEvent(&qEdt1,
new QKeyEvent(QEvent::KeyPress, Qt::Key_0 + i, Qt::NoModifier,
QString(QChar('0' + i))));
QApplication::postEvent(&qEdt1,
new QKeyEvent(QEvent::KeyRelease, Qt::Key_0 + i, Qt::NoModifier,
QString(QChar('0' + i))));
QApplication::postEvent(&qEdt2,
new QKeyEvent(QEvent::KeyPress, Qt::Key_A + i, Qt::NoModifier,
QString(QChar('A' + i))));
QApplication::postEvent(&qEdt2,
new QKeyEvent(QEvent::KeyRelease, Qt::Key_A + i, Qt::NoModifier,
QString(QChar('A' + i))));
if (++i >= 10) i = 0;
});
return app.exec();
}
即使是没有焦点的QLineEdit
s,如果直接发布给他们,似乎也能正确处理关键事件。 (我不确定这种行为是否取决于Windows系统。在我的情况下,它是我在cygwin中测试的X11。)
当OP明确提到QPushButton
s时,我再次调整了我的样本:
#include <QtWidgets>
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QApplication app(argc, argv);
QWidget qWin;
QVBoxLayout qVBox;
QPushButton qBtn1("Button 1");
QPushButton qBtn2("Button 2");
qVBox.addWidget(&qBtn1);
qVBox.addWidget(&qBtn2);
qWin.setLayout(&qVBox);
qWin.show();
QTimer qTimer;
qTimer.setInterval(1000/*ms*/);
qTimer.start();
int i = 0;
QObject::connect(&qTimer, &QTimer::timeout,
[&]() {
switch (i) {
case 0:
QApplication::postEvent(&qBtn1,
new QKeyEvent(QEvent::KeyPress, Qt::Key_Space, Qt::NoModifier,
QString(QChar(' '))));
break;
case 1:
QApplication::postEvent(&qBtn1,
new QKeyEvent(QEvent::KeyRelease, Qt::Key_Space, Qt::NoModifier,
QString(QChar(' '))));
break;
case 2:
#if 0 // EXCLUDED
QApplication::postEvent(&qBtn1,
new QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier,
QString(QChar('\t'))));
QApplication::postEvent(&qBtn1,
new QKeyEvent(QEvent::KeyRelease, Qt::Key_Tab, Qt::NoModifier,
QString(QChar('\t'))));
#endif // 0
break;
case 3:
QApplication::postEvent(&qBtn2,
new QKeyEvent(QEvent::KeyPress, Qt::Key_Space, Qt::NoModifier,
QString(QChar(' '))));
break;
case 4:
QApplication::postEvent(&qBtn2,
new QKeyEvent(QEvent::KeyRelease, Qt::Key_Space, Qt::NoModifier,
QString(QChar(' '))));
break;
case 5:
#if 0 // EXCLUDED
QApplication::postEvent(&qBtn2,
new QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier,
QString(QChar('\t'))));
QApplication::postEvent(&qBtn2,
new QKeyEvent(QEvent::KeyRelease, Qt::Key_Tab, Qt::NoModifier,
QString(QChar('\t'))));
#endif // 0
break;
}
if (++i > 5) i = 0;
});
QObject::connect(&qBtn1, &QPushButton::clicked,
[&](bool) { qDebug() << "Button 1 clicked"; });
QObject::connect(&qBtn2, &QPushButton::clicked,
[&](bool) { qDebug() << "Button 2 clicked"; });
return app.exec();
}
甚至发出了QPushButton::clicked
信号:
$ ./testQSendEvent
Qt Version: 5.9.4
Button 1 clicked
Button 2 clicked
Button 1 clicked
Button 2 clicked
Button 1 clicked
Button 2 clicked
Button 1 clicked
我尝试了无焦点改变。 (在我发布Tab事件之前,我可以看到焦点发生变化。)然而,与EXCLUDED
一样,空间键事件在QLineEdit
中独立于焦点处理。
最后一个示例代码版本,我在VS2013中使用Qt 5.9.2再次编译(对于本机WinAPI)。它的行为与我在cygwin中使用QPushButton
和Qt 5.9.4编译的X11完全相同。即将空间键事件发送到g++
改变了它的视觉外观,并且正确发射了QPushButton
信号。
QPushButton::clicked
我“意外地”认为应该正确设置的第四个QString
论点。我发布时发现了这个
QKeyEvent
接收 QKeyEvent(QEvent::KeyPress, Qt::Key_A + i, Qt::NoModifier,
QString(QChar('0' + i)));
插入数字显然忽略QLineEdit
。
模拟按键似乎是不必要的。接收器处理三个命令:
Qt::Key_A + i
:将焦点移动到焦点链中的下一个项目(如Tab所示)NEXT_FOCUS
:将焦点移动到焦点链中的上一个项目(如Shift-Tab所示)PREVIOUS_FOCUS
:调用焦点小部件的CLICK
方法 - 所有Qt的按钮都支持它,因为它在它们的基础click()
类中。因此,像下面这样的东西应该可以做到这一点,你不需要模仿键盘 - 特别是你不能保证你提到的特定键具有你期望的效果 - 行为是特定于平台的,并且可能甚至是主题特定的。例如。在OS X上,原生行为是因为空格键没有效果,因为按钮不可聚焦。
QAbstractButton