您的位置:首页 > 编程语言 > Qt开发

Qt软键盘——解决Qt例子输入失败的问题

2016-11-14 22:10 555 查看
    最近做嵌入式UI,在触摸屏上输入时需要一个软键盘,去找Qt示例时,发现有一个例子example/tools/inputpanel,我安装的版本没有这个例子,于是我就以“example/tools/inputpanel”为关键词搜索了一下,发现了在这个地方有:http://doc.qt.io/qt-4.8/qt-tools-inputpanel-example.html

    在这个网页的下面,有8个文件,似乎无法直接下载,但可以看到源码,于是我是通过复制/粘贴的方式保存了这8个文件。我将代码复制过来,放到ubuntu虚拟机上,编译运行后,发现当鼠标点击一个输入框QLineEdit时,数字键盘的确能弹出来(如下图)



但是,无论怎么点击数字键,输入框中总不出现数字或符号,试了多次都是这样,接下来我开始找原因。

1.按下数字键,是否有事件响应呢?

     在myinputpanel.cpp中,函数(SLOT)void
MyInputPanel::buttonClicked(QWidget*w)
负责响应Input
Panel中所有输入键被按下时所产生的信号(SIGNAL),函数的内容为:

void MyInputPanel::buttonClicked(QWidget *w)
{
QChar chr = qvariant_cast<QChar>(w->property("buttonValue"));
emit characterGenerated(chr);
}


显然当键被按下时,相应的"buttonValue"(动态属性)值通过信号(characterGenerated(QChar))被传递,在发射(emit)之前,我加了一句

qWarning(QString(chr).toStdString().c_str());


即每输入一个字符,打印一下传递的字符,发现打印正常。
而信号(SIGNAL)characterGenerated(chr)的槽为myinputpanelcontext.cpp中的函数:

void MyInputPanelContext::sendCharacter(QChar character)
{
QPointer<QWidget> w = focusWidget();
if (!w)
return;    //从这里返回

QKeyEvent keyPress(QEvent::KeyPress, character.unicode(), Qt::NoModifier, QString(character));
QApplication::sendEvent(w, &keyPress);

if (!w)
return;

QKeyEvent keyRelease(QEvent::KeyPress, character.unicode(), Qt::NoModifier, QString());
QApplication::sendEvent(w, &keyRelease);

}


在这个函数里通过qWarning添加打印信息,发现函数每次都从第一个return那里结束,说明w为空。

2.为什么输入不成功?

        为什么w为空呢?思考后得出结论:这个函数的做法是获取原窗口中焦点控件,然后将键盘上的输入值传递给它。而当我们在软键盘上输入时,焦点控件会变为我们刚点击的输入键QPushButton,而不是我们之前选择的QLineEdit

3.这个问题怎么解决?

我的解决办法是,信号(SIGNAL)characterGenerated(chr)发射时将上一个焦点传递过去,即把characterGenerated(chr)改为

void characterGenerated(QChar character, QWidget *w)
{
QChar chr = qvariant_cast<QChar>(w->property("buttonValue"));
emit characterGenerated(chr,lastFocusedWidget);
}


上面的lastFocusedWidget是在myinputpanel.cpp的

void MyInputPanel::saveFocusWidget(QWidget * /*oldFocus*/, QWidget*newFocus)
{
if (newFocus != 0 && !this->isAncestorOf(newFocus)) {
lastFocusedWidget = newFocus;
}
}


中定义的。

同样地,将槽也这样修改

void MyInputPanelContext::sendCharacter(QChar character, QWidget *w1)
{
QPointer<QWidget> w = w1;
if (!w)
return;
QKeyEvent keyPress(QEvent::KeyPress, character.unicode(), Qt::NoModifier, QString(character));
QApplication::sendEvent(w, &keyPress);

if (!w)
return;

QKeyEvent keyRelease(QEvent::KeyPress, character.unicode(), Qt::NoModifier, QString());
QApplication::sendEvent(w, &keyRelease);

}


【注意】修改函数时,记得还要修改它的定义和声明,同时还要修改连接SIGNAL和SLOT的connect函数。

4.如何实现删除功能?

其实很简单,我只不过将原图中的#变成了←,其实传递的"buttonValue"还是为#,所以只需在sendCharacter(QCharcharacter,
QWidget *w1)中这样修改即可:

void MyInputPanelContext::sendCharacter(QChar character, QWidget *w1)
{
QPointer<QWidget> w = w1;
if (!w)
return;

if(character.unicode() == '#')
{
QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier);
QApplication::sendEvent(w, &keyPress);
}
else
{
QKeyEvent keyPress(QEvent::KeyPress, character.unicode(), Qt::NoModifier, QString(character));
QApplication::sendEvent(w, &keyPress);
}

if (!w)
return;

QKeyEvent keyRelease(QEvent::KeyPress, character.unicode(), Qt::NoModifier, QString());
QApplication::sendEvent(w, &keyRelease);
}


5.如何将这个功能移植到其他项目中?

(1)将这些文件与原项目文件放在一起(不包括.pro文件和main.cpp);
(2)在原项目的.pro文件中添加软键盘所用到的文件(.cpp、.h、.ui文件等);
(3)在原项目的main.cpp文件中添加代码:

MyInputPanelContext*ic = new MyInputPanelContext;
app.setInputContext(ic);


【注意】根据实际情况,不一定是app. setInputContext(ic),要看QApplication的对象名。

6.下面是效果图





如果需要源码,可以给我发邮件:fengyuyixin@qq.com
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: