我想从一个线程向我的应用程序发送一个Qt :: Key_Left信号。
我尝试使用以下代码发送我的事件,但没有任何反应:
QKeyEvent *event = new QKeyEvent ( QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier);
QCoreApplication::sendEvent (app, pressEvent);
实际上,这些函数是从正在侦听端口的线程调用的。这可能是问题是由于主线程没有调用这些函数引起的吗?
我只是让你知道我的应用是QML(不知道它是否有所改变)。我也试过静态函数QCoreApplication::postEvent
提前谢谢你。 对不起我的英语水平。
答案 0 :(得分:1)
不,我没有,我也不知道该怎么做。主线程很忙 使用QGuiApplication :: exec
主线程并未真正锁定,每个事件循环周期之间都有一段时间,它会侦听来自其他线程的事件。
您可以使用QMetaObject::invokeMethod()
或通过信号触发插槽,在两种情况下都使用Qt::QueuedConnection
,这将使用该监听窗口来安排在下一个事件循环周期中执行的调用。相关的线程。
QCoreApplication::postEvent()
应该可以工作,我使用它来发送来自用QML实现的自定义屏幕控制器的事件并且它工作正常,但是QML确实存在于主线程中,所以可能你的问题是你是从另一个线程发送。所以我假设如果您安排通过主线程发送的事件,它将按预期工作。
编辑:
好的,我弄清楚了什么是错的,出于某种原因,将事件发布到核心应用程序实例并不会将其转发到qml引擎和后续的qml对象。但是如果接收器被设置为根qml对象engine->rootObjects().at(0)
,它可以......有点......
通过Keys.onPressed
和类似的方式收到焦点项目的事件,因此如果您需要的话,那么您就已经完成了设置。奇怪的是,如果我使用像TextEdit
这样的方法,这种方法并不能将文本写入字段,尽管模拟诸如使用箭头键移动光标之类的东西确实有效。我甚至可以按移位修改器并选择文字。但不写文字......
所以也许它不像预期的那么简单。希望有人能够阐明这个问题。对我来说,这对于Qt来说太常见了,通常非常简单,显然逻辑上的东西最终没有按预期工作或者根本没有工作,因为有一些奇怪的实现细节。
以下是我使用的代码:
class Worker : public QObject {
Q_OBJECT
public slots:
void forwardKeyEvent(int k) {
sendKeyEvent(k);
}
signals:
void sendKeyEvent(int k);
};
class Controller : public QObject {
Q_OBJECT
public:
Controller(QQmlApplicationEngine * e) : engine(e) {
w = new Worker;
t = new QThread;
w->moveToThread(t);
connect(this, SIGNAL(sendKeyEvent(int)), w, SLOT(forwardKeyEvent(int)));
connect(w, SIGNAL(sendKeyEvent(int)), this, SLOT(receiveEvent(int)));
t->start();
}
public slots:
void receiveEvent(int k) {
QCoreApplication::postEvent(engine->rootObjects().at(0), new QKeyEvent(QEvent::KeyPress, (Qt::Key)k, Qt::NoModifier));
QCoreApplication::postEvent(engine->rootObjects().at(0), new QKeyEvent(QEvent::KeyRelease, (Qt::Key)k, Qt::NoModifier));
}
private:
Worker * w;
QThread * t;
QQmlApplicationEngine * engine;
signals:
void sendKeyEvent(int k);
};
// QML side
Column {
TextEdit {
width: 400
height: 200
Keys.onPressed: console.log("pressed ", event.key)
Keys.onReleased: console.log("released ", event.key)
}
Row {
Repeater {
model: [Qt.Key_Left, Qt.Key_S, Qt.Key_Right]
delegate: Rectangle {
width: 50
height: 50
color: "red"
Text {
anchors.centerIn: parent
text: modelData
}
MouseArea {
anchors.fill: parent
onClicked: Work.sendKeyEvent(modelData) // this is actually the worker controller
}
}
}
}
}
为了测试线程间事件发布,从QML到C ++控制器再到另一个线程中的对象,然后回到控制器然后发布事件,它来回做了一些疯狂的事情。它确实按预期工作 - 来自辅助线程的数据被正确地发布到事件循环中,但发布的事件无法按预期工作。
答案 1 :(得分:0)
实际上问题来自系统和用户,有必要将窗口集中在系统上以使其工作。