Qt 項目之虛擬鍵盤 V1.0
- 2019 年 10 月 6 日
- 筆記
最近做了一個虛擬鍵盤的小Demo,分享給大家。
一般我在做一個東西之前會上網查找資料,看下有幾種實現的方式。在Qt下開發虛擬鍵盤總體上可分為兩種方式——進程內部和進程外部。
在進程內部,虛擬鍵盤可以是一個QWidget小部件,顯示鍵盤按鈕,對用戶按下的按鍵生成鍵盤事件,之後讓具有焦點的可輸入的部件響應鍵盤事件。
在進程外部,虛擬鍵盤則可以被其他應用程序使用,不過這需要進程間通信。Qt上使用DBus作為IPC通訊方式,虛擬鍵盤被開發完成則是一個插件,需要放到Qt指定的目錄下,Qt應用程序在使用虛擬鍵盤前需要註冊一下,關於虛擬鍵盤和插件以後我們有機會會介紹的。今天展示的是在進程內部開發虛擬鍵盤的方式。
我最終想要實現的是點擊任何可輸入部件鍵盤都可以彈出來,但是開發的過程中發現可輸入部件沒有在被點擊後發出信號或事件,最後只好用窗體的鼠標事件來替代。
提幾個項目中會遇到的問題:
①像鍵盤這種有眾多按鈕的窗體,如何創建按鈕及其信號和槽
②響應按鈕後如何轉換為鍵盤事件,事件的接收者是誰
③希望鍵盤隨着窗體焦點移動而移動
有些問題我是沒有解決的,這次和大家分享的是虛擬鍵盤的初版,以後會有更新。使用插件開發鍵盤上面考慮的問題插件都預留了接口,不用像自己開發這樣要考慮諸多問題,不過同樣也知道了很多知識。
程序平台:ubuntu Qt 5.5.1
一、 KeyBoard 類
1. 該類繼承QWidget,是鍵盤窗體的實現類,有以下幾個對外接口
void showKeyboard(int globalX, int globalY); void hideKeyboard(); void setFocusWidget(QWidget *focusWidget);
分別是鍵盤的顯示、隱藏以及生成鍵盤事件的接收對象。
2. 眾多鍵盤按鈕的布局,主要使用QSignalMapper。為方便閱讀,使用的數據結構沒有列出
KeyBoard::KeyBoard(QWidget *parent) : QWidget(parent) { QGridLayout *gridLayout = new QGridLayout(this); QSignalMapper *mapper = new QSignalMapper(this); connect(mapper, SIGNAL(mapped(int)), SLOT(buttonClicked(int))); m_focusWidget = parent; this->setStyle("#E4E4E4", "#A2A2A2", "#DCDCDC", "#000000"); int row = 0; int column = 0; for (int i = 0; i < layoutSize; ++i) { if (keyboardLayout[i].key == NEXT_ROW_MARKER) { row++; column = 0; continue; } QPushButton *button = new QPushButton; button->setFixedWidth(40); button->setText(QString::fromLatin1(keyboardLayout[i].label)); mapper->setMapping(button, keyboardLayout[i].key); connect(button, SIGNAL(clicked()), mapper, SLOT(map())); gridLayout->addWidget(button, row, column); column++; } }
3. 生成鍵盤事件
void KeyBoard::buttonClicked(int key) { QKeyEvent *keyPressEvent = NULL; if ((key == Qt::Key_Enter) || (key == Qt::Key_Backspace)) keyPressEvent = new QKeyEvent(QEvent::KeyPress, key, Qt::NoModifier); else keyPressEvent = new QKeyEvent(QEvent::KeyPress, key, Qt::NoModifier, keyToCharacter(key)); if (keyPressEvent != NULL) { QGuiApplication::postEvent(m_focusWidget, keyPressEvent); } }
二、 用戶界面調用
主要重新實現了鼠標點擊事件,將位置發送給鍵盤顯示函數
void Widget::mousePressEvent(QMouseEvent *event) { if( event->type()== QEvent::MouseButtonPress ) { qDebug()<<"LeftButton"; if(event->pos().x()<= pos().x()) { m_keyboard->showKeyboard(this->pos().x(),this->y() + this->frameGeometry().height()); } } }
總結:
①沒有找到獲取當前編輯框焦點的方法,QWidget中有焦點改變的信號,還有事件過濾 器,接下來會從這兩方面入手。
②QLineEdit等編輯框沒有響應鼠標點擊的信號或事件,需要重新繼承實現。
最後效果如圖:
