Qt如何捕获键盘事件?

Qt如何捕获键盘事件?,第1张

您好,Qt键盘事件属于Qt事件系统,所以事件系统中所有规则对按键事件都有效。下面关注点在按键特有的部分:

focus

一个拥有焦点(focus)的QWidget才可以接受键盘事件。有输入焦点的窗口是活动窗口或活动窗口子窗口或子子窗口等。

焦点移动的方式有以下几种:

按下Tab或Shift+Tab

注意:文本编译器(一般需要插入Tab),或者WebView(需要Tab来移动超链接焦点) 等

Qt中,需要输入Tab的地方可以用 Ctrl+Tab 或 Ctrl+Shift+Tab 替代。

点击一个QWidget

建议:只对接受文本输入的Widget启用该功能

按下键盘的快捷键

QLabel::setBuddy(), QGroupBox,以及 QTabBar 支持

使用鼠标滚轮

用户移动焦点

程序将决定被设置focus的Widget的哪一个子Widget获得焦点

注意:如果一个 Widget 已经 grabKeyboard,所有键盘事销局物件将发送到该Widget而不是获得焦点的Widget

focusPolicy

一个QWidget获得焦点的方式受 focusPolicy 控制

Qt::TabFocus

通过Tab键获得焦点

Qt::ClickFocus

通过被单击获得焦点

Qt::StrongFocus

可通过上面两种方式获得焦点

Qt::NoFocus

不能通过上两种方式获得焦点(默认值),setFocus仍可使其获得焦点

keypress和keyrelease

首先,我们要是Widget获得焦点,一般设置focusPolicy。

然亏液后腊碰要对按键进行响应,我们只需要直接重载:

keyPressEvent

keyReleaseEvent

注意:

对我们不处理的事件,要调用父类的相应事件处理函数。

如果widget当前没有焦点,考虑到事件转发:如果其子widget有焦点,那么该widget未处理的键盘事件将被转发过来。

有时输入焦点不在任何窗口中。这种情况发生在所有程序都是最小化的时候。这时,Windows将继续向活动窗口发送键盘消息,但是这些消息与发送给非最小化的活动窗口的键盘消息有不同的形式。

QKeyEvent

在windows下,与键盘事件有关的有8个消息:

对产生可显示字符的按键组合,Windows不仅给程序发送按键消息,而且还发送字符消息

有些键不产生字符,这些键包括shift键、功能键、光标移动键和特殊字符键如Insert和Delete。对于这些键,Windows只产生按键消息。

这些消息在Qt中只体现在QKeyEvent中。

对字符,可通过 QKeyEvent::text() 获得

其他键,QKeyEvent::key() 获得一个键值

event函数

由于 Tab 键被用来切换焦点,这使得它与众不同。

这是qwidget.cpp的event函数中的代码片段:

case QEvent::KeyPress:

{

QKeyEvent *k = (QKeyEvent *)event

bool res = false

if (!(k->modifiers() &(Qt::ControlModifier | Qt::AltModifier)))

{ //### Add MetaModifier?

if (k->key() == Qt::Key_Backtab || (k->key() == Qt::Key_Tab &&(k->modifiers() &Qt::ShiftModifier)))

res = focusNextPrevChild(false)

else if (k->key() == Qt::Key_Tab)

res = focusNextPrevChild(true)

if (res)

break

}

keyPressEvent(k)

}

如果我们需要处理Tab键,需要重载 event 函数。

Qt事件循环:从队列中不断取出消息、处理消息的过程。

Qt会接管windows的原生窗口消息,翻译轮猛成Qt消息,派发给程序下面的各个子对象。

起始于:QCoreApplication::exec()。 如果没有消息循环的话 Qt信号槽无法使用,举个例子

通过QueuedConnection连接的信号,其实是将一个事件压入了消息循环,如果没有QCoreApplication::exec(),那么这个消息循环将永远无法派发到指定的对象.

二:QObject的线程相关性

我们创建了一个QObject的时候,它会与创建自己的线程进行绑定;它参与的消息循环,其实就是它所在线程的消息循环,如果没有消息循环的话 QThread上的QObject甚至无法接受到事件;

另外就是两个不同的线程的QObject如果需要相互通信的话,只能通过QueuedConnection的方式,异步通知对方线程,在下一轮消息激桐脊循环处理QObject的消息。,QObject应该是它参与哪个消息循环,就由哪个来创建, 因此AutoQueuedConnection 直连 应该是在同一个线程的。不同的线程的话通过事件循环、信号与曹 是优雅的方式。重点: 不同线程的对象是无法直接通信的。需要通过事件。

三:

windows消息循环:

1: 注册窗口类,指定窗口处理函数

2:创建一个窗体  一般来说 创建很多明渗窗口 可以使用同一个窗口处理函数/

然后从消息队列里面取出事件、分发事件、系统将事件分发到不同窗口处理函数。

每一个线程有一份ThreadData,共享同一份事件队列。

四: Qt事件过滤器 :一个QObject对象可以监视发送其他的QObject对象的事件; 你要检测谁,说要去你这边注册一下,这不 有个label来注册了,注册之后我就可以截获你的事件。在我这里面 *** 作啦。 比如点击 画图啥的

1. bool QApplication::winEventFilter ( MSG * ) 消息程序在每次接受派州到消息时调用这个函尘晌蔽数。如果谨灶你想处理Qt不处理的窗口消息msg,请重新实现这个函数。 1. bool MainWindow::winEvent(MSG* pMsg) 2. { 3. if ( pMsg->message == WM_COPYDATA ) 4. { 5. COPYDATASTRUCT* pCopyDataStruct6. POSTERS_REC_STRUCT* pRec7. unsigned char* odapMsgPtr[MAX_POSTERS_SIZE]8. QString str9. pCopyDataStruct = (COPYDATASTRUCT*) pMsg->lParam10. switch (pCopyDataStruct->dwData) 11. { 12. case VALID_REC1 : 13. case VALID_REC2 : 14. { 15. (void)memcpy(odapMsgPtr, pCopyDataStruct->lpData, pCopyDataStruct->cbData)16. if (odapMsgPtr != NULL) 17. { 18. pRec = (POSTERS_REC_STRUCT *)odapMsgPtr19. class_data1 = pRec->var120. class_data2 = pRec->var221. } 22. } 23. } 24. return true25. } 26. else 27. return false28. } 29. Some Code on the web gives another example 30. #ifdef HAVE_WIN32_API 31. virtual bool winEventFilter(MSG * msg) { 32. SPW_InputEvent sbEvent33. if (SPW_TranslateEventWin32(msg, &sbEvent)) { 34. QWidget * focus = this->focusWidget()35. if (!focus) focus = this->activeWindow()36. if (focus) { 37. QCustomEvent qevent((QEvent::Type)SoQtInternal::SPACEBALL_EVENT, 38. (void *)&sbEvent)39. QApplication::sendEvent(focus, &qevent)40. } 41. } 42. #if (QT_VERSION >= 0x040000) 43. long result = 044. return QApplication::winEventFilter(msg, &result)45. #else 46. return QApplication::winEventFilter(msg)47. #endif The QSystemTrayIcon class provides an icon for an application in the system tray.

Modern operating systems usually provide a special area on the desktop, called the system tray or notification area, where long-running applications can display icons and short messages. 1. /* translates a Win32 event to a SPW_InputEvent. */ 2. int SPW_TranslateEventWin32(MSG * msg, SPW_InputEvent * sbEvent) 3. { 4. SiSpwEvent spwEvent5. SiGetEventData eventdata6. if (Spw_DeviceHandle != SI_NO_HANDLE) { 7. SiGetEventWinInit (&eventdata, msg->message, msg->wParam, msg->lParam)8. if (SiGetEvent (Spw_DeviceHandle, 0, &eventdata, &spwEvent) == SI_IS_EVENT) { 9. int i10. switch(spwEvent.type) { 11. case SI_MOTION_EVENT: 12. sbEvent->type = SPW_InputMotionEvent13. for(i=0i<6i++) { 14. sbEvent->sData[i] = (short)spwEvent.u.spwData.mData[i]15. } 16. break17. case SI_BUTTON_EVENT: 18. sbEvent->type = SPW_InputButtonPressEvent19. sbEvent->buttonState.pressed = (SiButtonPressed(&spwEvent) != SI_NO_BUTTON)20. sbEvent->buttonState.released = (SiButtonReleased(&spwEvent) != SI_NO_BUTTON)21. break22. } 23. return TRUE24. } 25. } 26. return FALSE27. } 小结:QT源码解析之Qt处理Windows消息的内容介绍完了,希望本文对你有帮助。来源:网络


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12524751.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-26
下一篇 2023-05-26

发表评论

登录后才能评论

评论列表(0条)

保存