QT6实现软键盘的两种方法
一.概述
在触摸屏设备上,软键盘是替代物理键盘的重要输入方式。一般简单的功能需要数字小键盘,复杂的需要全键盘。
二.QT6实现数字小键盘
1.numkeyboard.h
#ifndef NUMKEYBOARD_H
#define NUMKEYBOARD_H
#include <QDialog>
#include <QtDebug>
#include <QKeyEvent>
#include <QEvent>
#include <QLineEdit>
#include <QPushButton>
class NumKeyboard : public QDialog
{
Q_OBJECT
public:
explicit NumKeyboard(QWidget *parent = 0);
~NumKeyboard();
bool valid;
QLineEdit *lineEdit;
QPushButton *num1Button;
QPushButton *num2Button;
QPushButton *num3Button;
QPushButton *num4Button;
QPushButton *num5Button;
QPushButton *num6Button;
QPushButton *num7Button;
QPushButton *num8Button;
QPushButton *num9Button;
QPushButton *num0Button;
QPushButton *dotButton;//“.”
QPushButton *delButton;//删除
QPushButton *signButton;//+-
QPushButton *clearButton;//清除
QPushButton *cancelButton;
QPushButton *okButton;
void setText(QString str);
QString getText();
void InitUI();
protected:
void changeEvent(QEvent *e);
bool eventFilter(QObject *obj, QEvent *event);
private slots:
void on_num1Button_clicked();
void on_num2Button_clicked();
void on_num3Button_clicked();
void on_num4Button_clicked();
void on_num5Button_clicked();
void on_num6Button_clicked();
void on_num7Button_clicked();
void on_num8Button_clicked();
void on_num9Button_clicked();
void on_num0Button_clicked();
void on_dotButton_clicked();
void on_signButton_clicked();
void on_delButton_clicked();
void on_cancelButton_clicked();
void on_okButton_clicked();
void on_clearButton_clicked();
private:
QString strContent;
};
#endif // NUMKEYBOARD_H
2.numkeyboard.cpp
#include "numkeyboard.h"
#include <QDebug>
//#include "qtextcodec.h"
NumKeyboard::NumKeyboard(QWidget *parent) :
QDialog(parent)
{
setWindowTitle(tr("数字键盘"));
setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowTitleHint);
InitUI();
connect(num1Button, SIGNAL(clicked()), this, SLOT(on_num1Button_clicked()));
connect(num2Button, SIGNAL(clicked()), this, SLOT(on_num2Button_clicked()));
connect(num3Button, SIGNAL(clicked()), this, SLOT(on_num3Button_clicked()));
connect(num4Button, SIGNAL(clicked()), this, SLOT(on_num4Button_clicked()));
connect(num5Button, SIGNAL(clicked()), this, SLOT(on_num5Button_clicked()));
connect(num6Button, SIGNAL(clicked()), this, SLOT(on_num6Button_clicked()));
connect(num7Button, SIGNAL(clicked()), this, SLOT(on_num7Button_clicked()));
connect(num8Button, SIGNAL(clicked()), this, SLOT(on_num8Button_clicked()));
connect(num9Button, SIGNAL(clicked()), this, SLOT(on_num9Button_clicked()));
connect(num0Button, SIGNAL(clicked()), this, SLOT(on_num0Button_clicked()));
connect(dotButton, SIGNAL(clicked()), this, SLOT(on_dotButton_clicked()));
connect(cancelButton, SIGNAL(clicked()), this, SLOT(on_cancelButton_clicked()));
connect(okButton, SIGNAL(clicked()), this, SLOT(on_okButton_clicked()));
connect(signButton, SIGNAL(clicked()), this, SLOT(on_signButton_clicked()));
connect(delButton, SIGNAL(clicked()), this, SLOT(on_delButton_clicked()));
connect(clearButton, SIGNAL(clicked()), this, SLOT(on_clearButton_clicked()));
}
NumKeyboard::~NumKeyboard()
{
}
void NumKeyboard::InitUI()
{
QFont font;
font.setPointSize(22);
QFont font1;
font1.setPointSize(16);
num1Button = new QPushButton(this);
num1Button->setText("1");
num1Button->setGeometry(QRect(10, 70, 55, 50));
num1Button->setFont(font);
num1Button->setFocusPolicy(Qt::NoFocus);//去掉焦点
num2Button = new QPushButton(this);
num2Button->setText("2");
num2Button->setGeometry(QRect(75, 70, 55, 50));
num2Button->setFont(font);
num2Button->setFocusPolicy(Qt::NoFocus);
num3Button = new QPushButton(this);
num3Button->setText("3");
num3Button->setGeometry(QRect(140, 70, 55, 50));
num3Button->setFont(font);
num3Button->setFocusPolicy(Qt::NoFocus);
cancelButton = new QPushButton(this);
cancelButton->setText("Esc");
cancelButton->setGeometry(QRect(205, 70, 95, 50));
cancelButton->setFont(font1);
cancelButton->setFocusPolicy(Qt::NoFocus);
//-----------------------------------------------------------------------//
num4Button = new QPushButton(this);
num4Button->setText("4");
num4Button->setGeometry(QRect(10, 130, 55, 50));
num4Button->setFont(font);
num4Button->setFocusPolicy(Qt::NoFocus);
num5Button = new QPushButton(this);
num5Button->setText("5");
num5Button->setGeometry(QRect(75, 130, 55, 50));
num5Button->setFont(font);
num5Button->setFocusPolicy(Qt::NoFocus);
num6Button = new QPushButton(this);
num6Button->setText("6");
num6Button->setGeometry(QRect(140, 130, 55, 50));
num6Button->setFont(font);
num6Button->setFocusPolicy(Qt::NoFocus);
delButton = new QPushButton(this);
delButton->setText(tr("←"));
delButton->setGeometry(QRect(205, 130, 95, 50));
delButton->setFont(font1);
delButton->setFocusPolicy(Qt::NoFocus);
//-----------------------------------------------------------------------//
num7Button = new QPushButton(this);
num7Button->setText("7");
num7Button->setGeometry(QRect(10, 190, 55, 50));
num7Button->setFont(font);
num7Button->setFocusPolicy(Qt::NoFocus);
num8Button = new QPushButton(this);
num8Button->setText("8");
num8Button->setGeometry(QRect(75, 190, 55, 50));
num8Button->setFont(font);
num8Button->setFocusPolicy(Qt::NoFocus);
num9Button = new QPushButton(this);
num9Button->setText("9");
num9Button->setGeometry(QRect(140, 190, 55, 50));
num9Button->setFont(font);
num9Button->setFocusPolicy(Qt::NoFocus);
clearButton = new QPushButton(this);
clearButton->setText("C");
clearButton->setGeometry(QRect(205, 190, 95, 50));
clearButton->setFont(font1);
clearButton->setFocusPolicy(Qt::NoFocus);
//-----------------------------------------------------------------------//
signButton = new QPushButton(this);
signButton->setText(tr("±"));
signButton->setGeometry(QRect(10, 250, 55, 50));
signButton->setFont(font1);
signButton->setFocusPolicy(Qt::NoFocus);
num0Button = new QPushButton(this);
num0Button->setText("0");
num0Button->setGeometry(QRect(75, 250, 55, 50));
num0Button->setFont(font);
num0Button->setFocusPolicy(Qt::NoFocus);
dotButton = new QPushButton(this);
dotButton->setText(".");
dotButton->setGeometry(QRect(140, 250, 55, 50));
dotButton->setFont(font);
dotButton->setFocusPolicy(Qt::NoFocus);
okButton = new QPushButton(this);
okButton->setText(tr("OK"));
okButton->setGeometry(QRect(205, 250, 95, 50));
okButton->setFont(font1);
okButton->setFocusPolicy(Qt::NoFocus);
//-----------------------------------------------------------------------//
lineEdit = new QLineEdit(this);
lineEdit->setGeometry(QRect(10, 10, 290, 50));
QFont font3;
font3.setPointSize(24);
//font3.setWeight(50);
lineEdit->setFont(font3);
lineEdit->setText(QString());
//lineEdit->installEventFilter(this);//创建事件过滤器,eventFilter函数才有效
}
void NumKeyboard::changeEvent(QEvent *e)
{
QDialog::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
break;
default:
break;
}
}
bool NumKeyboard::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::KeyPress)
{
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
if (obj == lineEdit)
{
if(keyEvent->key() >= 0x20 && keyEvent->key()<= 0x0ff) //屏蔽所有按键输入
return true;
else
return false;
}
else
{
return false;
}
}
else
{
// standard event processing
return QObject::eventFilter(obj, event);
}
}
//***********************按键*****************************//
void NumKeyboard::on_num1Button_clicked() //1
{
int idx = lineEdit->cursorPosition(); //根据光标的位置索引
if(strContent.left(idx) == "0") //除了小数外,第一个数不为0
{
lineEdit->setCursorPosition(idx);
lineEdit->setFocus();
return;
}
// 字符串的存储有引用计数,当一个 QString 对象被复制为另一个 QString 对象时,它们实际上指向相同的存储空间,仅仅是增加一个引用计数
strContent.insert(idx, '1'); //插入字符串str在给定的索引位置对这个字符串,并返回一个引用。 //数据存入strContent
lineEdit->setText(strContent); //strContent中的内容显示在lineEdit
lineEdit->setCursorPosition(idx+1); //设置光标的位置 ??不设置好像也可以使用设定光标的位置
lineEdit->setFocus(); //存在光标
qDebug()<<"strContent"<<strContent;
qDebug()<<"idx"<<idx;
}
void NumKeyboard::on_num2Button_clicked() //2
{
int idx = lineEdit->cursorPosition();
if(strContent.left(idx) == "0")
{
lineEdit->setCursorPosition(idx);
lineEdit->setFocus();
return;
}
strContent.insert(idx, '2');
lineEdit->setText(strContent);
lineEdit->setCursorPosition(idx+1);
lineEdit->setFocus();
}
void NumKeyboard::on_num3Button_clicked() //3
{
int idx = lineEdit->cursorPosition();
if(strContent.left(idx) == "0")
{
lineEdit->setCursorPosition(idx);
lineEdit->setFocus();
return;
}
strContent.insert(idx, '3');
lineEdit->setText(strContent);
lineEdit->setCursorPosition(idx+1);
lineEdit->setFocus();
}
void NumKeyboard::on_num4Button_clicked() //4
{
int idx = lineEdit->cursorPosition();
if(strContent.left(idx) == "0")
{
lineEdit->setCursorPosition(idx);
lineEdit->setFocus();
return;
}
strContent.insert(idx, '4');
lineEdit->setText(strContent);
lineEdit->setCursorPosition(idx+1);
lineEdit->setFocus();
}
void NumKeyboard::on_num5Button_clicked() //5
{
int idx = lineEdit->cursorPosition();
if(strContent.left(idx) == "0")
{
lineEdit->setCursorPosition(idx);
lineEdit->setFocus();
return;
}
strContent.insert(idx, '5');
lineEdit->setText(strContent);
lineEdit->setCursorPosition(idx+1);
lineEdit->setFocus();
}
void NumKeyboard::on_num6Button_clicked() //6
{
int idx = lineEdit->cursorPosition();
if(strContent.left(idx) == "0")
{
lineEdit->setCursorPosition(idx);
lineEdit->setFocus();
return;
}
strContent.insert(idx, '6');
lineEdit->setText(strContent);
lineEdit->setCursorPosition(idx+1);
lineEdit->setFocus();
}
void NumKeyboard::on_num7Button_clicked() //7
{
int idx = lineEdit->cursorPosition();
if(strContent.left(idx) == "0")
{
lineEdit->setCursorPosition(idx);
lineEdit->setFocus();
return;
}
strContent.insert(idx, '7');
lineEdit->setText(strContent);
lineEdit->setCursorPosition(idx+1);
lineEdit->setFocus();
}
void NumKeyboard::on_num8Button_clicked() //8
{
int idx = lineEdit->cursorPosition();
if(strContent.left(idx) == "0")
{
lineEdit->setCursorPosition(idx);
lineEdit->setFocus();
return;
}
strContent.insert(idx, '8');
lineEdit->setText(strContent);
lineEdit->setCursorPosition(idx+1);
lineEdit->setFocus();
}
void NumKeyboard::on_num9Button_clicked() //9
{
int idx = lineEdit->cursorPosition();
if(strContent.left(idx) == "0")
{
lineEdit->setCursorPosition(idx);
lineEdit->setFocus();
return;
}
strContent.insert(idx, '9');
lineEdit->setText(strContent);
lineEdit->setCursorPosition(idx+1);
lineEdit->setFocus();
}
void NumKeyboard::on_dotButton_clicked() //.
{
int idx = lineEdit->cursorPosition();
// if(idx==0 || strContent.contains('.'))
// {
// lineEdit->setCursorPosition(idx);
// lineEdit->setFocus();
// return;
// }
strContent.insert(idx, '.');
lineEdit->setText(strContent);
lineEdit->setCursorPosition(idx+1);
lineEdit->setFocus();
}
void NumKeyboard::on_num0Button_clicked() //0
{
int idx = lineEdit->cursorPosition();
if(strContent.left(idx) == "0" || (idx==0 &&strContent!=""))
{
lineEdit->setCursorPosition(idx);
qDebug()<<"idx"<<idx;
lineEdit->setFocus();
return;
}
strContent.insert(idx, '0');
lineEdit->setText(strContent);
lineEdit->setCursorPosition(idx+1);
lineEdit->setFocus();
}
void NumKeyboard::on_signButton_clicked() //±
{
int idx = lineEdit->cursorPosition();
if(strContent.left(1) == "-")
{
strContent.remove(0, 1);
lineEdit->setText(strContent);
lineEdit->setCursorPosition(idx-1);
lineEdit->setFocus();
}
else
{
if(strContent=="0" /*|| strContent==""*/)
{
lineEdit->setCursorPosition(idx);
lineEdit->setFocus();
}
else
{
strContent.insert(0, '-');
lineEdit->setText(strContent);
lineEdit->setCursorPosition(idx+1);
lineEdit->setFocus();
}
}
}
void NumKeyboard::on_clearButton_clicked() //清除
{
int idx = lineEdit->cursorPosition();
if(idx == 0)
{
lineEdit->setCursorPosition(idx);
lineEdit->setFocus();
return;
}
//strContent.remove(0,idx);
strContent.clear();
lineEdit->setText(strContent);
lineEdit->setCursorPosition(0);
lineEdit->setFocus();
}
void NumKeyboard::on_delButton_clicked() //删除
{
int idx = lineEdit->cursorPosition();
if(idx == 0)
{
lineEdit->setCursorPosition(idx);
lineEdit->setFocus();
return;
}
strContent.remove(idx-1,1);
lineEdit->setText(strContent);
lineEdit->setCursorPosition(idx-1);
lineEdit->setFocus();
}
void NumKeyboard::on_cancelButton_clicked() //cancel
{
this->close();
valid = false;
}
void NumKeyboard::on_okButton_clicked() //ok
{
this->close();
valid = true;
}
void NumKeyboard::setText(QString str) //设置文本内容
{
strContent = str;
lineEdit->setText(strContent);
lineEdit->setFocus();
}
QString NumKeyboard::getText() //获取内容
{
return strContent;
}
3.测试代码
#include "widget.h"
#include "ui_widget.h"
#include <QTime>
#include <QCoreApplication>
#include <QMessageBox>
#include "QListView"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
ui->lineEdit_freq->installEventFilter(this); // 确保这行代码存在
numkeyboard = new NumKeyboard(); //数字键盘
}
Widget::~Widget()
{
qDebug()<<">>>>~Widget()";
delete ui;
}
bool Widget::eventFilter(QObject *watched, QEvent *event)
{
if(watched == ui->lineEdit_freq && event->type()==QEvent::MouseButtonPress)
{
numkeyboard->setText(ui->lineEdit_freq->text()); //当前的文本框的内容,this->指向的是SoftKeyLineEdit
numkeyboard->exec();
if(numkeyboard->valid)
{
ui->lineEdit_freq->setText(numkeyboard->getText()); //此处的setText是继承QLineEdit的,numkeyboard->setTex是自定义的,目的是获取当前的文本
}
return true; // 表示已处理该事件
}
return QWidget::eventFilter(watched, event); // 其他事件交基类处理
}
4.效果图
三.调用windows的自带软键盘osk.exe
1.代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <qmessagebox.h>
#include <QProcess>
#include <qdebug.h>
#include <qdesktopservices.h>
#include <QUrl>
#include <windows.h>
#pragma comment(lib,"user32.lib")
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->lineEdit->clear();
ui->lineEdit_2->clear();
ui->lineEdit->installEventFilter(this);
ui->lineEdit_2->installEventFilter(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
PVOID Oldvalue = nullptr;
BOOL bRet = Wow64DisableWow64FsRedirection(&Oldvalue);
QString csprocess = "C:\\Windows\\System32\\osk.exe";
QString param = "";
ShellExecute(nullptr,L"open",(LPCWSTR)csprocess.utf16(),(LPCWSTR)param.utf16(),nullptr,SW_SHOWNORMAL);
if(bRet)
{
Wow64RevertWow64FsRedirection(Oldvalue);
}
//发现及设置键盘大小 2025.6.24+
// 尝试查找屏幕键盘窗口
m_hOskWnd = FindWindowW(L"OSKMainClass", nullptr);
// 设置窗口尺寸 (宽度x高度)
int newWidth = 300; // 设置所需宽度
int newHeight = 300; // 设置所需高度
// 获取屏幕尺寸以居中窗口
int screenWidth = GetSystemMetrics(SM_CXSCREEN);
int screenHeight = GetSystemMetrics(SM_CYSCREEN);
int xPos = (screenWidth - newWidth) / 2;
int yPos = (screenHeight - newHeight) * 2 / 4; // 底部2/4处
// 调整窗口大小和位置
SetWindowPos(m_hOskWnd, nullptr,
xPos, yPos,
newWidth, newHeight,
SWP_NOZORDER | SWP_NOACTIVATE);
qDebug() << "On-screen keyboard resized to"
<< newWidth << "x" << newHeight;
}
2.效果图