QT的软键盘设计
QT中右键提升一个组件:作用就是把这个组件的类型变成提升之后的新类型,若程序员自己想要自定义实现某个控件的功能,就可用该功能
1.软键盘制作步骤
cpp
第一步:在QT工程中新添加一个软键盘的ui(模板选择QWidget),并布局好软键盘的ui
顺便把按钮的focusPolicy这个属性改成noFocus(没有鼠标焦点,鼠标光标不会在按钮上停留)
第二步:在你的主窗口中拖一个widget(等一会软键盘嵌套到这个widget中来显示的),右键点击widget,选择提升为刚才新建的软键盘类
第三步:实现软键盘的代码逻辑(让软键盘可以使用)
思路一:使用传统的方法,信号与槽(很麻烦)
思路二:使用QT中的按键事件来实现软键盘
在QT工程新增一个mybutton的类继承QPushButton(按钮类),关联信号与槽函数,在槽函数中实现按键的逻辑
第四步:mybutton里面的槽函数代码如下
//获取信号的发送者
QPushButton *p=qobject_cast<QPushButton *>(sender());
QString str=p->text(); // 获取按钮的字面值
//按照事件产生的流程去写代码
//自定义一个按键事件
QKeyEvent *keyevent=new QKeyEvent(QEvent::KeyPress,str.toInt()-32,Qt::NoModifier,str);
//把这个按键事件发送出去--》发送个鼠标光标聚集的组件
QCoreApplication::postEvent(QApplication::focusWidget(),keyevent);
2.介绍有关函数的使用
cpp
QKeyEvent::QKeyEvent(Type type, int key, Qt::KeyboardModifiers modifiers, const QString &text = QString())
参数: type --》事件类型 QEvent::KeyPress
key --》按键的键值
摸索规律:字母按键(无论大小写)
键值 A/a 65
B/b 66
modifiers --》你是否使用了某个组合键
Qt::NoModifier //没有使用组合键
Qt::ShiftModifier //使用了shift按键
text --》点击的按键的字面值
//把指定的事件发送出去
[static] void QCoreApplication::postEvent(QObject *receiver, QEvent *event)
参数:receiver --》事件的接收者
event --》要发送的某种事件
//鼠标的光标停留在哪个组件上,该函数立马返回这个组件的地址
[static] QWidget *QApplication::focusWidget() //返回鼠标光标聚集的组件
3.出现的编译错误及解决办法
cpp
第一个:QObject::connect: No such slot QPushButton::fun() in ..\solfkeydemo\mybutton.cpp:6
原因:你的mybutton这个类中使用了信号与槽,忘记添加Q_OBJECT这个宏定义了
解决方法:在mybutton的头文件中把Q_OBJECT这个宏定义加上即可
第二个:C:\Users\PC\Desktop\share\solfkeydemo\mybutton.cpp:3: error: undefined reference to `vtable for mybutton'
解决方法:把编译产生的临时文件全部删除,重新打开工程,再次编译
示例代码1:按键事件实现软键盘
当前目录结构:
cpp
// widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QDebug>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
// widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
qDebug()<<"Widget::Widget 构造";
}
Widget::~Widget()
{
delete ui;
}
//=======================================================//
// soft_keyboard.h
#ifndef SOFT_KEYBOARD_H
#define SOFT_KEYBOARD_H
#include <QWidget>
#include <QDebug>
namespace Ui {
class soft_keyboard;
}
class soft_keyboard : public QWidget
{
Q_OBJECT
public:
explicit soft_keyboard(QWidget *parent = nullptr);
~soft_keyboard();
private:
Ui::soft_keyboard *ui;
};
#endif // SOFT_KEYBOARD_H
// soft_keyboard.cpp
#include "soft_keyboard.h"
#include "ui_soft_keyboard.h"
soft_keyboard::soft_keyboard(QWidget *parent) :
QWidget(parent),
ui(new Ui::soft_keyboard)
{
ui->setupUi(this);
qDebug()<<"soft_keyboard::soft_keyboard 构造";
}
soft_keyboard::~soft_keyboard()
{
delete ui;
}
//=======================================================//
// custom_button.h
#ifndef CUSTOM_BUTTON_H
#define CUSTOM_BUTTON_H
#include <QPushButton>
#include <QDebug>
#include <QCoreApplication>
#include <QKeyEvent>
#include <QApplication>
class custom_button : public QPushButton
{
Q_OBJECT
public:
explicit custom_button(QWidget *parent = nullptr);
private slots:
void func();
};
#endif // CUSTOM_BUTTON_H
// custom_button.cpp
#include "custom_button.h"
custom_button::custom_button(QWidget *parent) : QPushButton(parent)
{
qDebug()<<"custom_button 构造";
connect(this, &QPushButton::clicked, this, &custom_button::func);
// connect(this, SIGNAL(clicked()), this, SLOT(func()));
}
void custom_button::func()
{
//获取信号的发送者
QPushButton *p=qobject_cast<QPushButton *>(sender());
QString str=p->text(); // 获取按钮的字面值
#if 0
if (!str.isEmpty()) {
QChar ch = str.at(0);
int key = ch.toUpper().unicode(); // 获取大写字符的键值
QKeyEvent *keyevent = new QKeyEvent(
QEvent::KeyPress,
key,
Qt::NoModifier,
QString(ch)
);
QCoreApplication::postEvent(QApplication::focusWidget(), keyevent);
}
#else
//按照事件产生的流程写代码
//自定义一个按键事件
QKeyEvent *keyevent=new QKeyEvent(QEvent::KeyPress,str.toInt() - 32,Qt::NoModifier,str);
//把这个按键事件发送出去--》发送给鼠标光标聚集的组件
QCoreApplication::postEvent(QApplication::focusWidget(),keyevent);
#endif
}
现象:

示例代码2:按键事件实现软键盘(加特殊按键)
与示例代码1的差别是在槽函数中增加了特殊按键的判断
cpp
// custom_button.h
#ifndef CUSTOM_BUTTON_H
#define CUSTOM_BUTTON_H
#include <QPushButton>
#include <QDebug>
#include <QCoreApplication>
#include <QKeyEvent>
#include <QApplication>
class custom_button : public QPushButton
{
Q_OBJECT
public:
explicit custom_button(QWidget *parent = nullptr);
private slots:
void func();
};
#endif // CUSTOM_BUTTON_H
// custom_button.cpp
#include "custom_button.h"
custom_button::custom_button(QWidget *parent) : QPushButton(parent)
{
qDebug()<<"custom_button 构造";
connect(this, &QPushButton::clicked, this, &custom_button::func);
// connect(this, SIGNAL(clicked()), this, SLOT(func()));
}
void custom_button::func()
{
//获取信号的发送者
QPushButton *p=qobject_cast<QPushButton *>(sender());
QString str=p->text(); // 获取按钮的字面值
#if 0
if (!str.isEmpty()) {
QChar ch = str.at(0);
int key = ch.toUpper().unicode(); // 获取大写字符的键值
QKeyEvent *keyevent = new QKeyEvent(
QEvent::KeyPress,
key,
Qt::NoModifier,
QString(ch)
);
QCoreApplication::postEvent(QApplication::focusWidget(), keyevent);
}
#else
//按照事件产生的流程写代码
QKeyEvent *keyevent;
//判断特殊按键
if(str=="Backspace") //退格键
{
//自定义一个按键事件
keyevent=new QKeyEvent(QEvent::KeyPress,Qt::Key_Backspace,Qt::NoModifier,str);
}
else if(str=="Enter")
{
//自定义一个按键事件
keyevent=new QKeyEvent(QEvent::KeyPress,Qt::Key_Enter,Qt::NoModifier,str);
}
else if(str=="")
{
//自定义一个按键事件
keyevent=new QKeyEvent(QEvent::KeyPress,Qt::Key_Space,Qt::NoModifier," ");
}
else //字母按键
{
//自定义一个按键事件
keyevent=new QKeyEvent(QEvent::KeyPress,str.toInt()-32,Qt::NoModifier,str);
}
//把这个按键事件发送出去--》发送给鼠标光标聚集的组件
QCoreApplication::postEvent(QApplication::focusWidget(),keyevent);
#endif
}
现象:

软键盘移植到新的工程的步骤:
1.将已实现的功能代码copy到新工程目录下
2.在工程文件名下右键---》添加现有文件
3.选择第一步copy过去的文件进行添加
4.在新工程中设计界面,将widget类提升为自定义的软键盘类

5.编译后即可使用
自定义软键盘设计步骤:图示
1.先在主窗口设计好界面,此时可以看到widget的类为QWidget(这个widget就是用来存放软件的)
2.新建一个UI界面用来设计软键盘(添加新的设计师界面类)
3.右键widget控件,选择提升为...,将该widget提升为上一步自定义的软键盘界面类

4.填写提升的类名称,如下
5.此时可以看到已将widget提升为自定义的软键盘类
7.编译后也可以看到已经显示到主窗口
7.新建一个C++类,使其继承自QPushButton (用来实现软键盘的功能)

8.将软键盘界面的按钮类提升为新建的C++类,此时该软键盘界面使用的就是该类写好的功能
9.将焦点策略改为不聚焦,这样在点击按钮时,此时的焦点就不是是按钮,而是单行输入框,这样就可以根据新建的C++类写好的事件进行处理
9.在新建的custom_button类(这里是上边提到的新建的C++类)中关联信号与槽函数,在槽函数中实现按键的逻辑
cpp
#include "custom_button.h"
custom_button::custom_button(QWidget *parent) : QPushButton(parent)
{
qDebug()<<"custom_button 构造";
connect(this, &QPushButton::clicked, this, &custom_button::func);
// connect(this, SIGNAL(clicked()), this, SLOT(func()));
}
void custom_button::func()
{
//获取信号的发送者
QPushButton *p=qobject_cast<QPushButton *>(sender());
QString str=p->text(); // 获取按钮的字面值
qDebug()<<"str.toInt():"<<str.toInt();
//按照事件产生的流程写代码
//自定义一个按键事件 str.toInt()-32 :输入按钮字面值的ASCII 值 -32 如输入a:即键值是97-32
QKeyEvent *keyevent=new QKeyEvent(QEvent::KeyPress,str.toInt() - 32,Qt::NoModifier,str);
//把这个按键事件发送出去--》发送个鼠标光标聚集的组件
QCoreApplication::postEvent(QApplication::focusWidget(),keyevent);
}
11.现象如下