Qt之软键盘的实现

2023-11-18


前言

  Qt5.8版本开始推出了基于QML实现的软键盘功能,在此之前,并没有官方版本的软键盘。本篇主要介绍Qt实现软键盘的两种方案,一种基于中文汉字数据库,一种基于谷歌拼音输入引擎。
  第一种中文提示有所限制,不够智能,建议使用第二种方案,Qt官方推出的软键盘也是基于谷歌拼音输入引擎实现的。

一、基于中文汉字数据库

  这种方式将中文汉字存放在py.db文件中,按照拼音去库中查询匹配的汉字,然后将多个查询结果显示出来。
  工程组织结构,如下:
在这里插入图片描述

1、核心代码

  核心代码如下:

//事件过滤器,用于识别鼠标单击汉字标签处获取对应汉字
bool frmInput::eventFilter(QObject *obj, QEvent *event)
{
    if (event->type() == QEvent::MouseButtonPress) {
        QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
        if (mouseEvent->button() == Qt::LeftButton) {
            if (obj == ui->labCh0) {
                setChinese(0);
            } else if (obj == ui->labCh1) {
                setChinese(1);
            } else if (obj == ui->labCh2) {
                setChinese(2);
            } else if (obj == ui->labCh3) {
                setChinese(3);
            } else if (obj == ui->labCh4) {
                setChinese(4);
            } else if (obj == ui->labCh5) {
                setChinese(5);
            } else if (obj == ui->labCh6) {
                setChinese(6);
            } else if (obj == ui->labCh7) {
                setChinese(7);
            } else if (obj == ui->labCh8) {
                setChinese(8);
            } else if (obj == ui->labCh9) {
                setChinese(9);
            } else if (currentEditType != "" && obj != ui->btnClose) {
                QString objName = obj->objectName();
                if (!obj->property("noinput").toBool() && objName != "frmMainWindow"
                        && objName != "frmInputWindow" && objName != "qt_edit_menu") {
                    ShowPanel();
                }
            }

            btnPress = (QPushButton *)obj;
            if (checkPress()) {
                isPress = true;
                timerPress->start(500);
            }
            return false;
        }
    } else if (event->type() == QEvent::MouseButtonRelease) {
        btnPress = (QPushButton *)obj;
        if (checkPress()) {
            isPress = false;
            timerPress->stop();
        }
        return false;
    } else if (event->type() == QEvent::KeyPress) {
        //如果输入法窗体不可见,则不需要处理
        if (!isVisible()) {
            return QWidget::eventFilter(obj, event);
        }

        QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
        //Shift切换输入法模式,esc键关闭输入法面板,空格取第一个汉字,退格键删除
        //中文模式下回车键取拼音,中文模式下当没有拼音时可以输入空格
        if (keyEvent->key() == Qt::Key_Space) {
            if (ui->labPY->text() != "") {
                setChinese(0);
                return true;
            } else {
                return false;
            }
        } else if (keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) {
            insertValue(ui->labPY->text());
            ui->labPY->setText("");
            selectChinese();
            return true;
        } else if (keyEvent->key() == Qt::Key_Shift) {
            ui->btnType->click();
            return true;
        } else if (keyEvent->key() == Qt::Key_Escape) {
            ui->btnClose->click();
            return true;
        } else if (keyEvent->key() == Qt::Key_Backspace) {
            ui->btnDelete->click();
            return true;
        } else if (keyEvent->text() == "+" || keyEvent->text() == "=") {
            if (ui->labPY->text() != "") {
                ui->btnNext->click();
                return true;
            } else {
                return false;
            }
        } else if (keyEvent->text() == "-" || keyEvent->text() == "_") {
            if (ui->labPY->text() != "") {
                ui->btnPre->click();
                return true;
            } else {
                return false;
            }
        } else if (keyEvent->key() == Qt::Key_CapsLock) {
            if (currentType != "max") {
                currentType = "max";
            } else {
                currentType = "min";
            }
            changeType(currentType);
            return true;
        } else {
            if (currentEditType == "QWidget") {
                return false;
            }
            QString key;
            if (currentType == "chinese") {
                key = keyEvent->text();
            } else if (currentType == "min") {
                key = keyEvent->text().toLower();
            } else if (currentType == "max") {
                key = keyEvent->text().toUpper();
            }
            QList<QPushButton *> btn = this->findChildren<QPushButton *>();
            foreach (QPushButton * b, btn) {
                if (b->text() == key) {
                    b->click();
                    return true;
                }
            }
        }
        return false;
    }
    return QWidget::eventFilter(obj, event);
}

查询中文汉字数据库,代码如下:

void frmInput::selectChinese()
{
    clearChinese();
    QSqlQuery query(QSqlDatabase::database("py"));
    QString currentPY = ui->labPY->text();
    QString sql = QString("select word from pinyin where pinyin='%1'").arg(currentPY);
    query.exec(sql);
    //逐个将查询到的字词加入汉字队列
    while(query.next()) {
        QString result = query.value(0).toString();
        QStringList text = result.split(" ");
        foreach (QString txt, text) {
            if (txt.length() > 0) {
                allPY.append(txt);
                currentPY_count++;
            }
        }
    }
    showChinese();
}

2、效果

效果如下:
在这里插入图片描述

二、基于谷歌拼音输入引擎

  这种方式基于谷歌拼音输入引擎,引擎源码在这里googlepinyin.7z,若想仔细研究,可自行下载。对外提供的接口在pinyinime.h文件里面,主要依赖dict_pinyin_user.dat和dict_pinyin.dat文件。
  工程组织结构,如下:
在这里插入图片描述

1、核心代码

  核心代码如下:

//事件过滤器,用于识别鼠标单击汉字标签处获取对应汉字
bool easyInput::eventFilter(QObject *obj, QEvent *event)
{
    if (event->type() == QEvent::MouseButtonPress) {
        QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
        if (mouseEvent->button() == Qt::LeftButton) {
            if (obj == ui->labCh1) {
                setChinese(0);
            } else if (obj == ui->labCh2) {
                setChinese(1);
            } else if (obj == ui->labCh3) {
                setChinese(2);
            } else if (obj == ui->labCh4) {
                setChinese(3);
            } else if (obj == ui->labCh5) {
                setChinese(4);
            } else if (currentEditType != "" && obj != ui->btnClose) {
                QString objName = obj->objectName();
                if (obj->parent() != 0x0 && !obj->property("noinput").toBool() && objName != "frmMainWindow"
                        && objName != "frmInputWindow" && objName != "qt_edit_menu" && objName != "labPY") {
                    if (obj->inherits("QGroupBox") || obj->inherits("QFrame") || obj->inherits("QMenu")) {
                        hidePanel();
                    } else {
                        showPanel();
                    }
                }
            }
            btnPress = (QPushButton *)obj;
            if (checkPress()) {
                isPress = true;
                timerPress->start(500);
            }
            return false;
        }
    } else if (event->type() == QEvent::MouseButtonRelease) {
        btnPress = (QPushButton *)obj;
        if (checkPress()) {
            isPress = false;
            timerPress->stop();
        }

        return false;
    } else if (event->type() == QEvent::KeyPress) {
        //如果输入法窗体不可见,则不需要处理
        if (!isVisible() && !mini) {
            return QWidget::eventFilter(obj, event);
        }

        QString labText = ui->labPY->text();
        QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);

        //Shift切换输入法模式,esc键关闭输入法面板,空格取第一个汉字,退格键删除
        //中文模式下回车键取拼音,中文模式下当没有拼音时可以输入空格
        if (keyEvent->key() == Qt::Key_Space) {
            if (labText != "") {
                ui->labPY->setText("");
                setChinese(0);
                return true;
            } else {
                return false;
            }
        } else if (keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) {
            if (labText != "") {
                insertValue(labText);
                ui->labPY->setText("");
                selectChinese();
            } else {
                //hidePanel(); //2019年12月4日 14:56:03
            }
            //return true;
        } else if (keyEvent->key() == Qt::Key_Control) {
            //
        } else if (keyEvent->key() == Qt::Key_Shift) {
                ui->btnType->click();
                return true;
        } else if (keyEvent->key() == Qt::Key_Escape) {
            ui->btnClose->click();
            return true;
        } else if (keyEvent->key() == Qt::Key_Backspace) {
            if (inputType == "chinese") {
                QString txt = labText;
                int len = txt.length();
                if (len > 0) {
                    ui->labPY->setText(txt.left(len - 1));
                    selectChinese();
                    return true;
                }
            }
        } else if (keyEvent->key() == Qt::Key_CapsLock) {
            ui->btnUpper->click();
            return true;
        } else if (keyEvent->text() == "+" || keyEvent->text() == "=") {
            if (labText != "") {
                ui->btnNext->click();
                return true;
            } else {
                return false;
            }
        } else if (keyEvent->text() == "-" || keyEvent->text() == "_") {
            if (labText != "") {
                ui->btnPre->click();
                return true;
            } else {
                return false;
            }
        } else {
            if (currentEditType == "QWidget") {
                return false;
            }

            QString key;
            if (inputType == "chinese") {
                key = keyEvent->text();
            } else if (inputType == "english") {
                if (upper) {
                    key = keyEvent->text().toUpper();
                } else {
                    key = keyEvent->text().toLower();
                }
            }

            if (!key.isEmpty()) {
                QList<QPushButton *> btn = ui->widgetMain->findChildren<QPushButton *>();
                foreach (QPushButton *b, btn) {
                    QString text = b->text();
                    if (!text.isEmpty() && text == key) {
                        b->click();
                        return true;
                    }
                }
            }
        }

        return false;
    }

    return QWidget::eventFilter(obj, event);
}

2、效果

效果如下:
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt之软键盘的实现 的相关文章

  • qmake 和 QT_INSTALL_PREFIX。如何为 Qt 库选择新位置?

    我是 qmake 的新手 我正在尝试构建一个现有的应用程序 Qt 最初安装在 usr local lib Qt 4 3 5 中 qmake query QT INSTALL PREFIX 返回该路径 我已将 Qt 库移动到另一个位置 生成的
  • Qt5 CMake 将所有库包含到可执行文件中

    我正在尝试使用 Qt 5 14 构建一个发布模式下的应用程序 并且 Qt Creator 内部一切正常 但是当我尝试单独运行可执行文件时 我收到如下错误 OS Windows 10 Qt 5 14 Cmake 3 5 我尝试过的 设置 CM
  • 删除行时 QModelIndex 变得无效

    我正在子类化QAbstractItemModel显示项目QTreeView 并且在这个子类中 projectModel 我有一个功能可以删除树视图中当前选定的索引 Component是用于表示模型所有成员的类 void projectMod
  • 从 Qt 中的半透明小部件中擦除绘制区域

    我面临着必须擦除 Qt 小部件上先前绘制的区域的问题 基本思想是 用户通过单击并拖动鼠标来选择屏幕的一个区域 并在所选区域上绘制一个矩形 标题 class ClearBack public QWidget Q OBJECT public e
  • 使用带有 MSVC 2015 编译器的 QT Creator 5.8

    我是新来的C 和编程 我正在尝试做一个小项目 使用Qt and Qt Creator 我当时用的是MinGW compiler 但对于这个项目 我需要与MSVC compiler 因为我需要使用QtWebEngineWidgets I ha
  • 使用 Qt 在 xoverlay 之上绘制

    我希望在使用 Xoverlay 渲染的视频流之上绘制一些 UI 我正在使用 gstreamer 播放视频并使用 xoverlay 在 xvimagesink 上渲染它 我的小部件继承自 QGLWidget 我希望使用 QPainter 绘制
  • Qml 中的 FileDialog 在发布中不起作用

    我正在与以下项目合作Qt Quick Control 2 当我尝试在调试模式下运行软件时 FileDialog qml 可以完美打开 但是当我将其部署为发布模式时 它无法工作 这是我的代码 import QtQuick 2 4 import
  • 无法将 QMap 传递到 SLOT

    所以 这有效 h public slots void addMenu QString passedName signals void clicked const QString text cpp signalMapper new QSign
  • 无法隐藏 QMenu 对象 QMenu::setVisible()?

    我已经建立了一个QMenu MainMenu在我的上面MainWindow在我的应用程序中 大家都习惯了 我有以下QMenu主菜单 文件 编辑 SuperHeavyExpertMenus 设置 帮助 我想隐藏子树SuperHeaverExp
  • 无法初始化静态QList?

    我收到以下错误 Cube cpp 10 error expected initializer before lt lt token 以下是头文件的重要部分 ifndef CUBE H define CUBE H include
  • Mac OS X 文件关联有效,但文件图标未更改

    我使用 Qt 5 3 2 开发了一个 Mac 应用程序 该应用程序处理具有特定扩展名的文件 比方说 xyz 我创建了一个名为 XYZ icns 的图标文件 并将其添加到我的应用程序包资源文件夹中 MyApp app Contents Res
  • 如何在 QTableWidget 的行和列中自动换行文本?

    I tried QTableWidget j new QTableWidget 10000 5 centralWidget j gt setColumnWidth 0 500 j gt setColumnWidth 1 30 j gt se
  • 如何在Qt中设置编译器?

    我对 Qt 完全陌生 我下载了离线版本 Qt 5 3 2 for Windows 64 bit VS 2013 OpenGL 573 MB 我无法编译我的项目 I have Qt Creator 3 2 1 开源 基于Qt 5 3 2 MS
  • Qt + win32 + mingw 上的原生 Windows API 链接问题

    我正在尝试使用 mingw 工具集将本机 Windows API 与 Qt 结合使用 部分功能存在链接问题 会发生什么 这是 mingw 名称修改的错误吗 ifdef Q WS WIN HWND hwnd QWidget winId HDC
  • 获取小部件的背景颜色 - 真的

    我无法获取小部件的实际背景颜色 在我的特殊情况下 我在使用 QTabWidget 中的小部件时遇到问题 这是在Windows7上 因此 经典的小部件有一些灰色背景 而选项卡内的小部件通常用白色背景绘制 I tried def bgcolor
  • 我的 QSqlQueryModel 不在列表视图中显示数据

    我正在玩 QSqlQueryModel 但我现在完全陷入困境 我一整天都在寻找解决方案 但到目前为止还没有运气 我所做的工作是它从我的 sqlite 数据库中提取数据 但由于某种原因我无法在列表视图中显示它 我的角色名似乎不存在 对于我从数
  • cx_freeze:QODBC 驱动程序未加载

    我的 python 应用程序如下所示 test py from PyQt4 import QtCore from PyQt4 import QtGui from PyQt4 import QtSql import sys import at
  • Qt GUI 编程设计

    我正在尝试创建一个 GUI 应用程序 主窗口 一个QMainWindow 包含 9 个固定大小的标签以及主窗口的大小 我尝试在没有 Qt GUI Designer 的情况下以编程方式制作它 该项目构建时没有错误 但我看不到主窗口上显示的任何
  • setContextProperty 和对象的 setProperty 之间的区别

    我现在真的很困惑 有什么区别 QQmlApplicationEngine engine engine rootContext setContextProperty myObject userData and object gt setPro
  • Qt 计算和比较密码哈希

    目前正在 Qt 中为测验程序构建面向 Web 的身份验证服务 据我了解 在数据库中存储用户密码时 必须对其进行隐藏 以防落入坏人之手 流行的方法似乎是添加的过程Salt https en wikipedia org wiki Salt cr

随机推荐

  • 具有文件操作和滤波功能的Open3D软件界面(附python pyqt 代码)

    安装依赖 pip install pyqtgraph i https pypi tuna tsinghua edu cn simple pip install pyopengl i https pypi tuna tsinghua edu
  • python 100以内的质数

    可以使用for循环 求100以内的质数 i 2 for j in range 1 101 如果100以内的数字除以2的余数等于0 if j i 0 如果是就跳过 继续下一个循环 continue print j 要找出从1到100之间的质数
  • 在 Python 中打印变量之间没有空格

    文章目录 使用 sep 参数打印变量之间没有空格 使用加法 运算符打印不带空格的变量 在 Python 中不使用换行符或空格打印 使用格式化的字符串文字来打印没有空格的变量 例如 print f hello variable 1 格式化字符
  • oracle 重设redo log 和倒入

    重设redo log alter system set allow resetlogs corruption true scope spfile recover database until cancel using bakcup cont
  • [RK3288][Android6.0] 调试笔记 --- 系统第一次开机进入Recovery模式原因

    Platform ROCKCHIP OS Android 6 0 Kernel 3 10 92 描述 当系统全部download开机后 会默认进入Recovery模式 这个其实是misc分区里的内容在作怪 misc分区 misc img是R
  • String、StringBuffer、StringBuilder的区别

    转载 极客时间 JAVA核心技术36讲 https www cnblogs com ygj0930 p 6581009 html 一 String创建机制 JAVA语言在创建一个字符串时 首先检查池中是否有值相同的字符串对象 如果有则不需要
  • 朴素贝叶斯--matlab自带工具箱的使用

    朴素贝叶斯分类使用条件 其数据点的维数 即特征之间相互独立 当属性之间相关性较小时 分类效率好 当属性之间相关性较大时 分类不如决策树 属性之间的相关性获得 用协方差矩阵 matlab自带函数cov获得 1 nb NaiveBays fit
  • git pull时报错Filename too long

    在git bash窗口执行以下命令 全局设置git支持长文件名 git config global core longpaths true
  • ClickHouse实时分析(一)- ClickHouse入门

    目录 1 什么是ClickHouse 1 1 OLAP场景的关键特征 1 2 列式数据库更适合OLAP场景的原因 1 2 1 输入 输出 1 2 2 CPU 2 ClickHouse的特点 2 1 列式存储 2 2 数据压缩 2 3 数据的
  • DALI协议了解

    DALI Digital Addressable Lighting Interface 是一种新的智能照明系统的控制协议 系统具有结构简单 安装方便 操作容易 功能良优等特点 协议定义了电子镇流器与控制器之间的通信方式 DALI协议系统由分
  • 哨兵节点:思想简单,效果很棒的的编程算法

    文章目录 普通的算法 哨兵算法 小结 别人的经验 我们的阶梯 今天和同事一起调代码 定位到一处很耗时的地方 在某个线程中 同步周期需要保证在2毫秒 如果耗时不到2毫秒 那么就让剩下的时间进行sleep 但是在调用一个模块的内部函数时 时不时
  • 轻盈绘图的Excalidraw插件

    朋友们 你们的Obsidian彩虹屁狂魔重新上线 从这篇Obsidian实践开始 我想跟大家陆续分享一下 Obsidian中那些让人眼前一亮的宝藏插件 原本我想从逻辑上最基础 使用上最简单的插件讲起 然鹅 请原谅我实在按捺不住自己迫切的心情
  • JAVA小游戏(国王和大臣)

    棋规则和需求 规则 棋子 2颗国王棋和 8 16 颗大臣棋 分别用黑白两色代表国王和大臣 黑子为国王 白子为大臣 棋盘 5 9的二维棋盘 共37个交点 如图所示 吃子规则 包括移子和添子 1 国王每回合可以选择移动一步 或者跳吃大臣一颗棋子
  • ceph集群警告和错误类型

    指标 说明 级别 noscrub flag s set 防止集群做清洗操作 full flag s set 使集群到达设置的full ratio值 会导致集群阻止写入操作 nodeep scrub flag s set 防止集群进行深度清洗
  • Vue与WebGL结合

    本文将WebGL与当前前端比较火的Vue框架进行初步结合 以备后续项目开发需要 部分代码源自https blog csdn net GISuuser article details 82224057以及 WebGL编程指南 大家可以自己百度
  • 使用IDEA创建springboot项目时,出现错误Cannot download ‘https://start.spring.io‘: connect timed out

    使用IDEA创建springboot项目时 出现错误Cannot download https start spring io connect timed out 解决方案 1 选择 custom 并使用阿里云 https start al
  • Objective-C Runtime 1小时入门教程

    原文出处 ian ianisme 一 前言 如果你没有Objective C基础 请学习了基础的iOS开发再来 这个1小时是给有一定iOS基础的童鞋的 如果你是大牛或者你感觉Objective C Runtime太简单不用1小时学习的 也请
  • MVVM框架极简总结

    MVVM是一个前端框架 由model view viewmodel组成 是MVC的升级版 变成了由viewmodel进行m和v之间的双向数据绑定 虽然代码量相较于MVC变得更多了一点 逻辑和视图分开来写 但是更利于代码解耦 也更方便测试来自
  • 刷脸支付互联网思维的推广让传播变得更快

    行业巨头也在加速抢占刷脸支付的风口 支付宝近期发布了新的刷脸支付设备 同时宣布补贴力度不设上限 以此来加速刷脸支付的落地 在巨头们的大力推动下 刷脸支付普及率不断提升 最新数据显示 目前我国刷脸支付用户数已经破亿 其中 90后 占据了主流
  • Qt之软键盘的实现

    文章目录 前言 一 基于中文汉字数据库 1 核心代码 2 效果 二 基于谷歌拼音输入引擎 1 核心代码 2 效果 前言 Qt5 8版本开始推出了基于QML实现的软键盘功能 在此之前 并没有官方版本的软键盘 本篇主要介绍Qt实现软键盘的两种方