您可以在堆栈上创建事件。然后使用QCoreApplication::sendEvent
立即传递事件:
QWidget w1, w2;
QKeyEvent event(QEvent::KeyPress, inputKey.keyValue, Qt::NoModifier);
QApplication::sendEvent(&w1, &ev);
QApplication::sendEvent(&w2, &ev);
每个都sendEvent
将调用小部件的event
方法,然后将调用xxxxEvent
受保护的方法(如果适用)。但是不要自己做,因为你会绕过应用程序全局事件过滤器并依赖于实现细节。
// WRONG!
w1.event(&ev);
// WRONG and won't compile since keyPressEvent is protected
w2.keyPressEvent(&ev);
或者,您可以在堆上创建它。Qt 会在您发布事件后立即管理它的生命周期。发布后,该活动不再属于您,您无法重复使用它。您必须为每个帖子创建多个事件。避免重复的最简单方法是创建一个按需生成事件的本地函数。
QWidget w1, w2;
auto ev = [=]{ return new QKeyEvent(QEvent::KeyPress, inputKey.keyValue, Qt::NoModifier); };
QApplication::postEvent(&w1, ev());
QApplication::postEvent(&w2, ev());
这些事件将被添加到主线程的事件队列中。一旦控件返回QApplication::exec
,它们将被一一传递给小部件。小部件的event
方法将被调用 from QApplication::exec
,而不是from postEvent
。
该QWidget::event
实现解码事件类型并调用受保护的便利处理程序,例如keyPressEvent
,enterEvent
等。它的实现遵循以下模式:
bool QWidget::event(QEvent * ev) {
switch (ev->type()) {
case QEvent::KeyPress:
keyPressEvent(static_cast<QKeyEvent*>(ev));
return true;
case QEvent::Enter:
enterEvent(static_cast<QEnterEvent*>(ev));
return true;
...
}
return QObject::event(ev);
}
在为具有此类便利虚拟方法的事件类型实现处理程序时xxxxEvent
,您应该重新实现虚拟方法,而不是其event()
本身。因此你MainWindow
应该重新实现keyPressEvent
:
void MainWindow::keyPressEvent(QKeyEvent * event) {
if (event->key() == Qt::Key_Enter)
ui->label->setText("Enter received");
else if (event->key() == Qt::Key_A)
ui->label->setText("A received");
QMainWindow::keyPressEvent(event);
}
如果您希望您的关键事件立即传递到您的窗口,并且这似乎是一种合理的方法,那么您的sendKeyEvent
方法会变得更加简单:
void MainWindow::sendKeyEvent()
{
if (sender() == ui->pushButton) {
QKeyEvent event(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier);
QApplication::sendEvent(this, &event);
}
else if (sender() == ui->pushButton_2) {
QKeyEvent event(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier);
QApplication::sendEvent(this, &event);
}
}
不过,有一种方法可以进一步简化事情。回想一下,QObject
支持动态属性。因此,您可以轻松地将键分配为按钮的属性,并在按下具有键属性的按钮时自动发送事件:
static const char keyPropKey[] = "key";
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->pushButton, &QPushButton::clicked, this, &MainWindow::sendKeyEvent);
connect(ui->pushButton_2, &QPushButton::clicked, this, &MainWindow::sendKeyEvent);
ui->pushButton.setProperty(keyPropKey, (int)Qt::Key_Enter);
ui->pushButton.setProperty(keyPropKey, (int)Qt::Key_A);
}
void MainWindow::sendKeyEvent()
{
auto key = sender().property(KeyPropKey);
if (key.isValid()) {
QKeyEvent event(QEvent::KeyPress, key.toInt(), Qt::NoModifier);
QApplication::sendEvent(this, &event);
}
}
最后,作为风格上的挑剔:没有理由让ui
成员成为指针。通过将其用作直接成员,您将避免一个堆分配和大量间接。