|
刚接触QT,老大让我做一个软键盘,前面根据QT自带的Example改写了一个,无奈是用UI设计师拖出来的界面不过关,于是痛定思痛,又做了一个,界面全靠手打的说,可以切换键盘与数字,不说了上图:
这是开始画面,点击就会弹出键盘
这是弹出的字母键盘,很丑我知道
这是切换的数字键盘 我知道丑。。
本人初学者哦。请轻喷。下面说代码
loain.h
#ifndef LOAIN_H
#define LOAIN_H
#include <QtCore/QVariant>
#include <QAction>
#include <QApplication>
#include <QButtonGroup>
#include <QHeaderView>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QWidget>
class loain: public QWidget
{
Q_OBJECT
public:
QLabel *label;
QLineEdit *lineEdit;
QPushButton *pushButton;
void setupUi(QWidget *import);
};
#endif // LOAIN_H
loain.app
#include "loain.h"
void loain::setupUi(QWidget *import)
{
import->setGeometry(300,300,300,100);
label = new QLabel(import);
label->setGeometry(10,10,100,20);
label->setText(tr("please input:"));
lineEdit = new QLineEdit(import);
lineEdit->setGeometry(100,10,100,20);
pushButton = new QPushButton(import);
pushButton->setText("close");
pushButton->setGeometry(200,60,60,30);
connect(pushButton,SIGNAL(clicked()),import,SLOT(close()));
}
这一段没有什么特别的,就是建立了一个开始的窗口,一个LineEdit输入文档。
keyboard.h
#ifndef KEYBOARD_H
#define KEYBOARD_H
#include <QWidget>
#include <QPushButton>
#include <QLineEdit>
#include <QFormLayout>
#include <QStackedWidget>
#include <QObject>
#include <Qt>
#include <QButtonGroup>
#include <QMetaObject>
class keyboard: public QWidget
{
Q_OBJECT
public:
QStackedWidget *my_stackedWidget;
QWidget *window_alp;
QButtonGroup *buttonGroup_alp;
QPushButton *button_Q;
QPushButton *button_W;
QPushButton *button_E;
QPushButton *button_R;
QPushButton *button_T;
QPushButton *button_Y;
QPushButton *button_U;
QPushButton *button_I;
QPushButton *button_O;
QPushButton *button_P;
QPushButton *button_A;
QPushButton *button_S;
QPushButton *button_D;
QPushButton *button_F;
QPushButton *button_G;
QPushButton *button_H;
QPushButton *button_J;
QPushButton *button_K;
QPushButton *button_L;
QPushButton *button_Z;
QPushButton *button_X;
QPushButton *button_C;
QPushButton *button_V;
QPushButton *button_B;
QPushButton *button_N;
QPushButton *button_M;
QPushButton *button_blank;
QPushButton *button_delete;
QPushButton *button_nu;
QPushButton *button_close;
QWidget *window_nu;
QPushButton *button_1;
QPushButton *button_2;
QPushButton *button_3;
QPushButton *button_4;
QPushButton *button_5;
QPushButton *button_6;
QPushButton *button_7;
QPushButton *button_8;
QPushButton *button_9;
QPushButton *button_0;
QPushButton *button_letter;
QPushButton *button_blank_2;
QPushButton *button_delete_2;
QPushButton *button_close_2;
void setupUi(QWidget *keyboard_interface);
private slots:
void switchPage();
};
#endif // KEYBOARD_H
keyboard.app
#include "keyboard.h"
#include <QDebug>
void keyboard::setupUi(QWidget *keyboard_interface)
{
keyboard_interface->setGeometry(100,100,850,250);
my_stackedWidget = new QStackedWidget(keyboard_interface);//new一个stackedwidget,翻页用,因为要切换页面的嘛
window_alp = new QWidget(my_stackedWidget);//new一个界面,当字母键盘界面
button_Q = new QPushButton("Q",window_alp);
button_W = new QPushButton("W",window_alp);
button_E = new QPushButton("E",window_alp);
button_R = new QPushButton("R",window_alp);
button_T = new QPushButton("T",window_alp);
button_Y = new QPushButton("Y",window_alp);
button_U = new QPushButton("U",window_alp);
button_I = new QPushButton("I",window_alp);
button_O = new QPushButton("O",window_alp);
button_P = new QPushButton("P",window_alp);
button_A = new QPushButton("A",window_alp);
button_S = new QPushButton("S",window_alp);
button_D = new QPushButton("D",window_alp);
button_F = new QPushButton("F",window_alp);
button_G = new QPushButton("G",window_alp);
button_H = new QPushButton("H",window_alp);
button_J = new QPushButton("J",window_alp);
button_K = new QPushButton("K",window_alp);
button_L = new QPushButton("L",window_alp);
button_Z = new QPushButton("Z",window_alp);
button_X = new QPushButton("X",window_alp);
button_C = new QPushButton("C",window_alp);
button_V = new QPushButton("V",window_alp);
button_B = new QPushButton("B",window_alp);
button_N = new QPushButton("N",window_alp);
button_M = new QPushButton("M",window_alp);
button_nu = new QPushButton("1 2 3",window_alp);
button_delete = new QPushButton("delete",window_alp);
button_blank = new QPushButton(" ",window_alp);
button_close = new QPushButton("close");
button_Q->setFocusPolicy(Qt::NoFocus);//将按钮设置为无焦点,下有解释
button_W->setFocusPolicy(Qt::NoFocus);
button_E->setFocusPolicy(Qt::NoFocus);
button_R->setFocusPolicy(Qt::NoFocus);
button_T->setFocusPolicy(Qt::NoFocus);
button_Y->setFocusPolicy(Qt::NoFocus);
button_U->setFocusPolicy(Qt::NoFocus);
button_I->setFocusPolicy(Qt::NoFocus);
button_O->setFocusPolicy(Qt::NoFocus);
button_P->setFocusPolicy(Qt::NoFocus);
button_A->setFocusPolicy(Qt::NoFocus);
button_S->setFocusPolicy(Qt::NoFocus);
button_D->setFocusPolicy(Qt::NoFocus);
button_F->setFocusPolicy(Qt::NoFocus);
button_G->setFocusPolicy(Qt::NoFocus);
button_H->setFocusPolicy(Qt::NoFocus);
button_J->setFocusPolicy(Qt::NoFocus);
button_K->setFocusPolicy(Qt::NoFocus);
button_L->setFocusPolicy(Qt::NoFocus);
button_Z->setFocusPolicy(Qt::NoFocus);
button_X->setFocusPolicy(Qt::NoFocus);
button_C->setFocusPolicy(Qt::NoFocus);
button_V->setFocusPolicy(Qt::NoFocus);
button_B->setFocusPolicy(Qt::NoFocus);
button_N->setFocusPolicy(Qt::NoFocus);
button_M->setFocusPolicy(Qt::NoFocus);
button_nu->setFocusPolicy(Qt::NoFocus);
button_delete->setFocusPolicy(Qt::NoFocus);
button_blank->setFocusPolicy(Qt::NoFocus);
button_close->setFocusPolicy(Qt::NoFocus);
//为每个按钮设置ID,当button被单击的时候buttonclick函数会返回按钮的id,这里将id设置为每个键值的unicode码。 //敲桌子!这是和示列不一样的地方,直接传id,后面不用再连接mappen,很是方便。
buttonGroup_alp = new QButtonGroup(keyboard_interface);
buttonGroup_alp->addButton(button_A,65);
buttonGroup_alp->addButton(button_B,66);
buttonGroup_alp->addButton(button_C,67);
buttonGroup_alp->addButton(button_D,68);
buttonGroup_alp->addButton(button_E,69);
buttonGroup_alp->addButton(button_F,70);
buttonGroup_alp->addButton(button_G,71);
buttonGroup_alp->addButton(button_H,72);
buttonGroup_alp->addButton(button_I,73);
buttonGroup_alp->addButton(button_J,74);
buttonGroup_alp->addButton(button_K,75);
buttonGroup_alp->addButton(button_L,76);
buttonGroup_alp->addButton(button_M,77);
buttonGroup_alp->addButton(button_N,78);
buttonGroup_alp->addButton(button_O,79);
buttonGroup_alp->addButton(button_P,80);
buttonGroup_alp->addButton(button_Q,81);
buttonGroup_alp->addButton(button_R,82);
buttonGroup_alp->addButton(button_S,83);
buttonGroup_alp->addButton(button_T,84);
buttonGroup_alp->addButton(button_U,85);
buttonGroup_alp->addButton(button_V,86);
buttonGroup_alp->addButton(button_W,87);
buttonGroup_alp->addButton(button_X,88);
buttonGroup_alp->addButton(button_Y,89);
buttonGroup_alp->addButton(button_Z,90);
buttonGroup_alp->addButton(button_delete,16777219);
buttonGroup_alp->addButton(button_blank,32);
//buttonGroup_alp->addbutton(button_close,41);
//buttonGroup_alp->addbutton(button_nu,41);
QGridLayout *layout_alp = new QGridLayout(window_alp);//这里使用格栅布局,说真的,这个布局搞了我一天,很简单的 //应用,看一下说明就知道
layout_alp->addWidget(button_Q, 0, 0,1,2);
layout_alp->addWidget(button_W, 0, 2,1,2);
layout_alp->addWidget(button_E, 0, 4,1,2);
layout_alp->addWidget(button_R, 0, 6,1,2);
layout_alp->addWidget(button_T, 0, 8,1,2);
layout_alp->addWidget(button_Y, 0, 10,1,2);
layout_alp->addWidget(button_U, 0, 12,1,2);
layout_alp->addWidget(button_I, 0, 14,1,2);
layout_alp->addWidget(button_O, 0, 16,1,2);
layout_alp->addWidget(button_P, 0, 18,1,2);
layout_alp->addWidget(button_A, 1, 1,1,2);
layout_alp->addWidget(button_S, 1, 3,1,2);
layout_alp->addWidget(button_D, 1, 5,1,2);
layout_alp->addWidget(button_F, 1, 7,1,2);
layout_alp->addWidget(button_G, 1, 9,1,2);
layout_alp->addWidget(button_H, 1, 11,1,2);
layout_alp->addWidget(button_J, 1, 13,1,2);
layout_alp->addWidget(button_K, 1, 15,1,2);
layout_alp->addWidget(button_L, 1, 17,1,2);
layout_alp->addWidget(button_Z, 3, 3,1,2);
layout_alp->addWidget(button_X, 3, 5,1,2);
layout_alp->addWidget(button_C, 3, 7,1,2);
layout_alp->addWidget(button_V, 3, 9,1,2);
layout_alp->addWidget(button_B, 3, 11,1,2);
layout_alp->addWidget(button_N, 3, 13,1,2);
layout_alp->addWidget(button_M, 3, 15,1,2);
layout_alp->addWidget(button_blank, 4, 4,1,10);
layout_alp->addWidget(button_nu, 4, 0,1,3);
layout_alp->addWidget(button_delete, 4, 15,1,3);
layout_alp->addWidget(button_close, 8, 14,2,2);
window_alp->setLayout(layout_alp);//这里将格栅布局应用到字母界面中,不然你写了也没用哦
my_stackedWidget->addWidget(window_alp);//这里将这个字母键盘界面添加为stackedWidget的一个页面
window_nu = new QWidget(my_stackedWidget);//new出来数字界面,下面都是一样的
button_1 = new QPushButton("1",window_nu);
button_2 = new QPushButton("2",window_nu);
button_3 = new QPushButton("3",window_nu);
button_4 = new QPushButton("4",window_nu);
button_5 = new QPushButton("5",window_nu);
button_6 = new QPushButton("6",window_nu);
button_7 = new QPushButton("7",window_nu);
button_8 = new QPushButton("8",window_nu);
button_9 = new QPushButton("9",window_nu);
button_0 = new QPushButton("0",window_nu);
button_delete_2 = new QPushButton("delete",window_nu);
button_close_2 = new QPushButton("close",window_nu);
button_blank_2 = new QPushButton("",window_nu);
button_letter = new QPushButton("ABC",window_nu);
button_1->setFocusPolicy(Qt::NoFocus);
button_2->setFocusPolicy(Qt::NoFocus);
button_3->setFocusPolicy(Qt::NoFocus);
button_4->setFocusPolicy(Qt::NoFocus);
button_5->setFocusPolicy(Qt::NoFocus);
button_6->setFocusPolicy(Qt::NoFocus);
button_7->setFocusPolicy(Qt::NoFocus);
button_8->setFocusPolicy(Qt::NoFocus);
button_9->setFocusPolicy(Qt::NoFocus);
button_0->setFocusPolicy(Qt::NoFocus);
button_delete_2->setFocusPolicy(Qt::NoFocus);
button_close_2->setFocusPolicy(Qt::NoFocus);
button_blank_2->setFocusPolicy(Qt::NoFocus);
button_letter->setFocusPolicy(Qt::NoFocus);
/*这里将按键设置为无焦点,我的解释是因为键盘事件必须是该按钮所在的widget接受焦点,
*而widget默认nofocus,pushbutton默认StrongFocus,那么就会导致按钮所在的父窗口接收不到焦点
* 就会导致键盘事件无法被触发,而将button设置为nofocus后,父窗口可以接受到焦点,就可以触发键盘事件
* (个人猜测,且本人使用QT 4.8.6 ,如果有专业解释,请告知)*/
buttonGroup_alp->addButton(button_0,48);
buttonGroup_alp->addButton(button_1,49);
buttonGroup_alp->addButton(button_2,50);
buttonGroup_alp->addButton(button_3,51);
buttonGroup_alp->addButton(button_4,52);
buttonGroup_alp->addButton(button_5,53);
buttonGroup_alp->addButton(button_6,54);
buttonGroup_alp->addButton(button_7,55);
buttonGroup_alp->addButton(button_8,56);
buttonGroup_alp->addButton(button_9,57);
buttonGroup_alp->addButton(button_delete_2,16777219);
buttonGroup_alp->addButton(button_blank_2,32);
QGridLayout *layout_nu = new QGridLayout;
layout_nu->addWidget(button_1, 0, 0, 1, 1);
layout_nu->addWidget(button_2, 0, 1, 1, 1);
layout_nu->addWidget(button_3, 0, 2, 1, 1);
layout_nu->addWidget(button_4, 1, 0, 1, 1);
layout_nu->addWidget(button_5, 1, 1, 1, 1);
layout_nu->addWidget(button_6, 1, 2, 1, 1);
layout_nu->addWidget(button_7, 2, 0, 1, 1);
layout_nu->addWidget(button_8, 2, 1, 1, 1);
layout_nu->addWidget(button_9, 2, 2, 1, 1);
layout_nu->addWidget(button_0, 3, 1, 1, 1);
layout_nu->addWidget(button_delete_2, 3, 2, 1, 1);
layout_nu->addWidget(button_letter, 3, 0, 1, 1);
layout_nu->addWidget(button_close_2, 6, 1, 1, 1);
layout_nu->addWidget(button_blank_2, 4, 0, 1, 3);
window_nu->setLayout(layout_nu);
my_stackedWidget->addWidget(window_nu);
connect(button_close,SIGNAL(clicked()),keyboard_interface,SLOT(close()));//将close与父界面的关闭连接起来
connect(button_close_2,SIGNAL(clicked()),keyboard_interface,SLOT(close()));
connect(button_letter,SIGNAL(clicked()),this,SLOT(switchPage()));//这里将翻页的按钮与swithPage函数连接起来,达
connect(button_nu,SIGNAL(clicked()),this,SLOT(switchPage())); //到翻页目的
//keyboard_interface->show();
//QMetaObject::connectSlotsByName(keyboard_interface);
}
//就是执行切换页面的功能呀
void keyboard::switchPage()
{
int nCount = my_stackedWidget->count();
int nIndex = my_stackedWidget->currentIndex();
// 获取下一个需要显示的页面索引
++nIndex;
// 当需要显示的页面索引大于等于总页面时,切换至首页
if (nIndex >= nCount)
nIndex = 0;
my_stackedWidget->setCurrentIndex(nIndex);
}
定义了按键并将其text文本(也就是按钮上显示的值),以及定义他的父窗口
这里界面的架构应该是这样子的
主界面上放一个StackedWidget,然后将两个界面添加为他的子页面,
再在两个界面上放上按钮,用QGridLayout将它们按照自己的意愿排列好
这里我做的很丑,有做的很好看的。。 可否教我一下。。
以上就是界面的全部代码,下面是业务层面的代码
alphabet_keyboard.h #ifndef ALPHABET_KEYBOARD_H
#define ALPHABET_KEYBOARD_H
#include <QtGui>
#include <QtCore>
#include "keyboard.h"
#include "load_qss.h"
class alphabet_keyboard : public QWidget
{
Q_OBJECT
public:
alphabet_keyboard();
QWidget *getFocusedWidget();
keyboard form;
signals:
void characterGenerated(int key);
protected:
bool event(QEvent *e);
private slots:
void saveFocusWidget(QWidget *oldFocus, QWidget *newFocus);
void buttonClicked_alp(int key);
private:
QWidget *lastFocusedWidget;
QSignalMapper signalMapper;
};
#endif // ALPHABET_KEYBOARD_H
alphabet_keyboard.app #include "alphabet_keyboard.h"
alphabet_keyboard::alphabet_keyboard()
: QWidget(0, Qt::Tool | Qt::WindowStaysOnTopHint),
lastFocusedWidget(0)
{
form.setupUi(this);
//光标事件改变,就更新lastFocusedWidget(光标的位置)
//focusChanged是QApplication类的一个函数,主要功能当信号焦点改变时,触发该槽函数,savaFocuWidget函数是更新光标位置
connect(qApp, SIGNAL(focusChanged(QWidget*,QWidget*)),
this, SLOT(saveFocusWidget(QWidget*,QWidget*)));
connect(form.buttonGroup_alp,SIGNAL(buttonClicked(int)),this,SLOT(buttonClicked_alp(int)));
//这里直接将buttonGroup与发送函数绑定到一起,当单击button时,发送按键的id,也就等于发送了键值
}//这是和示例不一样的地方无需绑定mapper,直接将键值的uncidoe码发来,至于为什么发uncidoe码,因为键盘事件需要。。。
bool alphabet_keyboard::event(QEvent *e)
{
switch (e->type())
{
case QEvent::WindowActivate://窗口被激活
if (lastFocusedWidget)//如果窗口被激活,而且与上一次的“请输入”窗口信号一样,(说明弹出的软键盘被关闭)
{
lastFocusedWidget->activateWindow();//弹出软键盘界面
}
break;
default:
break;
}
return QWidget::event(e);
}
void alphabet_keyboard::saveFocusWidget(QWidget * /*oldFocus*/, QWidget *newFocus)
{
if (newFocus != 0 && !this->isAncestorOf(newFocus))
{
lastFocusedWidget = newFocus;
}
}//如果信号有更新(就是你开始打字啦),那么更新光标的位置。
void alphabet_keyboard::buttonClicked_alp(int key)
{
emit characterGenerated(key);
//不经过处理,直接发送出去,
}
QWidget *alphabet_keyboard::getFocusedWidget()
{
return lastFocusedWidget;//这里是返回原本的窗口焦点,不然你可能点击键盘的时候,输入框又没了焦点。。就会也输入不进去
}
begin.h#ifndef BEGIN_H
#define BEGIN_H
#include <QtGui/QInputContext>
#include "alphabet_keyboard.h"
class begin : public QInputContext
{
Q_OBJECT
public:
begin();
~begin();
bool filterEvent(const QEvent* event);
QString identifierName();
QString language();
bool isComposing() const;
void reset();
private slots:
void sendCharacter(int key);
private:
void updatePosition();
private:
alphabet_keyboard *alp;
};
#endif // BEGIN_H
begin.app
#include <QtCore>
#include "begin.h"
#include <QApplication>
#include <QWSServer>
begin::begin()
{
alp = new alphabet_keyboard;
connect(alp, SIGNAL(characterGenerated(int)), SLOT(sendCharacter(int)));
//将信号与槽sendCharacter()函数绑定,信号为pushbutton id。槽函数将信号的值显示出来
}
begin::~begin()
{
delete alp;
}
bool begin::filterEvent(const QEvent* event)
{
if (event->type() == QEvent::RequestSoftwareInputPanel)
{
updatePosition();
alp->show();
return true;
}//这里就是将软键盘弹出来
else if (event->type() == QEvent::CloseSoftwareInputPanel)
{
alp->hide();
return true;
}//这里就是主界面关闭的时候,把弹出的软键盘也给关闭了
return false;
}
QString begin::identifierName()
{
return "begin";
}
//复位
void begin::reset()
{
}
//判断发送事件成功与否
bool begin::isComposing() const
{
return false;
}
//编码方式
QString begin::language()
{
return "en_US";
}
void begin::sendCharacter(int key)
{
QPointer<QWidget> w = alp->getFocusedWidget();
if (!w)
{
return;
}//判定此时 光标是否在主界面
//这里传递的本就是unicode值,不必再转码,示例的做法是传过来一个字符,在这里转码,局限性很大只能一个字符不说
//以后你要做大小写键的时候,更是麻烦,我这种直接加一个判定,然后将发来的键值统一变成小写的就成,是多少自己去查。。
QKeyEvent keyPress(QEvent::KeyPress, key, Qt::NoModifier, QString(key));
//检测按键被按下,提取按键值。
QApplication::sendEvent(w, &keyPress);//w为事件接收者,发送按键值
if (!w)
{
return;
}
QKeyEvent keyRelease(QEvent::KeyRelease, key, Qt::NoModifier, QString());
/*检测 按键被释放,这里一定要用“QEvent::KeyRelease”,不然删除键会执行两次。原因:可能是因为按键被模拟按下了两次,字母的话,可能是自主过滤了,有明确的解答也请告诉我一哈。*/
QApplication::sendEvent(w, &keyRelease);//发送案件释放消息
}
void begin::updatePosition()
{
QWidget *widget = focusWidget();//返回有光标的部件的指针(就是输入框的指针)
if (!widget)//检测,如果没有了,既窗口被关闭,那么直接退出
return;
QRect widgetRect = widget->rect();
QPoint panelPos = QPoint(widgetRect.left() + 10, widgetRect.bottom() + 12);
panelPos = widget->mapToGlobal(panelPos);//保存窗口的位置,不然你拖一下,又跑回去了
alp->move(panelPos);
}
main.cpp
/*
This program is a soft keyboard program,
non-ui designer interface.It is an adaptation of the QT's own example.
本程序为软键盘程序,非UI设计师做出界面。是QT自带示例的改编,点击可弹出软键盘,可进行数字与字母键盘的切换,支持退格以及空格键
转载请注明出处
name:ws4453
email:2942800767@qq.com
time:2018年1月29日15时02分。
*/
#include <QApplication>
#include "loain.h"
#include "begin.h"
#include "keyboard.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//CommonHelper::setStyle("../QSS/white.qss");
begin *ic = new begin;
a.setInputContext(ic);//开始后台的软键盘,随时准备show~
QWidget import;
loain y;
y.setupUi(&import);
import.show();//弹出主界面
return a.exec();
}
就是这么多了,做出的最大改变就是用绑定id的方式,不用那么麻烦的绑定mapped了
|