QT5 Virtual Keyboard实现自适应悬浮键盘(多种方法详细记录)

这篇具有很好参考价值的文章主要介绍了QT5 Virtual Keyboard实现自适应悬浮键盘(多种方法详细记录)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

        项目需求实现悬浮键盘,点击QLineEdit或QTextEdit自动弹出自适应悬浮键盘,尝试了以下几种方法后选择了修改QT Virtual Keyboard源码。在这里把其他方法/想法也列出来做一下记录。

        项目环境:QT5.13.2  VS2017

目录

方法1:调用windows自带系统软件盘

介绍

 代码调用

方法2:用大佬们公开的自制键盘

介绍

方法3:修改QT自带Virtual Keyboard代码实现定位悬浮

介绍

代码调用及编译步骤

记录出现的部分问题


方法1:调用windows自带系统软件盘

介绍

        windows自带软键盘分为osk.exe以及tabtip.exe。这里简单阐述一下个人理解的两者区别,osk.exe就是日常使用时的系统软件盘,tabtip.exe是windows平板模式时使用的系统软件盘,仅响应平板模式时命令,所以普通模式时调用tabtip是没有弹出的。

        osk.exe 位于 C:\Windows\System32\osk.exe

        tabtip.exe 位于 C:\Program Files\Common Files\microsoft shared\ink\TabTip.exe

        直接调用可以win+R打开运行窗口输入osk或tabtip查看。

Windows10中的osk(上)和tabtip(下):

qtquick.virtualkeyboard,乱七八糟的知识点笔记,qt5,c++,visual studio

qtquick.virtualkeyboard,乱七八糟的知识点笔记,qt5,c++,visual studio

 代码调用

        曾尝试重写QTextEdit以及QLineEdit的点击响应事件mousePressEvent(QMouseEvent *event),以实现点击信息框后弹出系统软键盘。但是很遗憾失败了,点击后并不会弹出osk或tabtip系统软键盘,具体原因未做探究,欢迎各位补充。想要尝试的童鞋可以查看参考文献4。

        下文提供的方法为:点击按钮弹出windows系统软件盘。(以下为osk调用代码,电脑无平板模式,未尝试tabtip)

QtWidgetsApplication.ui

         这里直接使用QT Designer在ui界面中添加Push Button

qtquick.virtualkeyboard,乱七八糟的知识点笔记,qt5,c++,visual studio

 QtWidgetsApplication.h

//软键盘的头文件
#include <Windows.h>
#pragma comment(lib, "user32.lib")

#include <QtWidgets/QMainWindow>
#include "ui_QtWidgetsApplication1.h"
using namespace std;

class QtWidgetsApplication : public QMainWindow
{
    Q_OBJECT

public:
    QtWidgetsApplication1(QWidget *parent = Q_NULLPTR);

private:
    Ui::QtWidgetsApplicationClass ui;
}

QtWidgetsApplication.cpp

#include "QtWidgetsApplication.h"


QtWidgetsApplication::QtWidgetsApplication(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
    // 按钮点击触发弹出osk.exe
    connect(ui.textButton, &QPushButton::clicked, [=]() {
		PVOID OldValue = nullptr;
        BOOL bRet = Wow64DisableWow64FsRedirection(&OldValue);
        QString csProcess = "C:\\Windows\\System32\\osk.exe";
        QString params="";
        ShellExecute(nullptr, L"open", (LPCWSTR)csProcess.utf16(), (LPCWSTR)params.utf16(), nullptr, SW_SHOWNORMAL);
        if (bRet)
        {
            Wow64RevertWow64FsRedirection(OldValue);
        }
	});
}

方法2:用大佬们公开的自制键盘

介绍

        参考文献[5]到参考文献[9]是搜索过程中找到的一些大佬的开源自制虚拟键盘,仅列举能找到的部分连接,其余连接已经消失在浏览器历史记录中找不到了。但是自制的美观度啥的还是不如QT自带的虚拟键盘,所以采用了方法3。

方法3:修改QT自带Virtual Keyboard代码实现定位悬浮

介绍

修改前QT Virtual Keyboard效果如下图,数字键盘(上),常规键盘(下):

qtquick.virtualkeyboard,乱七八糟的知识点笔记,qt5,c++,visual studio

 qtquick.virtualkeyboard,乱七八糟的知识点笔记,qt5,c++,visual studio

         可以看到QT自带的虚拟键盘会自动占据半个屏幕,挡住了界面,使用体验略有欠缺。

修改后实际效果如下图所示,数字键盘(上),常规键盘(下):(PS:功能实验项目,界面过于杂乱,勿介意)

qtquick.virtualkeyboard,乱七八糟的知识点笔记,qt5,c++,visual studio

qtquick.virtualkeyboard,乱七八糟的知识点笔记,qt5,c++,visual studio

         修改后的QT虚拟键盘缩小了键盘尺寸,以及实现了根据QLineEdit和QTextEdit位置自适应悬浮。

代码调用及编译步骤

        以下位置信息以本人电脑各部件位置信息为例,具体位置可根据个人安装位置进行调整。

(1)首先你的QT要有源码,如果你在最初安装的时候已经安装了源码那么源码位于D:\Qt\Qt5.13.2\5.13.2\Src。如果在安装时没有选择源码,可进入各版本QT源码下载进行下载。本文环境为QT5.13.2,具体选择路径如下图所示。

qtquick.virtualkeyboard,乱七八糟的知识点笔记,qt5,c++,visual studio

qtquick.virtualkeyboard,乱七八糟的知识点笔记,qt5,c++,visual studio

qtquick.virtualkeyboard,乱七八糟的知识点笔记,qt5,c++,visual studio

qtquick.virtualkeyboard,乱七八糟的知识点笔记,qt5,c++,visual studio

        下载后解压至D:\Qt\Qt5.13.2\5.13.2\qt-everywhere-src-5.13.2 

 (2)进入目录D:\Qt\Qt5.13.2\5.13.2\qt-everywhere-src-5.13.2\qtvirtualkeyboard\src\virtualkeyboard,点击下方文件打开QT Creator。 

qtquick.virtualkeyboard,乱七八糟的知识点笔记,qt5,c++,visual studio

(3)修改以下四个文件。(在这里感谢参考文献[9]的大佬)

virtualkeyboard.pro

qtquick.virtualkeyboard,乱七八糟的知识点笔记,qt5,c++,visual studio

         在virtualkeyboard.pro中加入下方代码(此处包含上下文部分代码,方便大家找到具体位置)

QT += qml quick gui gui-private core-private
# 加入widgets,自动载入相关库
QT += widgets

CONFIG += qtquickcompiler

 InputPanel.qml

qtquick.virtualkeyboard,乱七八糟的知识点笔记,qt5,c++,visual studio

         这里由于篇幅问题将源码中大段注释进行删除,添加代码部分已在下方标出。

import QtQuick 2.0
import QtQuick.VirtualKeyboard 2.1
// 加入
import QtQuick.Window 2.2

Item {
    id: inputPanel
    property alias active: keyboard.active
    property bool externalLanguageSwitchEnabled
    signal externalLanguageSwitch(var localeList, int currentIndex)
    property alias keyboard: keyboard
    readonly property bool __isRootItem: inputPanel.parent != null && inputPanel.parent.parent == null

    SelectionControl {
        objectName: "selectionControl"
        x: -parent.x
        y: -parent.y
        enabled: active && !keyboard.fullScreenMode && !__isRootItem
    }

    implicitHeight: keyboard.height
    Keyboard {
        id: keyboard
        // 将以下内容注释掉
//        anchors.left: parent.left
//        anchors.right: parent.right
//        anchors.bottom: parent.bottom

        // 以下为添加代码
        // 获取锚点
        anchors.horizontalCenter: parent.horizontalCenter
        // 键盘宽度(可根据需要进行修改)
        width: Screen.desktopAvailableWidth * 2 / 5
        states: State {
                name: "visible";
                when: keyboard.active;
                PropertyChanges {
                    target: keyboard;
                    y: getInputY()
                }
            }
        transitions: Transition {
                from: "";
                to: "visible";
                reversible: true;
                ParallelAnimation {
                    NumberAnimation {
                        properties: "y";
                        duration: 250;
                        easing.type: Easing.InOutQuad;
                    }
                }
            }
        // 获取锚点坐标Y值
        function getInputY(){
                if(InputContext.inputItemGeometry.y + InputContext.inputItemGeometry.height + keyboard.height <= Screen.desktopAvailableHeight){
                    return InputContext.inputItemGeometry.y + InputContext.inputItemGeometry.height

                }
                else if(InputContext.inputItemGeometry.y - keyboard.height - 100 >= 0)
                {
                    return InputContext.inputItemGeometry.y - keyboard.height - 50
                }
                else
                {
                      return Screen.desktopAvailableHeight - keyboard.height
                }
            }
        // 添加代码部分结束
    }
    MouseArea {
        z: -1
        anchors.fill: keyboard
        enabled: active
    }

    Binding {
        target: InputContext.priv
        property: "keyboardRectangle"
        value: mapToItem(null,
                         __isRootItem ? keyboard.x : x,
                         (__isRootItem ? keyboard.y : y) + keyboard.wordCandidateView.currentYOffset - (keyboard.shadowInputControl.visible ? keyboard.shadowInputControl.height : 0),
                         keyboard.width,
                         keyboard.height - keyboard.wordCandidateView.currentYOffset + (keyboard.shadowInputControl.visible ? keyboard.shadowInputControl.height : 0))
        when: !InputContext.animating
    }
}

 qvirtualkeyboardinputcontext.h(Headers文件夹内)

#ifndef QVIRTUALKEYBOARDINPUTCONTEXT_H
#define QVIRTUALKEYBOARDINPUTCONTEXT_H

#include <QObject>
#include <QRectF>
#include <QLocale>
#include <QInputMethodEvent>
#include <QInputMethod>
#include <QtVirtualKeyboard/qvirtualkeyboard_global.h>
// 加入头文件
#include <QtWidgets/QWidget>

QT_BEGIN_NAMESPACE

namespace QtVirtualKeyboard {
class PlatformInputContext;
}
class QVirtualKeyboardInputEngine;
class QVirtualKeyboardInputContextPrivate;

class QVIRTUALKEYBOARD_EXPORT QVirtualKeyboardInputContext : public QObject
{
    Q_OBJECT
    // ......此处篇幅以及直观原因省略55-76行
    Q_PROPERTY(QVirtualKeyboardInputContextPrivate *priv READ priv CONSTANT)

    // 加入
    Q_PROPERTY(QRectF inputItemGeometry READ inputItemGeometry CONSTANT)


public:
    explicit QVirtualKeyboardInputContext(QObject *parent = nullptr);
    ~QVirtualKeyboardInputContext();

    // 加入
    QRectF inputItemGeometry();

    bool isShiftActive() const;
    // ......此处篇幅以及直观原因省略91-119行

Q_SIGNALS:

    // ......此处篇幅以及直观原因省略123-139行

private:

    QScopedPointer<QVirtualKeyboardInputContextPrivate> d_ptr;
};

QT_END_NAMESPACE

#endif

  qvirtualkeyboardinputcontext.cpp(Sources文件夹内)

// 加入内容
QRectF QVirtualKeyboardInputContext::inputItemGeometry()
{
    QWidget* pInputItem = static_cast<QWidget*>(inputItem());
    return pInputItem ? QRectF((static_cast<QWidget*>(pInputItem->parent()))->mapToGlobal(pInputItem->geometry().topLeft()), pInputItem->geometry().size()) : QRectF(0,0,0,0);
}

(4)进入下方工具

qtquick.virtualkeyboard,乱七八糟的知识点笔记,qt5,c++,visual studio

        进入目录 :D:\Qt\Qt5.13.2\5.13.2\qt-everywhere-src-5.13.2\qtvirtualkeyboard\src\virtualkeyboard

qtquick.virtualkeyboard,乱七八糟的知识点笔记,qt5,c++,visual studio

         依次执行qmakenmakenmake install

qtquick.virtualkeyboard,乱七八糟的知识点笔记,qt5,c++,visual studio

qtquick.virtualkeyboard,乱七八糟的知识点笔记,qt5,c++,visual studio

 qtquick.virtualkeyboard,乱七八糟的知识点笔记,qt5,c++,visual studio

 (5)VS2017中进入Qt Project Settings,加入Vitual Keyboard模块。

qtquick.virtualkeyboard,乱七八糟的知识点笔记,qt5,c++,visual studio

qtquick.virtualkeyboard,乱七八糟的知识点笔记,qt5,c++,visual studio

 (6)在main.cpp中加入以下代码

#include "QtWidgetsApplication1.h"
#include "Products.h"
#include <string>
#include <QtWidgets/QApplication>

int main(int argc, char *argv[])
{
	qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard")); // 虚拟键盘调用

    QApplication a(argc, argv);
    QtWidgetsApplication1 w;
    w.show();
    return a.exec();
}

 (7)数字键盘和常用键盘的选择见如下属性

qtquick.virtualkeyboard,乱七八糟的知识点笔记,qt5,c++,visual studio

记录出现的部分问题

(1)qvirtualkeyboardinputcontext.obj : error LNK2019: 无法解析的外部符号 "__declspec(dllimport) public: class QPoint __cdecl QWidget::mapToGlobal(class QPoint const &)const " (__imp_?mapToGlobal@QWidget@@QEBA?AVQPoint@@AEBV2@@Z),该符号在函数 "public: class QRectF __cdecl QVirtualKeyboardInputContext::inputItemGeometry(void)" (?inputItemGeometry@QVirtualKeyboardInputContext@@QEAA?AVQRectF@@XZ) 中被引用
..\..\lib\Qt5VirtualKeyboard.dll : fatal error LNK1120: 1 个无法解析的外部命令

qtquick.virtualkeyboard,乱七八糟的知识点笔记,qt5,c++,visual studio(2)fatal error C1083: 无法打开包括文件: “QWidget”: No such file or directory
fallbackinputmethod.cppqtquick.virtualkeyboard,乱七八糟的知识点笔记,qt5,c++,visual studio

        出现以上两种问题,请排查以下内容:

        1、请在第三步中virtualkeyboard.pro查看是否加入QT += widgets;

        2、查看第四步中进入目录是否为D:\Qt\Qt5.13.2\5.13.2\qt-everywhere-src-5.13.2\qtvirtualkeyboard\src\virtualkeyboard。若仅到D:\Qt\Qt5.13.2\5.13.2\qt-everywhere-src-5.13.2\qtvirtualkeyboard会出现以上问题。

        仍出现以下问题,尝试以下两种方法:

 方法一:用以下代码替换QT += widgets

greaterThan(QT_MAJOR_VERSION, 4):QT += widgets

方法二:加入库

INCLUDEPATH += D:/Qt/Qt5.13.2/5.13.2/msvc2017_64/include/QtWidgets
LIBS += D:/Qt/Qt5.13.2/5.13.2/msvc2017_64/lib/Qt5Widgets.lib

参考文献:

[1] Windows下C++调用系统软键盘及其需要注意的点_FlushHip的博客-CSDN博客

[2]qt调用windows键盘

[3]如何将存在任务管理器中隐藏的tabtip键盘显示出来

[4]QT给控件QLineEdit添加clicked()事件方法_gloria.Momo的博客-CSDN博客_qt clicked

[5]qt模拟键盘_开心an的博客-CSDN博客

[6]QT 虚拟键盘 可进行中英输入【C++】_每晚秃头的程序员的博客-CSDN博客_qt5.12.12虚拟键盘只保留中英文输入法

[7]qt制作软键盘(虚拟键盘)_努力拱白菜的博客-CSDN博客_qt 虚拟键盘

[8]轻量级Qt键盘-实现篇 - 知乎

[9]Qt5 Virtual Keyboard C++集成与实现二(自适应位置)-爱易默博客

[10]QT pro QT+= widgets终极总结_梦幽风的博客-CSDN博客_qt+=widgets 文章来源地址https://www.toymoban.com/news/detail-787363.html

到了这里,关于QT5 Virtual Keyboard实现自适应悬浮键盘(多种方法详细记录)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • LVGL学习笔记 28 - 键盘keyboard

    目录 1. 设置关联文本框 2. 设置模式 2.1 LV_KEYBOARD_MODE_TEXT_LOWER 2.2 LV_KEYBOARD_MODE_TEXT_UPPER 2.3 LV_KEYBOARD_MODE_SPECIAL 2.4 LV_KEYBOARD_MODE_NUMBER 2.5 LV_KEYBOARD_MODE_USER_1 ~ LV_KEYBOARD_MODE_USER_4 3. 使能弹窗模式 4. 更改按键布局 5. 事件 键盘是一个特殊的按键矩阵,自身实现了按键(map)映射和其他

    2024年02月13日
    浏览(46)
  • JavaScript 虚拟键盘:Mindfusion JavaScript Keyboard

    高度交互,高度可定制--JavaScript 虚拟键盘--Mindfusion JavaScript Keyboard 现在,您的 JavaScript 应用程序可以像本地移动应用程序一样处理屏幕输入。   特征 键盘布局 扩展、紧凑和标准布局模式。KeyboardLayout 工具可帮助您根据需要创建和排列自定义键盘。 关键图像 您可以使用图像

    2024年02月09日
    浏览(39)
  • LVGL:拓展部件——键盘 lv_keyboard

    此控件特点: 特殊Button矩阵: lv_keyboard 本质上是一个经过定制的 按钮矩阵 控件。每个按钮都可以独立触发事件或响应。 预定义的键映射: lv_keyboard 自带了一套预设的 按键布局 和 对应的字符映射表 ,开发者可以根据需要选择或自定义这些键映射。 与 lv_textarea 配合使用:

    2024年03月20日
    浏览(38)
  • 【python自动化】Playwright基础教程——Keyboard键盘

    playwright模拟键盘操作 键盘事件提供了用于管理虚拟键盘的API,高级API是 keyboard.type() ,它使用的是原始字符再页面上生成对应的 keydown 、 keypress / input 和 keyup 事件。 模拟真实键盘操作进行更精细的控制可以使用 keyboard.down() 、 keyboard.up() 和 keyboard.insert_text() 手动触发事件。

    2024年02月22日
    浏览(39)
  • vue+simple-keyboard 虚拟键盘有中文(拼音),获取焦点调出键盘半封组件

    前几天临时接个需求,我们的主机产品没键盘,一直都是调主机的虚拟键盘,但是最近不知道那块出了点问题,就要用前端做一个,我之前就听说过 simple-keyboard 组件,就没当回事,随口就应下了,结果这个我做的这个头疼啊,什么切换input之后重新输入,切换input之后无法删

    2024年04月11日
    浏览(65)
  • 如何用Qt实现一个无标题栏、半透明、置顶(悬浮)的窗口

    在Qt框架中,要实现一个无标题栏、半透明、置顶(悬浮)的窗口,需要一些特定的设置和技巧。废话不多说,下面我将以DrawClient软件为例,介绍一下实现这种效果的四个要点。 要点一:移除标题栏(去除关闭、最小化、最大化按钮) 在窗口的构造函数中设置窗口的样式,

    2024年02月19日
    浏览(38)
  • UOS Python+Qt5实现声卡回路测试

    1.回路治具设计: 2.Ui界面: 3.源代码:

    2024年01月16日
    浏览(73)
  • 基于Qt5的图像交互控件开发(C++实现)

    博主近期看到海康VM、halcon以及visionpro视觉软件都包含一个图像智能交互控件,然后近期根据其中的技术原理,也基于Qt5仿照开发了一个类似的功能,包含矩形、旋转矩形、任意多边形、圆、圆环、扇环,直线卡尺以及圆卡尺等常用控件,图像智能交互是在计算机视觉领域中

    2024年02月05日
    浏览(59)
  • QT5.14 实现ModbusTCP客户端 Demo

    本文在QT5.14平台,基于QModbusClientTcp类,实现了客户端对单个寄存器的读写,用ModbusSlave做服务器做测试。 1.界面 (1)更改读按钮的名称为bt_Read (2)更改写按钮的名称为bt_Write 2.修改pro文件的第三行 greaterThan(QT_MAJOR_VERSION, 4): QT += widgets  serialbus   3.修改mainWindow.h #ifndef MAINWINDOW_H

    2024年01月22日
    浏览(61)
  • QT5实现职工工资信息管理系统(文件读写)

    暑期学校QT实践项目 该系统需创建和管理如下信息:1、职工信息:工号、姓名、年龄、入职日期、电话、住址、月工资数据集。2、月工资信息:月份、基本工资、岗位工资、工龄工资、津贴、岗贴、补贴、房贴、交通补贴。 系统功能要求如下: 1.创建和管理职工信息的对

    2024年02月09日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包