QT软键盘-兼容qt4和qt5

前言

由于需要在触摸屏上实现输入操作,但是触摸屏的qt版本为qt4,后期也有可能会换为qt5,所以为了之后移植程序能够直接移植,所以重新搭建了一套输入法架构

实现的原理

基于qt的焦点切换事件来实现,所有继承子QWidget的控件可以获得焦点。另外焦点控件理论来说有且只会有一个,所以我们在程序里只需要连接QApplication的focusChange信号就可以了。当有新的焦点切换时,判断焦点是否需要使用输入法,然后显示键盘,在键盘输入完成后移除当前焦点控件的焦点,让键盘消失。

关键代码

输入法类

首先是输入法类,这个类是单例类,因为要监控全局。主要完成焦点控件获取和对键盘控件的管理


class InputMethodPrivate;
class AbstractKeyBoard;
class QCP_LIB_DECL InputMethod : public QObject
{
    Q_OBJECT
public:
    ~InputMethod();

    //初始化,会初始化默认键盘Numeric_Keyboard和Pinyin_Keyboard
    void initSorftKeyBoard();
    //外部注册键盘,可覆盖原有键盘
    void registerKeyBoard(const QString &keyBoardName, AbstractKeyBoard *keyBoard);
    //移除键盘
    void removeKeyBoard(const QString &keyBoardName);
signals:
    void signal_comfirm(QWidget *focus,const QVariant &value);
private:
    explicit InputMethod(QObject *parent = 0);
private:
    InputMethodPrivate *d_ptr;
    Q_DECLARE_PRIVATE(InputMethod)
    Q_DISABLE_COPY(InputMethod)
    friend class Singleton<InputMethod>;

};
#define InputMethodInstance Singleton<InputMethod>::instance()

头文件很简单,只提供给外部调用的函数就行了。外部需要获取键盘输入的值时可以连接信号signal_comfirm,拿到当前焦点控件和键盘确认输入的值。

InputMethodPrivate::InputMethodPrivate():
    m_curKeyboard(NULL),
    m_focusWidget(NULL),
    q_ptr(NULL)
{
    connect(qApp,SIGNAL(focusChanged(QWidget*,QWidget*)),this,SLOT(slot_focusChanged(QWidget*,QWidget*)));
}

在私有类的构造中连接焦点切换信号

void InputMethodPrivate::slot_focusChanged(QWidget *old, QWidget *now)
{
    Q_UNUSED(old)
    m_focusWidget = now;
    if(!checkIsKeyBoard(now))//判断是否是键盘上的控件,不能是键盘的控件
    {
        if(m_curKeyboard)//判断当前是否有键盘在使用,如果使用则关闭键盘
        {
            m_curKeyboard->cancel();
            m_curKeyboard = NULL;
        }
        //判断是否是可输入控件,并返回输入控件指定的键盘名称
        QString keyboardName = isInputWidget(now);
        if(!keyboardName.isEmpty())
        {
            showKeyBoard(keyboardName,now);//显示指定键盘
        }
    }
}

焦点切换的槽函数实现

键盘抽象类

键盘可以有多个,对于只能输入数字的使用数字键盘,需要输入中文可能就要使用拼音键盘,所以需要对键盘类进行抽象,把键盘的公用特性拿出来即可。具体的键盘只要继承这个抽象类即可。


#include <QWidget>
#include "inputmethod.h"

class AbstractKeyBoardPrivate;
class QCP_LIB_DECL AbstractKeyBoard : public QWidget
{
    Q_OBJECT
public:
    enum Position{
        CONTROL = 0, // 显示位置在控件边上
        TOP, //屏幕顶部
        BOTTOM, //屏幕底部
        Embedded //同主程序显示位置对齐
    };
    explicit AbstractKeyBoard(QWidget *parent = 0);

    //显示键盘
    virtual void showKeyboard(QWidget *focusWidget);
    //键盘确认输入
    virtual void confirm();
    //键盘取消
    virtual void cancel();
    //给键盘输入当前数据
    virtual void setCurData(const QVariant &_data) = 0;
    //当前数据
    virtual QVariant curData() = 0;
    //焦点控件
    virtual void setFocusWidget(QWidget *focusWidget) = 0;
    virtual QWidget *focusWidget() = 0;
    //刷新键盘显示位置
    virtual void updatePos(Position type,QWidget *focusWidget);
    //提交数据,会设置控件数据
    virtual void commitData(const QVariant &_data);
    //动画使能
    void setAnimationEnable(bool enabled);
    bool animationEnable();
signals:
    //当键盘确认输入后,发送此信号,需要在实现类值调用此信号
    void signal_confirm(const QVariant &value);
    //在confirm和cancel默认发送
    void signal_hide();
private:
    QSharedPointer<AbstractKeyBoardPrivate> d_ptr;
    Q_DECLARE_PRIVATE(AbstractKeyBoard)
    Q_DISABLE_COPY(AbstractKeyBoard)
};

键盘的基本操作就是显示、输入值、关闭。基本也就围绕着这些来进行扩展。我这边因为项目中键盘不能直接输入到控件中,所有会对控件数据进行获取和提交,具体的数据展示由焦点控件实现。

AbstractKeyBoard::AbstractKeyBoard(QWidget *parent) : QWidget(parent),d_ptr(new AbstractKeyBoardPrivate)
{
    d_ptr->q_ptr = this;
    setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::Tool
               #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
                   | Qt::WindowDoesNotAcceptFocus
               #endif
                   );
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
    setAttribute(Qt::WA_X11DoNotAcceptFocus);//qt5中设置此标志会导致在清除焦点后控件又会重新获取焦点
#endif
    d_func()->initAnimation();
}

FramelessWindowHint :去除外边框

WindowStaysOnTopHint :保证键盘一定在最上方,避免键盘被盖住

WindowDoesNotAcceptFocus :qt5以上保证键盘不会获取焦点,避免焦点控件消失

WA_X11DoNotAcceptFocus:qt4下取消焦点获取,这个参数qt5上也有,但是经过测试发现关闭键盘后取消焦点控件后,这个焦点控件会重新获取焦点,导致键盘又会显示出来,但是在嵌入式linux和Ubuntu系统下却没有(qt4版本,暂时未试qt5版本)

void AbstractKeyBoard::commitData(const QVariant &_data)
{
    QWidget *_focusWidget = this->focusWidget();
    if(_focusWidget == NULL)return;
    const QMetaObject *metaObj = _focusWidget->metaObject();
    if(metaObj == NULL)return;
    QVariant keyboardData = _focusWidget->property(KeyBoard::KEY_KeyBoardData.toLatin1().data());
    if(keyboardData.isValid())//自定义数据提交方法
    {
        metaObj->invokeMethod(_focusWidget,
                              "setKeyBoardData",
                              QGenericArgument(keyboardData.typeName(),_data.data()));
    }
    else if(_focusWidget->inherits("QLineEdit") ||
             _focusWidget->inherits("QTextEdit"))//默认使用控件的text属性
    {
        QVariant text = _focusWidget->property("text");
        metaObj->invokeMethod(_focusWidget,
                              "setText",
                              QGenericArgument(text.typeName(),_data.data()));
    }
    else if(_focusWidget->inherits("QPlainTextEdit"))
    {
        QVariant plainText = _focusWidget->property("plainText");
        metaObj->invokeMethod(_focusWidget,
                              "setPlainText",
                              QGenericArgument(plainText.typeName(),_data.data()));
    }
}

给焦点控件提交数据,这边是通过元对象QMetaObject 来实现方法调用,这样的好处是不需要知道具体的焦点控件类是什么。其中setKeyBoardData时自定义的数据提交方法,只需要在任何需要键盘输入的控件类中实现setKeyBoardData函数就可以获取键盘提交的数据,来保证通用性。

程序运行截图

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
QT软键盘是一款可以在QT开发环境下使用的虚拟键盘组件。它可以用于在移动设备、嵌入式系统或者桌面应用中提供虚拟键盘输入功能。用户可以通过触摸屏或者鼠标点击等方式,使用QT软键盘来输入文字、数字或者符号。 谈到Google,它是一家全球知名的互联网科技公司,也是目前最受欢迎的搜索引擎之一。Google公司提供了许多优秀的产品和服务,例如谷歌搜索、谷歌地图、谷歌翻译等,这些产品和服务都以其高效、准确和强大的搜索能力著称。 将QT软键盘与Google结合起来使用,可以为用户在QT应用中提供便捷的搜索体验。例如,当用户在一个需要搜索功能的QT应用中需要输入关键词时,可以通过打开QT软键盘来输入关键词,然后通过与Google的集成,将输入的关键词直接发送给Google搜索引擎进行搜索。这样,用户无需离开QT应用,就可以轻松地完成搜索操作,并快速获取结果。 QT软键盘与Google的结合,不仅可以提高用户的使用便利性和效率,还能够为QT应用增加更多的功能。通过与Google的API接口进行对接,可以实现更加智能化的搜索功能,并且能够根据用户的搜索历史和行为,为其提供更加个性化和精准的搜索结果。这样,不仅能够提升用户体验,还能够为开发者带来更多的商业机会。 综上所述,将QT软键盘与Google结合使用,可以为用户提供便捷高效的搜索体验,为开发者增加更多的应用功能和商业机会。这种结合为用户带来了更加智能化和个性化的搜索体验,也为开发者在竞争激烈的市场中提供了更多的发展机会。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值