0


Qt自定义虚拟键盘,模拟Qt插件虚拟键盘(数字键盘+全键盘),支持大小写,中英文,适用Windows Linux。

1.背景

    Qt自带的虚拟键盘插件(qtvirtualkeyboard)不是很好用,界面大小、字体大小、界面位置不能任意调整等问题。

2.项目环境

    Qt 5.12.3

    Desktop Qt 5.12.3 MinGW 64-Bit

    Windows10

3.项目效果

4.部分代码解析(以全键盘为例)

4.1按键分类(可有可无)

     首先把想要的键盘样式跟按键布局好,键盘所有的按键均使用QPushButton,为了区分不同按钮的功能,减少后面按钮触发时的判断,用setProperty设置按钮属性。
ui->btnQ_1->setProperty("btnLetter", true);
...
ui->btnSpace->setProperty("btnSpace", true);
...
ui->btnAt_->setProperty("btnOther", true);
...
ui->btnEnter->setProperty("btnFunc", true);
...
ui->btnPageUp->setProperty("btnPage", true);
...
ui->btnSelect1->setProperty("btnSelect", true);
    上面分成了六种不同的属性,其中包括字母、回退(比较特殊,就单独拎出来)、其他(区分标点符)、功能(切换大小写中英文),待选(中文会使用到),翻页(中文会使用到)。这个分类看个人喜好,因为在Linux设备上使用的时候还要触发不同音效,就分成这样了。

4.2绑定全部的按键信号

 QList<QPushButton *>myBtn = this->findChildren<QPushButton *>();
    foreach(QPushButton *btn, myBtn)
        connect(btn, &QPushButton::clicked, this, &normalKeyboard::fBtnClick);
    获取全部按键的clicked信号,绑定同一个槽函数,不管哪个按键触发,都在这个槽函数里面判断是哪一种按键功能。

4.3获取判断的条件

QObject *sender() const;
    sender()是Qt信号与槽中比较重要的一个概念,它表示发射信号的对象,可以是任意QObjecr的派生类。如QPushButton,QLineEdit等。多个不同信号绑定的同一个槽函数时,它能在槽函数中帮我们快速找到发送的信号的对象来自哪个。

4.4绑定改变焦点的信号

connect(qApp, SIGNAL(focusChanged(QWidget *, QWidget *)), this, SLOT(fFocusChanged(QWidget *, QWidget *)));
    Qt的<QApplication>提供了很多的全局信号,在程序的任何位置都可以接收处理,focusChanged是当系统焦点发生改变的时候,就会发出信号,这里可以用来获取触摸时需要输入的输入框。

4.5添加事件过滤器

bool normalKeyboard::eventFilter(QObject *watched, QEvent *event)
{
    ...
}
qApp->installEventFilter(this);
    过滤器对象的 eventFilter()函数可以接受或拒绝拦截到的事件,若该函数返回 **false,** 则表示事件需要作进一步处理,此时事件会被发送到目标对象本身进行处理(注意: 这里并未向父对象进行传递),若 evetnFilter()返回 **true**,**则表示****停止处理该事件**,此时 **目标对象**和**后面安装的事件过滤器 **就无法获得该事件。

4.6改变键盘字体大小

void normalKeyboard::fChangeKeyboardFontSize(int fontSize)
{
    QFont myFont(this->font().family(), fontSize);
    QList<QPushButton *> myBtn = this->findChildren<QPushButton *>();
    foreach (QPushButton * btn, myBtn)
    {
        btn->setFont(myFont);
    }
    ui->showPinyin->setFont(myFont);
}

4.7设置键盘的大小和位置

QPoint pos = QPoint();
this->setGeometry(pos.x(), pos.y(), width, height);

通过QPoint获取键盘界面的中心点,然后重新布局出键盘的位置和大小。它需要四个参数,分别是横坐标、纵坐标、宽度和高度。这样就可以实现在任意位置调出键盘了。

4.8设置为单例模式,保证一个程序只存在一个输入法实例对象

 static normalKeyboard *Instance() {
        if (!_instance) {
            _instance = new normalKeyboard;
        }
        return _instance;
    }

static normalKeyboard *_instance;       //实例对象

4.9中文输入

    当前的项目采用数据库查询的方式,虽然说不是很智能,输入的文字也不算全,但基本上满足日常使用了。

5.代码展示

    讲了不少废话,还是贴源码吧!

5.1键盘部分

#ifndef NORMALKEYBOARD_H
#define NORMALKEYBOARD_H

#include <QWidget>
#include <QDesktopWidget>
#include <QLineEdit>
#include <QPushButton>
#include <QTimer>
#include <QPainter>
#include <QMouseEvent>
#include <QDebug>

#include "pinyinsql.h"

namespace Ui {
class normalKeyboard;
}

class normalKeyboard : public QWidget
{
    Q_OBJECT

public:
    explicit normalKeyboard(QWidget *parent = nullptr);
    ~normalKeyboard();

    //单例模式,保证一个程序只存在一个输入法实例对象
    static normalKeyboard *Instance() {
        if (!_instance) {
            _instance = new normalKeyboard;
        }
        return _instance;
    }

    void fNormalKeyboardInit();

    void fBackspace();

    void fInsertStr(QString str);

    bool fCheakPressType();

    void fChangeKeyboardFontSize(int fontSize);

    void fResetKeyboardSize(QLineEdit *lineedit, QString style, int width, int high, int fontSize);

    void fKeyboardPropertyInit();

    void fChangeInputType(QString type);

    void fShowChinese();
public slots:
    void fBtnLongClick();

    void fBtnClick();

    void fFocusChanged(QWidget *, QWidget *);

protected:
    bool eventFilter(QObject *watched, QEvent *event);

    void mousePressEvent(QMouseEvent *e);

    void mouseReleaseEvent(QMouseEvent *);
private slots:
    void on_showPinyin_textChanged(const QString &arg1);

private:
    Ui::normalKeyboard *ui;

    static normalKeyboard *_instance;       //实例对象

    int g_DeskWidth,                        //桌面的宽
        g_DeskHeight,                       //桌面的高
        g_KeyboardWidth,                    //键盘的宽
        g_KeyboardHeight,                   //键盘的高
        g_CurrentChineseCount;              //显示当前行第一个的下标

    QLineEdit *p_CurrentLineEdit = nullptr; //当前聚焦的输入行

    bool g_IsFirstClick,                    //是否首次加载
         g_IsPressed,                       //是否长按退格
         g_IsMousePressd;

    QPushButton *p_LongPressedBtn = nullptr;//长按按钮

    QTimer *p_LongPressTimer = nullptr;     //长按定时器

    QString g_CurrentFocusType;             //当前焦点控件的类型

    QString g_CurrentInputType;             //当前输入法类型

    QPoint g_MousePoint;

    QStringList g_ChineseList;

    QList <QPushButton *> g_SelectList;

};

#endif // NORMALKEYBOARD_H
#include "normalkeyboard.h"
#include "normalkeyboard.h"
#include "ui_normalkeyboard.h"

normalKeyboard::normalKeyboard(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::normalKeyboard)
{
    ui->setupUi(this);

    this->setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);

    fKeyboardPropertyInit();
    fNormalKeyboardInit();
}

normalKeyboard::~normalKeyboard()
{
    delete ui;
}

void normalKeyboard::fNormalKeyboardInit()
{
    g_IsFirstClick = true;
    g_CurrentChineseCount = 0;
    g_IsPressed = false;
    g_CurrentFocusType.clear();
    g_CurrentInputType = "InputUpper"; //InputLower InputChinese InputNumber_C InputNumber_E
    g_IsMousePressd = false;

    fChangeInputType("InputUpper");

    //获取桌面的宽高
    QDesktopWidget myAppWidget;
    g_DeskWidth = myAppWidget.availableGeometry().width();
    g_DeskHeight = myAppWidget.availableGeometry().height();

    p_LongPressTimer = new QTimer;
    connect(p_LongPressTimer, &QTimer::timeout, this, &normalKeyboard::fBtnLongClick);

    QList<QPushButton *>myBtn = this->findChildren<QPushButton *>();
    foreach(QPushButton *btn, myBtn)
        connect(btn, &QPushButton::clicked, this, &normalKeyboard::fBtnClick);

    //绑定全部改变焦点的信号
    connect(qApp, SIGNAL(focusChanged(QWidget *, QWidget *)), this, SLOT(fFocusChanged(QWidget *, QWidget *)));
    qApp->installEventFilter(this);
}

void normalKeyboard::fKeyboardPropertyInit()
{
    ui->btnQ_1->setProperty("btnLetter", true);
    ui->btnW_2->setProperty("btnLetter", true);
    ui->btnE_3->setProperty("btnLetter", true);
    ui->btnR_4->setProperty("btnLetter", true);
    ui->btnT_5->setProperty("btnLetter", true);
    ui->btnY_6->setProperty("btnLetter", true);
    ui->btnU_7->setProperty("btnLetter", true);
    ui->btnI_8->setProperty("btnLetter", true);
    ui->btnO_9->setProperty("btnLetter", true);
    ui->btnP_0->setProperty("btnLetter", true);
    ui->btnA_->setProperty("btnLetter", true);
    ui->btnB_->setProperty("btnLetter", true);
    ui->btnD_->setProperty("btnLetter", true);
    ui->btnF_->setProperty("btnLetter", true);
    ui->btnG_->setProperty("btnLetter", true);
    ui->btnH_->setProperty("btnLetter", true);
    ui->btnJ_->setProperty("btnLetter", true);
    ui->btnK_->setProperty("btnLetter", true);
    ui->btnL_->setProperty("btnLetter", true);
    ui->btnZ_->setProperty("btnLetter", true);
    ui->btnX_->setProperty("btnLetter", true);
    ui->btnC_->setProperty("btnLetter", true);
    ui->btnV_->setProperty("btnLetter", true);
    ui->btnB_->setProperty("btnLetter", true);
    ui->btnN_->setProperty("btnLetter", true);
    ui->btnM_->setProperty("btnLetter", true);

    ui->btnSpace->setProperty("btnSpace", true);

    ui->btnAt_->setProperty("btnOther", true);
    ui->btnPeriod->setProperty("btnOther", true);
    ui->btnApostrophe->setProperty("btnOther", true);
    ui->btnMinus->setProperty("btnOther", true);
    ui->backspace->setProperty("btnOther", true);

    ui->btnShiftLeft->setProperty("btnFunc", true);
    ui->btnSymbol->setProperty("btnFunc", true);
    ui->btnLanguage->setProperty("btnFunc", true);
    ui->btnShiftRight->setProperty("btnFunc", true);
    ui->btnEnter->setProperty("btnFunc", true);

    ui->btnPageUp->setProperty("btnPage", true);
    ui->btnPageDown->setProperty("btnPage", true);

    g_SelectList << ui->btnSelect1 << ui->btnSelect2 << ui->btnSelect3 << ui->btnSelect4 << ui->btnSelect5
                    << ui->btnSelect6 << ui->btnSelect7 << ui->btnSelect8 << ui->btnSelect9;

    ui->btnSelect1->setProperty("btnSelect", true);
    ui->btnSelect2->setProperty("btnSelect", true);
    ui->btnSelect3->setProperty("btnSelect", true);
    ui->btnSelect4->setProperty("btnSelect", true);
    ui->btnSelect5->setProperty("btnSelect", true);
    ui->btnSelect6->setProperty("btnSelect", true);
    ui->btnSelect7->setProperty("btnSelect", true);
    ui->btnSelect8->setProperty("btnSelect", true);
    ui->btnSelect9->setProperty("btnSelect", true);
}

//焦点改变
void normalKeyboard::fFocusChanged(QWidget *p_PreceWidget, QWidget *p_CurrentWidget)
{
    if(p_CurrentWidget != nullptr && !this->isAncestorOf(p_CurrentWidget))
    {
#ifndef __arm__
        if (p_PreceWidget == 0 && !g_IsFirstClick)
            return;
#endif
        g_IsFirstClick = false;

        QWidget *p_ModalWidget = QApplication::activeModalWidget();
        QWidget *p_PopupWidget = QApplication::activePopupWidget();
        QWidget *p_Widget = QApplication::activeWindow();

        /*
        Qt::NonModal       非模态对话框
        Qt::WindowModal      窗口级模态对话框,即只会阻塞父窗口、父窗口的父窗口及兄弟窗口。(半模态对话框)
        Qt::ApplicationModal    应用程序级模态对话框,即会阻塞整个应用程序的所有窗口。(半模态对话框)
        */
        if(p_ModalWidget !=nullptr && p_ModalWidget->inherits("QDialog"))
        {
            Qt::WindowModality Modality = p_ModalWidget->windowModality();

            if(Qt::ApplicationModal == Modality)
            {
                p_CurrentLineEdit = nullptr;
                g_CurrentFocusType.clear();
                g_CurrentInputType = "InputUpper";
                fChangeInputType(g_CurrentInputType);
                this->setVisible(false);
                return;
            }
        }
        if(p_CurrentWidget->inherits("QLineEdit"))
        {
            p_CurrentLineEdit = (QLineEdit *) p_CurrentWidget;
            g_CurrentFocusType = "QLineEdit";
        }
        else
        {
            p_CurrentLineEdit = nullptr;
            g_CurrentFocusType.clear();
            g_CurrentInputType = "InputUpper";
            fChangeInputType(g_CurrentInputType);
            this->setVisible(false);
        }
    }
}

void normalKeyboard::mousePressEvent(QMouseEvent *e)
{
    if (e->button() == Qt::LeftButton)
    {
        g_IsMousePressd = true;
        g_MousePoint = e->globalPos() - this->pos();
        e->accept();
    }
}

void normalKeyboard::mouseReleaseEvent(QMouseEvent *)
{
    g_IsMousePressd = false;
}

//事件过滤器
bool normalKeyboard::eventFilter(QObject *watched, QEvent *event)
{
    if(event->type() == QEvent::MouseButtonPress)
    {
        if(!g_CurrentFocusType.isEmpty() && watched != ui->btn_keyboard_close)
        {

        }
        p_LongPressedBtn = (QPushButton *)watched;
        if(fCheakPressType())
        {
            g_IsPressed = true;
            p_LongPressTimer->start(500);
        }
        return false;
    }
    else if(event->type() == QEvent::MouseButtonRelease)
    {
        p_LongPressedBtn = (QPushButton *)watched;
        if(fCheakPressType())
        {
            g_IsPressed = true;
            p_LongPressTimer->stop();
        }
        return false;
    }
    else if(event->type() == QEvent::KeyPress)
    {
        if(!isVisible())
            return QWidget::eventFilter(watched, event);
        QString myStr;
        QList<QPushButton *>myBtn = this->findChildren<QPushButton *>();
        foreach(QPushButton *btn, myBtn)
        {
            if(btn->text() == myStr)
            {
                btn->click();
                return true;
            }
        }
        return false;
    }
    return QWidget::eventFilter(watched, event);
}

bool normalKeyboard::fCheakPressType()
{
    //只有属于输入法键盘的合法按钮才继续处理
    if (p_LongPressedBtn->property("btnLetter").toBool() || p_LongPressedBtn->property("btnOther").toBool())
        return true;
    else
        return false;
}

//点击
void normalKeyboard::fBtnClick()
{
    if(g_CurrentFocusType == "")
        return;
    else
    {
        QPushButton *myBtn = (QPushButton *)sender();
        QString objectName = myBtn->objectName();

        if(objectName == "btn_backspace")
            fBackspace();
        else if(objectName == "btn_keyboard_close")
        {
            this->setVisible(false);
        }
        else if(objectName == "btnF_")
        {
            if (g_CurrentInputType == "InputNumber_E" || g_CurrentInputType == "InputNumber_C")
            {
                fInsertStr("&");
            }
            else
            {
                fInsertStr(ui->btnF_->text());
            }
        }
        else if (objectName == "btnShiftRight" || objectName == "btnShiftLeft")
        {
            if (g_CurrentInputType == "InputUpper")
            {
                g_CurrentInputType = "InputLower";
            }
            else if (g_CurrentInputType == "InputLower")
            {
                g_CurrentInputType = "InputUpper";
            }
            fChangeInputType(g_CurrentInputType);
        }
        else if (objectName == "btnLanguage")
        {
            if (g_CurrentInputType == "InputChinese")
            {
                g_CurrentInputType = "InputUpper";
            }
            else if (g_CurrentInputType == "InputNumber_C")
            {
                g_CurrentInputType = "InputNumber_E";
            }
            else if (g_CurrentInputType == "InputNumber_E")
            {
                g_CurrentInputType = "InputNumber_C";
            }
            else if (g_CurrentInputType == "InputUpper" || g_CurrentInputType == "InputLower")
            {
                g_CurrentInputType = "InputChinese";
            }
            fChangeInputType(g_CurrentInputType);
        }
        else if (objectName == "btnSymbol")
        {
            if (g_CurrentInputType == "InputChinese")
            {
                g_CurrentInputType = "InputNumber_C";
            }
            else if (g_CurrentInputType == "InputUpper" || g_CurrentInputType == "InputLower")
            {
                g_CurrentInputType = "InputNumber_E";
            }
            else if (g_CurrentInputType == "InputNumber_E" || g_CurrentInputType == "InputNumber_C")
            {
                g_CurrentInputType = "InputUpper";
            }
            fChangeInputType(g_CurrentInputType);
        }
        else if (objectName == "backspace")
        {
            //如果当前是中文模式,则删除对应拼音,删除完拼音之后再删除对应文本输入框的内容
            if (g_CurrentInputType == "InputChinese")
            {
                QString pinyin = ui->showPinyin->text();
                int len = pinyin.length();
                if (len > 0)
                    ui->showPinyin->setText(pinyin.left(len - 1));
                else
                    fBackspace();
            }
            else
                fBackspace();
        }
        else if (objectName == "btnPageUp" || objectName == "btnPageDown")
        {
            //中文模式才能翻页
            if(objectName == "btnPageUp")
            {
                if(g_ChineseList.count() >= 9 && g_CurrentChineseCount >= 9 )
                   g_CurrentChineseCount -= 9;
            }
            else
            {
                if(g_ChineseList.count() > 9 && g_CurrentChineseCount < g_ChineseList.count() - 9)
                    g_CurrentChineseCount += 9;
            }
            //清空待选按钮
            for(int i = 0; i < 9; i++)
            {
                g_SelectList.at(i)->setText("");
            }
            fShowChinese();
        }
        else if (objectName == "btnSpace")
        {
            if(g_CurrentInputType == "InputChinese")
            {
               if (ui->btnSelect1->text() != "")
               {
                    fInsertStr(ui->btnSelect1->text());
                    ui->showPinyin->clear();
               }
               else
                    fInsertStr(" ");
            }
            else
                fInsertStr(" ");
        }
        else if (objectName == "btnEnter")
        {
            if(g_CurrentInputType == "InputChinese")
            {
                if (ui->btnSelect1->text() != "")
                {
                     fInsertStr(ui->btnSelect1->text());
                     ui->showPinyin->clear();
                }
            }
        }
        else
        {
            if(g_CurrentInputType == "InputChinese")
            {
                if(myBtn->property("btnSelect").toBool())
                {
                    QString myStr = myBtn->text();
                    fInsertStr(myStr);
                    ui->showPinyin->setText("");
                }
                else if (myBtn->property("btnOther").toBool())
                {
                    QString myStr = myBtn->text();
                    fInsertStr(myStr);
                }
                else
                {
                    QString myStr = myBtn->text();
                    ui->showPinyin->insert(myStr);
                }

            }
            else
            {
                QString myStr = myBtn->text();
                fInsertStr(myStr);
            }
        }
    }
}

//插入
void normalKeyboard::fInsertStr(QString str)
{
    if (g_CurrentFocusType == "QLineEdit")
        p_CurrentLineEdit->insert(str);
}

//退格
void normalKeyboard::fBackspace()
{
    if (g_CurrentFocusType == "QLineEdit")
        p_CurrentLineEdit->backspace();
}

//长按
void normalKeyboard::fBtnLongClick()
{
    if (g_IsPressed) {
        p_LongPressTimer->setInterval(30); //设置间隔时间
        p_LongPressedBtn->click();
    }
}

//改变字体大小
void normalKeyboard::fChangeKeyboardFontSize(int fontSize)
{
    QFont myFont(this->font().family(), fontSize);
    QList<QPushButton *> myBtn = this->findChildren<QPushButton *>();
    foreach (QPushButton * btn, myBtn)
    {
        btn->setFont(myFont);
    }
    ui->showPinyin->setFont(myFont);
}

//设置键盘的大小和位置(当前点击的lineedit,键盘的位置,键盘的宽度,键盘的高度,键盘中pushbutton的大小)
void normalKeyboard::fResetKeyboardSize(QLineEdit *lineedit, QString style, int width, int height, int fontSize)
{
    //qDebug() << "numberKeyboard fResetKeyboardSize" << g_DeskWidth << g_DeskHeight;
    fChangeKeyboardFontSize(fontSize);

    QSize myIconSize(height/6, height/6);

    ui->btnShiftLeft->setIconSize(myIconSize);
    ui->btnShiftRight->setIconSize(myIconSize);
    ui->backspace->setIconSize(myIconSize);
    ui->btn_keyboard_close->setIconSize(myIconSize);
    ui->btnLanguage->setIconSize(myIconSize);
    ui->btnEnter->setIconSize(myIconSize);

    //根据用户选择的输入法位置设置-居中显示-底部填充-显示在输入框正下方等方式
    if (style == "center")
    {
        QPoint pos = QPoint(g_DeskWidth/2 - width/2, g_DeskHeight/2 - height/2);
        this->setGeometry(pos.x(), pos.y(), width, height);
    }
    else if (style == "bottom")
    {
        this->setGeometry(0, g_DeskHeight - height, g_DeskWidth, height);
    }
    else if (style == "leftdown")
    {
        QRect rect = lineedit->rect();
        QPoint pos = QPoint(rect.left(), rect.bottom() + 2);
        pos = lineedit->mapToGlobal(pos);//将窗口坐标转换成桌面坐标
        this->setGeometry(pos.x(), pos.y(), width, height);
    }
    else if (style == "leftup")
    {
        QRect rect = lineedit->rect();
        QPoint pos = QPoint(rect.left(), rect.top()- height - 2);
        pos = lineedit->mapToGlobal(pos);
        this->setGeometry(pos.x(), pos.y(), width, height);
    }
    else if (style == "rightup")
    {
        QRect rect = lineedit->rect();
        QPoint pos = QPoint(rect.right() - width, rect.top() - height - 2);
        pos = lineedit->mapToGlobal(pos);
        this->setGeometry(pos.x(), pos.y(), width, height);
    }
    else if (style == "rightdown")
    {
        QRect rect = lineedit->rect();
        QPoint pos = QPoint(rect.right() - width, rect.bottom() + 2);
        pos = lineedit->mapToGlobal(pos);
        this->setGeometry(pos.x(), pos.y(), width, height);
    }
}

//改变键盘类型
void normalKeyboard::fChangeInputType(QString type)
{
    g_ChineseList.clear();
    if (type == "InputUpper")
    {
        ui->selectWidget->hide();
        ui->btnA_->setText("A");
        ui->btnB_->setText("B");
        ui->btnC_->setText("C");
        ui->btnD_->setText("D");
        ui->btnE_3->setText("E");
        ui->btnF_->setText("F");
        ui->btnG_->setText("G");
        ui->btnH_->setText("H");
        ui->btnI_8->setText("I");
        ui->btnJ_->setText("J");
        ui->btnK_->setText("K");
        ui->btnL_->setText("L");
        ui->btnM_->setText("M");
        ui->btnN_->setText("N");
        ui->btnO_9->setText("O");
        ui->btnP_0->setText("P");
        ui->btnQ_1->setText("Q");
        ui->btnR_4->setText("R");
        ui->btnS_->setText("S");
        ui->btnT_5->setText("T");
        ui->btnU_7->setText("U");
        ui->btnV_->setText("V");
        ui->btnW_2->setText("W");
        ui->btnX_->setText("X");
        ui->btnY_6->setText("Y");
        ui->btnZ_->setText("Z");

        ui->btnAt_->setText("@");
        ui->btnPeriod->setText(".");
        ui->btnApostrophe->setText("'");
        ui->btnMinus->setText("-");

        ui->btnSpace->setText(tr("English"));

        ui->btnShiftLeft->setEnabled(true);
        ui->btnShiftRight->setEnabled(true);
        ui->btnShiftLeft->setIcon(QPixmap(":/images/shift_checked.png"));
        ui->btnShiftRight->setIcon(QPixmap(":/images/shift_checked.png"));

    }
    else if (type == "InputLower")
    {
        ui->selectWidget->hide();
        ui->btnA_->setText("a");
        ui->btnB_->setText("b");
        ui->btnC_->setText("c");
        ui->btnD_->setText("d");
        ui->btnE_3->setText("e");
        ui->btnF_->setText("f");
        ui->btnG_->setText("g");
        ui->btnH_->setText("h");
        ui->btnI_8->setText("i");
        ui->btnJ_->setText("j");
        ui->btnK_->setText("k");
        ui->btnL_->setText("l");
        ui->btnM_->setText("m");
        ui->btnN_->setText("n");
        ui->btnO_9->setText("o");
        ui->btnP_0->setText("p");
        ui->btnQ_1->setText("q");
        ui->btnR_4->setText("r");
        ui->btnS_->setText("s");
        ui->btnT_5->setText("t");
        ui->btnU_7->setText("u");
        ui->btnV_->setText("v");
        ui->btnW_2->setText("w");
        ui->btnX_->setText("x");
        ui->btnY_6->setText("y");
        ui->btnZ_->setText("z");

        ui->btnAt_->setText("@");
        ui->btnPeriod->setText(".");
        ui->btnApostrophe->setText("'");
        ui->btnMinus->setText("-");

        ui->btnSpace->setText(tr("English"));

        ui->btnShiftLeft->setEnabled(true);
        ui->btnShiftRight->setEnabled(true);
        ui->btnShiftLeft->setIcon(QPixmap(":/images/shift_double_checked.png"));
        ui->btnShiftRight->setIcon(QPixmap(":/images/shift_double_checked.png"));
    }
    else if (type == "InputChinese")
    {
        ui->selectWidget->show();
        ui->btnA_->setText("a");
        ui->btnB_->setText("b");
        ui->btnC_->setText("c");
        ui->btnD_->setText("d");
        ui->btnE_3->setText("e");
        ui->btnF_->setText("f");
        ui->btnG_->setText("g");
        ui->btnH_->setText("h");
        ui->btnI_8->setText("i");
        ui->btnJ_->setText("j");
        ui->btnK_->setText("k");
        ui->btnL_->setText("l");
        ui->btnM_->setText("m");
        ui->btnN_->setText("n");
        ui->btnO_9->setText("o");
        ui->btnP_0->setText("p");
        ui->btnQ_1->setText("q");
        ui->btnR_4->setText("r");
        ui->btnS_->setText("s");
        ui->btnT_5->setText("t");
        ui->btnU_7->setText("u");
        ui->btnV_->setText("v");
        ui->btnW_2->setText("w");
        ui->btnX_->setText("x");
        ui->btnY_6->setText("y");
        ui->btnZ_->setText("z");

        ui->btnAt_->setText("@");
        ui->btnPeriod->setText("。");
        ui->btnApostrophe->setText("’");
        ui->btnMinus->setText("-");

        ui->btnSpace->setText(tr("中文"));
        ui->btnShiftLeft->setEnabled(false);
        ui->btnShiftRight->setEnabled(false);
        ui->btnShiftLeft->setIcon(QPixmap(":/images/shift.png"));
        ui->btnShiftRight->setIcon(QPixmap(":/images/shift.png"));

    }
    else if (type == "InputNumber_E")
    {
        ui->selectWidget->hide();
        ui->btnA_->setText("@");
        ui->btnB_->setText(",");
        ui->btnC_->setText("<");
        ui->btnD_->setText("%");
        ui->btnE_3->setText("3");
        ui->btnF_->setText("&&");
        ui->btnG_->setText("*");
        ui->btnH_->setText("-");
        ui->btnI_8->setText("8");
        ui->btnJ_->setText("+");
        ui->btnK_->setText("(");
        ui->btnL_->setText(")");
        ui->btnM_->setText(";");
        ui->btnN_->setText(":");
        ui->btnO_9->setText("9");
        ui->btnP_0->setText("0");
        ui->btnQ_1->setText("1");
        ui->btnR_4->setText("4");
        ui->btnS_->setText("#");
        ui->btnT_5->setText("5");
        ui->btnU_7->setText("7");
        ui->btnV_->setText(">");
        ui->btnW_2->setText("2");
        ui->btnX_->setText("\"");
        ui->btnY_6->setText("6");
        ui->btnZ_->setText("!");

        ui->btnAt_->setText("@");
        ui->btnPeriod->setText(".");
        ui->btnApostrophe->setText("'");
        ui->btnMinus->setText("-");

        ui->btnSpace->setText(tr("English"));

        ui->btnShiftLeft->setEnabled(false);
        ui->btnShiftRight->setEnabled(false);
        ui->btnShiftLeft->setIcon(QPixmap(":/images/shift.png"));
        ui->btnShiftRight->setIcon(QPixmap(":/images/shift.png"));
    }
    else if (type == "InputNumber_C")
    {
        ui->selectWidget->hide();
        ui->btnA_->setText("@");
        ui->btnB_->setText(",");
        ui->btnC_->setText("《");
        ui->btnD_->setText("%");
        ui->btnE_3->setText("3");
        ui->btnF_->setText(tr("&&"));
        ui->btnG_->setText("*");
        ui->btnH_->setText("_");
        ui->btnI_8->setText("8");
        ui->btnJ_->setText("+");
        ui->btnK_->setText("(");
        ui->btnL_->setText(")");
        ui->btnM_->setText(";");
        ui->btnN_->setText(":");
        ui->btnO_9->setText("9");
        ui->btnP_0->setText("0");
        ui->btnQ_1->setText("1");
        ui->btnR_4->setText("4");
        ui->btnS_->setText("#");
        ui->btnT_5->setText("5");
        ui->btnU_7->setText("7");
        ui->btnV_->setText("》");
        ui->btnW_2->setText("2");
        ui->btnX_->setText("”");
        ui->btnY_6->setText("6");
        ui->btnZ_->setText("!");

        ui->btnAt_->setText("@");
        ui->btnPeriod->setText("。");
        ui->btnApostrophe->setText("’");
        ui->btnMinus->setText("@v@");

        ui->btnSpace->setText(tr("中文"));
        ui->btnShiftLeft->setEnabled(false);
        ui->btnShiftRight->setEnabled(false);
        ui->btnShiftLeft->setIcon(QPixmap(":/images/shift.png"));
        ui->btnShiftRight->setIcon(QPixmap(":/images/shift.png"));
    }

    ui->showPinyin->clear();
}

void normalKeyboard::on_showPinyin_textChanged(const QString &arg1)
{
    //qDebug() << "normalKeyboard on_showPinyin_textChanged" << arg1;

    g_CurrentChineseCount = 0;
    PinyinSql mypinyin;
    g_ChineseList.clear();
    for(int i = 0; i < 9; i++)
    {
        g_SelectList.at(i)->setText("");
    }

    mypinyin.fOpenPinyinSql("./hKeyboard/pinyin.db");
    g_ChineseList = mypinyin.fSearchPinyinData(arg1);
    mypinyin.fCloseSql();

    fShowChinese();
}

void normalKeyboard::fShowChinese()
{
    int j = 0;
    for(int i = g_CurrentChineseCount; i < g_ChineseList.count(); i++)
    {
        if(j < 9)
        {
            g_SelectList.at(j)->setText(g_ChineseList.at(i));
            j++;
        }
    }
}

5.2数据库部分

#ifndef PINYINSQL_H
#define PINYINSQL_H

#include <QObject>
#include <QSqlDatabase>
#include <QtSql>
#include <QSqlError>
#include <QSqlQuery>
#include <QDebug>
#include <QStringList>

class PinyinSql : public QObject
{
    Q_OBJECT
public:
    explicit PinyinSql(QObject *parent = nullptr);

    bool fOpenPinyinSql(QString sqlName);

    void fCloseSql();

    QStringList fSearchPinyinData(QString);

private:

    QSqlDatabase g_PinyinSqlDB;

};

#endif // PINYINSQL_H
#include "pinyinsql.h"

PinyinSql::PinyinSql(QObject *parent) : QObject(parent)
{

}

//打开数据库文件
bool PinyinSql::fOpenPinyinSql(QString sqlName)
{
    if(QSqlDatabase::contains("qt_sql_default_connection"))
        g_PinyinSqlDB = QSqlDatabase::database("qt_sql_default_connection");
    else
        g_PinyinSqlDB = QSqlDatabase::addDatabase("QSQLITE");

    g_PinyinSqlDB.setDatabaseName(sqlName);
    if(g_PinyinSqlDB.open())
    {
        //qDebug() << "hSql fOpenSql open sql succed!" << sqlName;
        return true;
    }
    else
    {
        //qDebug() << "hSql fOpenSql open sql failed!" << sqlName;
        return false;
    }
}

//关闭数据库
void PinyinSql::fCloseSql()
{
    g_PinyinSqlDB.close();
}

//搜索拼音对应的汉字
QStringList PinyinSql::fSearchPinyinData(QString pinyin)
{
    QStringList resultList;

    QSqlQuery myQuery;
    QString myStr = QString("select word from zhcn where py == '%1' order by id asc;").arg(pinyin);

    bool isSuccess = myQuery.exec(myStr);

    if(isSuccess)
    {
        while (myQuery.next())
        {
            resultList << myQuery.value(0).toString();
        }
    }
    resultList.removeDuplicates();

    //qDebug() << "PinyinSql fSearchPinyinData resultList:"  << resultList;

    return resultList;
}

6.Demo下载

    文中所涉及的源工程已上传,请有需要移步下载https://download.csdn.net/download/m0_56573550/89446913。

    以上程序可能存在纰漏,实现功能也不尽完善。期待和大家一起学习交流,共同进步。

注意:1.若有侵权,请联系删除。

       2.若想转载,请注明出处。
标签: qt

本文转载自: https://blog.csdn.net/m0_56573550/article/details/139739517
版权归原作者 三分糖丶去冰 所有, 如有侵权,请联系我们删除。

“Qt自定义虚拟键盘,模拟Qt插件虚拟键盘(数字键盘+全键盘),支持大小写,中英文,适用Windows Linux。”的评论:

还没有评论