46

Qt 项目之虚拟键盘 V1.0

 4 years ago
source link: https://www.tuicool.com/articles/IBNfUnM
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

最近做了一个虚拟键盘的小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 等编辑框没有响应鼠标点击的信号或事件,需要重新继承实现。

最后效果如图:

nErmyyM.png!web

需要参考的小伙伴可在公众号后台留下联系方式。

eIZJ3iQ.jpg!web


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK