Inspectable упомянул, что правильным способом для OP является использование UIAutomation . (Конечно, это предполагает, что OP разрабатывается в MS Windows, но, безусловно, существуют аналогичные решения для других операционных систем / систем Windows.)
Из любопытства я немного поиграл с этим.
Мой получатель QLineEdit
и единственный виджет & ndash; он получает фокус после запуска.
Тем не менее, у меня не получилось. Другие идеи, которые у меня были:
- отправить
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
![snapshot of testQSendEvent](https://i.stack.imgur.com/A3PhZ.png)
Модифицированный образец с двумя 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();
}
![snapshot of testQSendEvent (2nd version)](https://i.stack.imgur.com/uNKF9.png)
Даже QLineEdit
, которые не имеют фокуса, похоже, обрабатывают ключевые события должным образом, если непосредственно отправлены на них. (Я не уверен, зависит ли это поведение от системы Windows. В моем случае это X11, как я тестировал в cygwin.)
Как уже упоминалось в 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();
}
![snapshot of testQSendEvent (3rd version)](https://i.stack.imgur.com/B7cwu.png)
Даже был издан сигнал 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
, события Пробел обрабатываются в QPushButton
независимо фокус.
Последний пример кода, я снова скомпилировал в VS2013 с Qt 5.9.2 (для собственного WinAPI). Он вел себя точно , как тот, который я скомпилировал в cygwin с g++
и Qt 5.9.4 для X11.
То есть отправка пробела ключевого события на QPushButton
изменила его визуальный облик, и сигнал QPushButton::clicked
был испущен правильно.
![snapshot of testQEvent (3rd version) compiled with Qt/WinAPI](https://i.stack.imgur.com/TzgPM.png)
Я "случайно" заметил, что четвертый QString
аргумент QKeyEvent
должен быть установлен правильно. Я узнал об этом, когда отправил
QKeyEvent(QEvent::KeyPress, Qt::Key_A + i, Qt::NoModifier,
QString(QChar('0' + i)));
Принимающие QLineEdit
вставленные цифры явно игнорируют Qt::Key_A + i
.