QT自制软键盘 最完美、最简单、跟自带虚拟键盘一样

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

QT自制软键盘 最完美、最简单、跟自带虚拟键盘一样

  • Chapter1 QT自制软键盘 最完美、最简单、跟自带虚拟键盘一样
    • 一、本自制虚拟键盘特点
    • 二、windows打开系统自带软键盘
    • 三、让键盘界面保持在最上方、不改变底层界面焦点
    • 四、长按按键重复输入键盘内容
    • 五、模拟键盘点击事件完成虚拟键盘输入
    • 六、键盘符号输入
    • 七、界面
    • 八、头文件代码
    • 九、源文件代码
    • 十、使用示例
    • 十一、效果
  • Chapter2 [QDialog]qt虚拟键盘的实现以及qdateedit实现打开虚拟键盘
    • 一、虚拟键盘的拖动
    • 二、创建QDialog类继承于自己写的dialog类并布局键盘界面
    • 三、具体函数的实现
      • 3.1初始化
      • 3.2读取字符
      • 3.3增加字符
      • 3.4删除字符
      • 3.5槽函数
    • 4、自定义QLineEdit实现点击打开自定义键盘
    • 5、qdateedit和qtimeedit控件实现点击打开自定义键盘
      • 5.1安装事件过滤器
      • 5.2写事件过滤
  • Chapter3 Qt 实现虚拟键盘


Chapter1 QT自制软键盘 最完美、最简单、跟自带虚拟键盘一样

原文链接:https://blog.csdn.net/qq_41632571/article/details/125808787

一、本自制虚拟键盘特点

1.键盘界面保持在所有界面最上方。

2.点击键盘按钮不会改变底层文本输入框焦点。

3.通过模拟键盘点击事件完成键盘输入文本信息。

4.包含各种键盘自带符号输入。

5.长按按键可以持续重复输入键盘内容。

6.支持win7、win10、Linux等各个系统。

7.界面好看。

总之跟真的虚拟键盘一样,不会有不爽的地方

二、windows打开系统自带软键盘

QDesktopServices::openUrl(QUrl("osk.exe", QUrl::TolerantMode));

传统打开系统自带虚拟键盘的方法如上,一行代码即可,但是系统自带的虚拟键盘不一定好用,有的按键太小,有的电脑上可能没有自带的软键盘,干脆直接写一个。

三、让键盘界面保持在最上方、不改变底层界面焦点

很多自制键盘时不知道怎么使键盘保持在最顶层,发现点击键盘界面后系统焦点在键盘界面上了,光标不在底层的行输入框里,就通过输入完成后点击确定的方式将键盘内容传到底层界面,显得不nice,其实这两个问题都很简单能够解决,代码如下

this->setWindowFlags(Qt::WindowStaysOnTopHint | Qt::WindowDoesNotAcceptFocus);

Qt::WindowStaysOnTopHint 设置窗口置顶

Qt::WindowDoesNotAcceptFocus 设置无焦点窗口

四、长按按键重复输入键盘内容

特别是我们点击退格删除键时,文本比较多是我们使用真实键盘就会长按退格键把十多个文本挨个删除,而使用虚拟键盘时要按十多次退格键,显得不nice。那么我们使用QPushButton的setAutoRepeat为true,就可以实现按键长按功能了,设置重复操作延时为500ms差不多了,按下的时长超过500ms后马上再次执行按键槽函数。

pbtn->setAutoRepeat(true);    //允许自动重复
pbtn->setAutoRepeatDelay(500);//设置重复操作的时延

五、模拟键盘点击事件完成虚拟键盘输入

一些自制虚拟键盘完成键盘输入的方式是同传递文本到输入框的方式,话不多说,就是不nice。点击虚拟按键直接发送对应的按键点击事件就很nice,这样其实就不会太死,甚至中文输入也可以,我们写的是键盘,不是写中文输入法,那些下载网上含有中文输入法的库的大可不必,输入法你系统用的什么就是什么。如果你想中文输入,系统下载的有搜狗输入法,你的键盘只需按下ctrl+shift切换输入法即可,而不是在键盘里实现中文输入法的功能。那样不nice,模拟发送按键点击事件代码如下。

	QPushButton* pbtn = (QPushButton*)sender();if (pbtn->text() >= 'a' && pbtn->text() <= 'z') {QKeyEvent keyPress(QEvent::KeyPress, int(pbtn->text().at(0).toLatin1()) - 32, Qt::NoModifier, pbtn->text());QKeyEvent keyRelease(QEvent::KeyRelease, int(pbtn->text().at(0).toLatin1()) - 32, Qt::NoModifier, pbtn->text());QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);}

通过QApplication::sendEvent发送一个按键按下和按键松开的事件就相当于模拟一个按键按下事件

QKeyEvent说明:

QKeyEvent::QKeyEvent(QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, const QString &text = QString(), bool autorep = false, ushort count = 1)

类型参数必须为QEvent::KeyPress、QEvent::KeyRelease或QEvent::ShortcutOverride。

Int key是事件循环应该监听的Qt:: key的代码。 如果key为0,则事件不是已知键的结果; 例如,它可能是组合序列或键盘宏的结果。 修饰符包含键盘修饰符,给定的文本是键生成的Unicode文本。 如果autorep为真,isAutoRepeat()将为真。 Count是事件中涉及的键的数量。

QKeyEvent在我们这里用4个参数就行了,第二个参数Qt:: key对应的按键,第四个参数是需要发送的文本,没有这个参数是无法输入任何内容的。

QApplication::sendEvent的第一个参数非常重要,是接收键盘输入的控件,比如是底层界面的lineEdit。

六、键盘符号输入

m_mapSymbolKeys.insert("~", Qt::Key_AsciiTilde);m_mapSymbolKeys.insert("`", Qt::Key_nobreakspace); m_mapSymbolKeys.insert("-", Qt::Key_Minus);m_mapSymbolKeys.insert("_", Qt::Key_Underscore);m_mapSymbolKeys.insert("+", Qt::Key_Plus);m_mapSymbolKeys.insert("=", Qt::Key_Equal);m_mapSymbolKeys.insert(",", Qt::Key_Comma);m_mapSymbolKeys.insert(".", Qt::Key_Period);m_mapSymbolKeys.insert("/", Qt::Key_Slash);m_mapSymbolKeys.insert("<", Qt::Key_Less);m_mapSymbolKeys.insert(">", Qt::Key_Greater);m_mapSymbolKeys.insert("?", Qt::Key_Question);m_mapSymbolKeys.insert("[", Qt::Key_BracketLeft);m_mapSymbolKeys.insert("]", Qt::Key_BracketRight);m_mapSymbolKeys.insert("{", Qt::Key_BraceLeft);m_mapSymbolKeys.insert("}", Qt::Key_BraceRight); m_mapSymbolKeys.insert("|", Qt::Key_Bar);m_mapSymbolKeys.insert("\\", Qt::Key_Backslash);m_mapSymbolKeys.insert(":", Qt::Key_Colon);m_mapSymbolKeys.insert(";", Qt::Key_Semicolon);m_mapSymbolKeys.insert("\"", Qt::Key_QuoteLeft);m_mapSymbolKeys.insert("'", Qt::Key_Apostrophe);QKeyEvent keyPress(QEvent::KeyPress, m_mapSymbolKeys.value(symbol), Qt::NoModifier, symbol);QKeyEvent keyRelease(QEvent::KeyRelease, m_mapSymbolKeys.value(symbol), Qt::NoModifier, symbol);QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);

键盘输入特定的符号重要是找到QKeyEvent第二个参数对应的按键值即可。按键中的值被都在qnamespace.h的头文件中的enum Key枚举类型内。

七、界面

在这里插入图片描述

八、头文件代码

#pragma once
#pragma execution_character_set("utf-8")
#include <QDialog>
#include "ui_frmKeyBoard.h"
#include "moveWidget.h"
#include <QPushButton>
#include <QKeyEvent>
#include <QDebug>
#include <QStyle>class frmKeyBoard : public QDialog
{Q_OBJECTpublic:frmKeyBoard(QWidget *parent = nullptr);~frmKeyBoard();void initFocusWidget(QWidget*);private slots:void slotKeyButtonClicked();void slotKeyLetterButtonClicked();void slotKeyNumberButtonClicked();private:Ui::frmKeyBoardClass ui;void initFrm();void initStyleSheet();QWidget* m_focusWidget;	//键盘输入主窗口QVector<QPushButton*> m_letterKeys;QVector<QPushButton*> m_NumberKeys;QMap<QString, Qt::Key> m_mapSymbolKeys;};

九、源文件代码

#include "frmKeyBoard.h"frmKeyBoard::frmKeyBoard(QWidget *parent): QDialog(parent)
{ui.setupUi(this);this->setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::WindowDoesNotAcceptFocus);this->setWindowTitle("屏幕键盘");this->setWindowModality(Qt::WindowModal); this->setAttribute(Qt::WA_DeleteOnClose);MoveWidget* moveWidget = new MoveWidget();moveWidget->setWidget(this);this->initFrm();this->initStyleSheet();
}frmKeyBoard::~frmKeyBoard()
{
}void frmKeyBoard::initFocusWidget(QWidget* widget)
{m_focusWidget = widget;
}void frmKeyBoard::initFrm()
{ui.pushButton_closeKeyboard->setIcon(style()->standardIcon(QStyle::SP_TitleBarCloseButton));m_letterKeys.clear();m_NumberKeys.clear();QList<QPushButton*> pbtns = this->findChildren<QPushButton*>();foreach(QPushButton * pbtn, pbtns) {pbtn->setAutoRepeat(true);    //允许自动重复pbtn->setAutoRepeatDelay(500);//设置重复操作的时延if (pbtn->text() >= 'a' && pbtn->text() <= 'z') {connect(pbtn, &QPushButton::clicked, this, &frmKeyBoard::slotKeyLetterButtonClicked);m_letterKeys.push_back(pbtn);}else if (pbtn->text().toInt() > 0 && pbtn->text().toInt() <= 9 || pbtn->text() == "0") {connect(pbtn, &QPushButton::clicked, this, &frmKeyBoard::slotKeyNumberButtonClicked);m_NumberKeys.push_back(pbtn);}else{connect(pbtn, &QPushButton::clicked, this, &frmKeyBoard::slotKeyButtonClicked);}}m_mapSymbolKeys.insert("~", Qt::Key_AsciiTilde);m_mapSymbolKeys.insert("`", Qt::Key_nobreakspace); m_mapSymbolKeys.insert("-", Qt::Key_Minus);m_mapSymbolKeys.insert("_", Qt::Key_Underscore);m_mapSymbolKeys.insert("+", Qt::Key_Plus);m_mapSymbolKeys.insert("=", Qt::Key_Equal);m_mapSymbolKeys.insert(",", Qt::Key_Comma);m_mapSymbolKeys.insert(".", Qt::Key_Period);m_mapSymbolKeys.insert("/", Qt::Key_Slash);m_mapSymbolKeys.insert("<", Qt::Key_Less);m_mapSymbolKeys.insert(">", Qt::Key_Greater);m_mapSymbolKeys.insert("?", Qt::Key_Question);m_mapSymbolKeys.insert("[", Qt::Key_BracketLeft);m_mapSymbolKeys.insert("]", Qt::Key_BracketRight);m_mapSymbolKeys.insert("{", Qt::Key_BraceLeft);m_mapSymbolKeys.insert("}", Qt::Key_BraceRight); m_mapSymbolKeys.insert("|", Qt::Key_Bar);m_mapSymbolKeys.insert("\\", Qt::Key_Backslash);m_mapSymbolKeys.insert(":", Qt::Key_Colon);m_mapSymbolKeys.insert(";", Qt::Key_Semicolon);m_mapSymbolKeys.insert("\"", Qt::Key_QuoteLeft);m_mapSymbolKeys.insert("'", Qt::Key_Apostrophe);
}void frmKeyBoard::initStyleSheet()
{QString qss;qss += "QWidget{ background-color:rgb(26,26,26)}";qss += "QPushButton{ color:white; background-color:rgb(51,51,51); height:60px; font-size:bold 15pt; border:1px solid rgb(26,26,26); border-radius: 0px; min-width:50px;}";qss += "QPushButton:hover{background-color:rgb(229,229,229); color:black;}";qss += "QPushButton:pressed,QPushButton:checked{background-color:rgb(0,118,215);}";qss += "#pushButton_closeKeyboard{background-color:rgba(0,0,0,0); border:0px}";qss += "#pushButton_closeKeyboard:hover{background-color:#b30220;}";qss += "#pushButton_space{min-width:500px;}";qss += "#pushButton_backspace,#pushButton_shift{min-width:100px;}";qss += "#pushButton_enter{min-width:120px;}";qss += "#pushButton_tab,#pushButton_ctrl{min-width:70px;}";qss += "#pushButton_capsLock{min-width:80px;}";qss += "#pushButton_up{min-width:150px;}";this->setStyleSheet(qss);
}void frmKeyBoard::slotKeyButtonClicked()
{QPushButton* pbtn = (QPushButton*)sender();QString objectName = pbtn->objectName();if (objectName == "pushButton_closeKeyboard") {this->close();return;}if (pbtn->text().contains("Backspace")) {QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier);QKeyEvent keyRelease(QEvent::KeyRelease, Qt::Key_Backspace, Qt::NoModifier);QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);}else if (pbtn->text().contains("Caps")) {	if (pbtn->isChecked()) {for (auto pbtnKey : m_letterKeys) {pbtnKey->setText(pbtnKey->text().toUpper());}}else {for (auto pbtnKey : m_letterKeys) {pbtnKey->setText(pbtnKey->text().toLower());}}}else if(pbtn->text() == "Space") {QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Space, Qt::NoModifier, " ");QKeyEvent keyRelease(QEvent::KeyRelease, Qt::Key_Space, Qt::NoModifier, " ");QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);}else if (pbtn->text().contains("Tab")) {QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier);QKeyEvent keyRelease(QEvent::KeyRelease, Qt::Key_Tab, Qt::NoModifier);QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);}else if (pbtn->text().contains("Enter")) {QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier);QKeyEvent keyRelease(QEvent::KeyRelease, Qt::Key_Enter, Qt::NoModifier);QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);}else if (pbtn->text().contains("Shift")) {if (pbtn->isChecked()) {for (auto pbtnKey : m_letterKeys) {pbtnKey->setText(pbtnKey->text().toUpper());}}else {for (auto pbtnKey : m_letterKeys) {pbtnKey->setText(pbtnKey->text().toLower());}}QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Shift, Qt::NoModifier);QKeyEvent keyRelease(QEvent::KeyRelease, Qt::Key_Shift, Qt::NoModifier);QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);}else if (pbtn->text().contains("Ctrl")) {QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Control, Qt::NoModifier);QKeyEvent keyRelease(QEvent::KeyRelease, Qt::Key_Control, Qt::NoModifier);QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);}else if (pbtn->text().contains("Win")) {QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Menu, Qt::NoModifier);QKeyEvent keyRelease(QEvent::KeyRelease, Qt::Key_Menu, Qt::NoModifier);QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);}else if (pbtn->text().contains("Alt")) {QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Alt, Qt::NoModifier);QKeyEvent keyRelease(QEvent::KeyRelease, Qt::Key_Alt, Qt::NoModifier);QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);}else if (pbtn->text().contains("↑")) {QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier);QKeyEvent keyRelease(QEvent::KeyRelease, Qt::Key_Up, Qt::NoModifier);QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);}else if (pbtn->text().contains("↓")) {QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier);QKeyEvent keyRelease(QEvent::KeyRelease, Qt::Key_Down, Qt::NoModifier);QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);}else if (pbtn->text().contains("←")) {QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier);QKeyEvent keyRelease(QEvent::KeyRelease, Qt::Key_Left, Qt::NoModifier);QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);}else if (pbtn->text().contains("→")) {QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier);QKeyEvent keyRelease(QEvent::KeyRelease, Qt::Key_Right, Qt::NoModifier);QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);}else {QString symbol;if (ui.pushButton_shift->isChecked())symbol = pbtn->text().split("\n").at(0);elsesymbol = pbtn->text().split("\n").at(1);QKeyEvent keyPress(QEvent::KeyPress, m_mapSymbolKeys.value(symbol), Qt::NoModifier, symbol);QKeyEvent keyRelease(QEvent::KeyRelease, m_mapSymbolKeys.value(symbol), Qt::NoModifier, symbol);QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);}//取消组合键按下if (!pbtn->text().contains("Shift") && !pbtn->text().contains("Ctrl") && !pbtn->text().contains("Win") && !pbtn->text().contains("Alt")) {if (ui.pushButton_shift->isChecked()) {ui.pushButton_shift->setChecked(false);for (auto pbtnKey : m_letterKeys) {pbtnKey->setText(pbtnKey->text().toLower());}}if (ui.pushButton_ctrl->isChecked())ui.pushButton_ctrl->setChecked(false);if (ui.pushButton_win->isChecked())ui.pushButton_win->setChecked(false);if (ui.pushButton_alt->isChecked())ui.pushButton_alt->setChecked(false);}
}void frmKeyBoard::slotKeyLetterButtonClicked()
{QPushButton* pbtn = (QPushButton*)sender();if (pbtn->text() >= 'a' && pbtn->text() <= 'z') {QKeyEvent keyPress(QEvent::KeyPress, int(pbtn->text().at(0).toLatin1()) - 32, Qt::NoModifier, pbtn->text());QKeyEvent keyRelease(QEvent::KeyRelease, int(pbtn->text().at(0).toLatin1()) - 32, Qt::NoModifier, pbtn->text());QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);}else if (pbtn->text() >= 'A' && pbtn->text() <= 'Z') {QKeyEvent keyPress(QEvent::KeyPress, int(pbtn->text().at(0).toLatin1()), Qt::NoModifier, pbtn->text());QKeyEvent keyRelease(QEvent::KeyRelease, int(pbtn->text().at(0).toLatin1()), Qt::NoModifier, pbtn->text());QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);}//取消组合键按下if (ui.pushButton_shift->isChecked()) {ui.pushButton_shift->setChecked(false);for (auto pbtnKey : m_letterKeys) {pbtnKey->setText(pbtnKey->text().toLower());}}if (ui.pushButton_ctrl->isChecked())ui.pushButton_ctrl->setChecked(false);if (ui.pushButton_win->isChecked())ui.pushButton_win->setChecked(false);if (ui.pushButton_alt->isChecked())ui.pushButton_alt->setChecked(false);
}void frmKeyBoard::slotKeyNumberButtonClicked()
{QPushButton* pbtn = (QPushButton*)sender();QKeyEvent keyPress(QEvent::KeyPress, pbtn->text().toInt() + 48, Qt::NoModifier, pbtn->text());QKeyEvent keyRelease(QEvent::KeyRelease, pbtn->text().toInt() + 48, Qt::NoModifier, pbtn->text());QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);//取消组合键按下if (ui.pushButton_shift->isChecked()) {ui.pushButton_shift->setChecked(false);for (auto pbtnKey : m_letterKeys) {pbtnKey->setText(pbtnKey->text().toLower());}}if (ui.pushButton_ctrl->isChecked())ui.pushButton_ctrl->setChecked(false);if (ui.pushButton_win->isChecked())ui.pushButton_win->setChecked(false);if (ui.pushButton_alt->isChecked())ui.pushButton_alt->setChecked(false);
}

十、使用示例

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);QHBoxLayout* layout = new QHBoxLayout();layout->setContentsMargins(0, 0, 0, 0);layout->addWidget(ui->pushButton, 0, Qt::AlignRight);ui->lineEdit->setLayout(layout);}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::on_pushButton_clicked()
{frmKeyBoard* keyBoard = new frmKeyBoard();keyBoard->initFocusWidget(this);keyBoard->show();
}

十一、效果

在这里插入图片描述

Chapter2 [QDialog]qt虚拟键盘的实现以及qdateedit实现打开虚拟键盘

原文链接:https://blog.csdn.net/x1010121/article/details/126534744

一、虚拟键盘的拖动

首先,实现虚拟键盘的拖动功能就需要对QDialog的鼠标事件进行重写,所以就需要自己写一个继承于QDialog的子类。
在这里插入图片描述
这里代码参考qt实现窗口拖动的两种思路_肩上风骋的博客-CSDN博客_qt 拖动窗口

二、创建QDialog类继承于自己写的dialog类并布局键盘界面

在这里插入图片描述
这里除了构造函数以外,还需要初始化、读取字符、添加字符、删除字符四个函数以及一个按钮按下的槽函数,然后对按钮界面进行布局,我的布局如下:。
在这里插入图片描述
一个lineedit以及一些按钮,我这里是写了一个自定义的按钮类,将按钮都提升为我自定义的类型,可以使得按钮更美观。

三、具体函数的实现

3.1初始化

在这里插入图片描述
初始化中是对所有的自定义按钮连接信号与槽,其中findChildren<>函数是搜寻所有能转换为指定类型的控件,这个用于批量处理非常方便,所以这里就批量将按钮的clicked信号与自定义的clicked槽函数绑定。

3.2读取字符

在这里插入图片描述
打开键盘时,要将目标的lineEdit的内容读取到键盘中的lineEdit中,并将私有成员变量value也进行初始化,该函数在构造函数中调用。

3.3增加字符

在这里插入图片描述
实现点击按钮增加对应的字符,并更新lineEdit显示的内容。

3.4删除字符

在这里插入图片描述

实现点击删除按钮时,删除一个字符。

3.5槽函数

在这里插入图片描述
第一步是获取发送信号的按钮的指针,根据指针来判断当前的按钮是哪种类型。第二步针对不同类型做出不同处理,当类型是关闭按钮时就触发qdialog自带的reject信号实现关闭对话框;是接收按钮时就触发qdialog自带的accept信号,这个是用于要写入数据的QLineEdit的信号,后面会用到;是删除按钮就调用删除字符的函数;剩下的就只有添加字符的按钮也就是键盘上的各个数字,实现增加字符。

4、自定义QLineEdit实现点击打开自定义键盘

这里只需要重写lineEdit的mousePressEvent事件,在事件中添加以下代码。
在这里插入图片描述

这里意思是当QLineEdit检测到鼠标按下事件时,打开键盘,并用exec()循环检测是否有Accepted信号触发,这个accepted信号就是前面那个槽函数点击确定时触发的信号,收到这个信号就读取键盘中当前的value的值并写入到控件中。

5、qdateedit和qtimeedit控件实现点击打开自定义键盘

首先也是需要重写这两个类,但与QlineEdit不同的是,这两个控件本身是组合型控件,所以不能简单的重写mousePressEvent事件,而是需要用到事件过滤器。

5.1安装事件过滤器

在这里插入图片描述
这里的lineEdit()就是返回一个QLineEdit对象,这个是这个控件本身获取lineedit子控件的一个方法。

5.2写事件过滤

在这里插入图片描述
这里的主要逻辑是,判断是否是lineedit子控件的鼠标按压事件,如果是就打开键盘,之后根据点击位置的不同来对时、分、秒的数据进行修改,修改完后同样是用exec()循环检测信号来实现输入。

虚拟键盘参考Qt 实现虚拟键盘_lie to me的博客-CSDN博客_qt 虚拟键盘

Chapter3 Qt 实现虚拟键盘

https://blog.csdn.net/weixin_42193704/article/details/108255663?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2defaultOPENSEARCHRate-1-108255663-blog-126534744.pc_relevant_multi_platform_featuressortv2dupreplace&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2defaultOPENSEARCHRate-1-108255663-blog-126534744.pc_relevant_multi_platform_featuressortv2dupreplace&utm_relevant_index=1

利用重写LineEdit 然后监听鼠标点击事件,根据LineEdit 的选择控制是数字键盘还是英文数字混合键盘。
在这里插入图片描述
在这里插入图片描述
实现方式非常的简单

只需要遍历所有的按键然后绑定槽函数

void keyboardNumDialog::init()
{//    this->setWindowFlags(Qt::FramelessWindowHint);
//    this->setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog);setWindowModality(Qt::WindowModal);//半阻塞模式QList<QPushButton *> btn = this->findChildren<QPushButton *>();foreach (QPushButton * b, btn) {connect(b, SIGNAL(clicked()), this, SLOT(btn_clicked()));}}

特殊按键单独处理,如果是数值直接将显示的内容添加到编辑框上就行了

void keyboardNumDialog::btn_clicked()
{QPushButton *btn = (QPushButton *)sender();if(btn == ui->pb_close){this->reject();return ;}if(btn == ui->pb_enter){this->accept();return ;}if(btn == ui->pb_delete){delOneValue();return ;}if(btn == ui->pb_clear){this->value = "";ui->lineEdit->clear();return ;}QString objectName = btn->text();addChar(objectName);
}

LineEdit部分

继承这个控件然后重写鼠标松开事件

然后再界面上提升控件 就可以了

直接监听鼠标单击事件(这样把自己坑了,监听鼠标事件不能监听按下事件要监听松开事件,因为按下以后需要和松开同步使用的,这样操作会导致第一次点击输入法无效)

因为数字输入操作比较频繁,这里改成单例

void LineEditInput::mouseReleaseEvent(QMouseEvent * )
{qDebug()<<this->inputMethodHints()<<" ";if(this->inputMethodHints() == Qt::ImhPreferNumbers){keyboardNumDialog *input = keyboardNumDialog::GetInstance();input->setInputType(QLineEdit::Normal);input->initValue(this->text());
//        keyboardNumDialog *input = bn(this->text());if(input->exec() == QDialog::Accepted){this->setText(input->getValue());}else{}input->close();}else if(this->inputMethodHints() == Qt::ImhHiddenText){keyboardEnDialog input;input.initValue(this->text());if(input.exec() == QDialog::Accepted){this->setText(input.getValue());}else{}}else if(this->echoMode() == QLineEdit::Password){keyboardNumDialog *input = keyboardNumDialog::GetInstance();input->initValue(this->text());input->setInputType(QLineEdit::Password);
//        keyboardNumDialog *input = bn(this->text());if(input->exec() == QDialog::Accepted){this->setText(input->getValue());}else{}input->close();}else{
//        ErrorMessage(tr("Error"),tr("未设置输入类型"));}
}

然后就可以通过Qt Creator UI编辑器中的
在这里插入图片描述
通过选择这两个的其中一个就可以切换数字键盘或者是英文键盘了

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/155796.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

3、在docker 容器中安装tomcat

&#xff11;、在服务器上查找tomcat镜像,查看前5条 docker search tomcat --limit 5​​​​​​​ 2、拉取镜像到本地 拉取官方的tomcat到本地 docker pull tomcat:9.0.34-jdk8 3、查看本地镜像 docker images |grep tomcat 4、启动tomcat 服务 使用默认配置 docker ru…

如何选择一个向量数据库:Elastic Cloud 和 Zilliz Cloud 面面观

随着以 Milvus 为代表的向量数据库在 AI 产业界越来越受欢迎&#xff0c;诸如 Elasticsearch 之类的传统数据库和检索系统也开始行动起来&#xff0c;纷纷在快速集成专门的向量检索插件方面展开角逐。 例如&#xff0c;在提供类似插件的传统数据库中&#xff0c;Elasticsearch …

VAE模型(详细推导+实例代码)

文章目录 EM算法思路E步M步直观感觉 GMM模型VAEVAE思想从GMM到VAE公式推导重参数VAE神经网络另一个视角的VAE思想为什么引入encoder为什么要重参数噪声与重建 Discrete VAE 本文会从EM算法&#xff0c;GMM模型一步一步的的推导&#xff0c;在过渡到VAE模型&#xff0c;如果有熟…

棱镜七彩参编!开源领域4项团体标准正式发布

近日&#xff0c;中电标2023年第27号团体标准公告正式发布&#xff0c;《T/CESA 1270.2-2023 信息技术 开源治理 第 2 部分&#xff1a;企业治理评估模型》、《T/CESA 1270.3-2023 信息技术 开源治理 第 3 部分&#xff1a;社区治理框架》、《T/CESA 1270.5-2023 信息技术 开源…

信创办公–基于WPS的EXCEL最佳实践系列 (单元格与行列)

信创办公–基于WPS的EXCEL最佳实践系列 &#xff08;单元格与行列&#xff09; 目录 应用背景操作步骤1、插入和删除行和列2、合并单元格3、调整行高与列宽4、隐藏行与列5、修改单元格对齐和缩进6、更改字体7、使用格式刷8、设置单元格内的文本自动换行9、应用单元格样式10、插…

STM32F4X I2C LM75

STM32F4X I2C LM75 I2C协议讲解I2C接线I2C协议波形I2C起始信号I2C停止信号I2C应答信号I2C寻址I2C地址格式 I2C数据传输 LM75ALM75A介绍LM75A引脚说明LM75A地址LM75A寄存器LM75A I2C协议写配置寄存器读配置寄存器写Tos和Thyst寄存器读Tos Thyst Temp寄存器LM75A温度计算 LM75A例…

力扣(LeetCode)2578. 最小和分割(C++)

哈希集合 请读者思考&#xff0c;num拆分成num1和num2&#xff0c;要使得num1 num2最小&#xff0c;应满足两条性质&#xff1a; num1和num2位数相同&#xff0c;或最多差一位。num1和num2应按数值从小到大在num中取数。 想到统计num的位数&#xff0c;以实现性质1的需要&a…

淘宝天猫商品历史价格API接口

获取淘宝商品历史价格接口的步骤如下&#xff1a; 注册淘宝开放平台&#xff1a;首先在淘宝开放平台上注册一个账号&#xff0c;并进行登录。创建应用&#xff1a;在淘宝开放平台上创建一个应用&#xff0c;并获取该应用的App Key和App Secret&#xff0c;用于后续的接口调用。…

【数据结构】二叉树的链式结构及实现

目录 1. 前置说明 2. 二叉树的遍历 2.1 前序、中序以及后序遍历 2.2 层序遍历 3. 节点个数及高度等 4. 二叉树的创建和销毁 1. 前置说明 在学习二叉树的基本操作前&#xff0c;需先要创建一棵二叉树&#xff0c;然后才能学习其相关的基本操作。由于现在大家对二叉树结构…

区块链技术的飞跃: 2023年的数字革命

随着时代的推进和技术的不断创新&#xff0c;2023年成为区块链技术飞跃发展的一年。区块链&#xff0c;一个曾经只是数字货币领域的技术&#xff0c;现在已经逐渐渗透到各个行业&#xff0c;成为推动数字经济发展的重要力量。在这个数字革命的时代&#xff0c;我们探讨区块链技…

什么是存储服务器?

随着互联网的发展&#xff0c;越来越多的信息会在网络上暴露&#xff0c;所以企业就会更加重视数据&#xff0c;因此更加安全可靠的数据存储服务器受到了大多数人的信赖&#xff0c;今天就让小编带大家了解一下什么是存储服务器吧&#xff01; 存储服务器的含义。存储服务器是…

代理IP端口是什么意思呢?

今天&#xff0c;咱们来聊聊一个小众但很有料的话题——代理IP端口&#xff0c;它可是你纵横互联网世界的好搭子哦&#xff01; 首先&#xff0c;我们得先弄明白&#xff0c;代理IP端口是个啥? 代理IP端口就像是通往网络世界的门票&#xff0c;是你和代理服务器之间的桥梁。…

使用注解新开事务 @Transactional

使用注解新开事务 Transactional(propagation Propagation.REQUIRES_NEW)

使用Perl脚本编写爬虫程序的一些技术问题解答

网络爬虫是一种强大的工具&#xff0c;用于从互联网上收集和提取数据。Perl 作为一种功能强大的脚本语言&#xff0c;提供了丰富的工具和库&#xff0c;使得编写的爬虫程序变得简单而灵活。在使用的过程中大家会遇到一些问题&#xff0c;本文将通过问答方式&#xff0c;解答一些…

Jetson Orin NX 开发指南(6): VINS-Fusion-gpu 的编译和运行

一、前言 由于 Jetson 系列的开发板 CPU 性能不是很好&#xff0c;因此在处理图像数据时往往需要 GPU 加速&#xff0c;而 VINS-Fusion 是针对同步定位与建图&#xff08;SLAM&#xff09;问题中十分出色的视觉算法&#xff0c;但是其在图像处理过程中资源消耗较大&#xff0c…

执行make menuconfig问题的解决

执行make menuconfig 出现问题 在终端输入以下命令执行。 make menuconfig在终端输入上面命令执行时&#xff0c;没有成功运行&#xff0c;出现了如下的问题。 出现这个错误提示意味着在运行 make menuconfig 命令时&#xff0c;系统找不到 ncurses 库。ncurses 是一种文本用…

iPhone手机记笔记工具选择用哪个

iPhone手机大家应该都比较熟悉&#xff0c;其使用性能是比较流畅的&#xff0c;在iPhone手机上记录笔记可以帮助大家快速地进行总结工作、记录工作内容等&#xff0c;在iPhone手机上记笔记工具选择用哪个呢&#xff1f; 可以在iPhone手机上使用的笔记工具是比较多的&#xff0…

Vue3中使用tinymce全功能演示,包括开源功能

效果图&#xff1a; 1、下载插件: npm i tinymce npm i tinymce/tinymce-vue 2、在node_modules文件夹中找到tinymce下的skins复制到项目public文件夹中 &#xff08;可以先创建一个tinymce文件夹&#xff09;&#xff1a; 3、在tinymce官网中下载中文包&#xff0c;并放在刚…

FISCO BCOS | 构建第一个区块链应用程序

本章将介绍基于FISCO BCOS区块链的业务应用场景开发的全流程。介绍包括业务场景分析、合约设计实现、合约编译、区块链开发等。最后&#xff0c;我们介绍一个应用模块实现&#xff0c;即通过我们提供的Java SDK实现对区块链上合约的调用访问。 本教程要求用户熟悉Linux操作环境…

NCV6324CMTAATBG---车规级3MHz 2A 高效同步降压转换器

同步降压转换器&#xff1f; 是一种电源管理电路&#xff0c;它可以将输入电压转换为较低的输出电压。与传统的降压转换器相比&#xff0c;同步降压转换器具有更高的效率和更好的动态响应。 同步降压转换器的工作原理是通过控制开关管的导通和截止来实现电能的转换。在导通状…