QT软键盘制作(非UI设计师界面)

论坛 期权论坛 脚本     
匿名网站用户   2020-12-21 09:08   20   0

刚接触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了




分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:1136255
帖子:227251
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP