目的是从另一个应用程序中选择并单击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);
}
我认为这不是正确的方法。我确认我在调试器中执行了这个插槽,但是什么也没发生,就像事件进入了无限的虚无...
感谢任何帮助(方法或想法)
答案 0 :(得分:1)
IInspectable提到OP打算使用的正确方法是使用UIAutomation。 (当然,这是假定OP是在MS Windows上开发的,但是对于其他OS / Windows系统肯定有类似的解决方案。)
出于好奇,我玩了一点。
我的接收器是一个QLineEdit
,并且是唯一的一个小部件–启动后将获得焦点。
但是,我没有使它工作。我有其他想法:
QKeyPress
和QKeyRelease
QString
中提供OP忽略的QKeyEvent
参数但这没有帮助。
最后,由于有点担心直接发送事件(除了应用程序事件循环),我用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
(其中至少一个绝对不是焦点):
#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
,如果直接发布到关键事件上,也似乎可以正确处理。 (我不确定这种行为是否取决于Windows系统。就我而言,这是我在cygwin中测试的X11。)
正如OP明确提到的QPushButton
一样,我再次修改了示例:
#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
我尝试了有无焦点切换。 (在我EXCLUDED
Tab 事件之前,我可以看到焦点发生了变化。)但是,与QLineEdit
中的 Space 键事件一样,在QPushButton
中处理,与焦点无关。
最后一个示例代码版本,我在VS2013中使用Qt 5.9.2再次编译(对于本机WinAPI)。它的表现完全像我在cygwin中用g++
和Qt 5.9.4 for X11编译的那样。
即将 Space 键事件发送到QPushButton
会更改其外观,并且QPushButton::clicked
信号已正确发出。
我“偶然地”发现QString
的第四个QKeyEvent
自变量应正确设置。我在发布时发现了这一点
QKeyEvent(QEvent::KeyPress, Qt::Key_A + i, Qt::NoModifier,
QString(QChar('0' + i)));
接收方QLineEdit
插入的数字显然忽略了Qt::Key_A + i
。