Нет, не видел и не вижу, как это сделать. Основной поток занят QGuiApplication::exec
Основной поток на самом деле не заблокирован, между каждым циклом цикла событий есть период, когда он прослушивает события из других потоков.
Вы можете использовать use QMetaObject::invokeMethod()
или инициировать слот через сигнал, в обоих случаях используя Qt::QueuedConnection
, который будет использовать это окно прослушивания для планирования вызова, который будет выполняться в следующем цикле цикла событий связанного потока.
QCoreApplication::postEvent()
должен работать, я использую его для отправки событий из пользовательского экранного контроллера, реализованного в QML, и он работает нормально, однако QML живет в основном потоке, поэтому, предположительно, ваша проблема заключается в том, что вы отправляете из другого потока. Поэтому я предполагаю, что если вы запланируете отправку событий через основной поток, он будет работать так, как ожидалось.
РЕДАКТИРОВАТЬ:
ОК, я понял, что не так, по какой-то причине отправка события в основной экземпляр приложения не перенаправляет его в механизм qml и последующие объекты qml. Но если получатель настроен на корневой объект qml engine->rootObjects().at(0)
, он работает... несколько...
События для элементов, находящихся в фокусе, принимаются через Keys.onPressed
и тому подобное, поэтому, если это все, что вам нужно, то все готово. Как ни странно, если я использую что-то вроде TextEdit
, этот подход не работает для записи текста в поле, хотя эмуляция таких вещей, как использование клавиш со стрелками для перемещения курсора, работает. Я даже могу нажать модификатор Shift и выделить текст. Но не писать текст...
Так что, возможно, это не так просто, как ожидалось. Надеюсь, кто-то сможет пролить свет на проблему. Для меня это слишком типично для 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++, к объекту в другом потоке и обратно к контроллеру, который затем отправляет событие. Он работает так, как предполагалось: данные из вторичного потока правильно отправляются в цикл событий, но отправленные события не работают должным образом.
person
dtech
schedule
26.01.2018