QT 软键盘实现

 

在树莓派下面运行了一下我的写的代码,发现在输入框中并不能使用键盘输入内容,什么都不能输入,只能自己实现软键盘。

 

QT 的事件处理:

  1. Qt 程序需要在main()函数创建一个QCoreApplication对象
  2. 然后调用它的exec()函数。这个函数就是开始 Qt 的事件循环。
  3. 在执行exec()函数之后,程序将进入事件循环来监听应用程序的事件。
  • 当事件发生时:
  1. Qt 将创建一个事件对象。Qt 中所有事件类都继承于QEvent
  2. 在事件对象创建完毕后,Qt 将这个事件对象传递给QObject的event()函数。event()函数并不直接处理事件,而是将这些事件对象按照它们不同的类型,分发给不同的事件处理器(event handler)。

如上所述,event()函数主要用于事件的分发。所以,如果你希望在事件分发之前做一些操作,就可以重写这个event()函数了。

参考链接

  • 鼠标事件

使用的时候,加头文件:#include

    void mousePressEvent(QMouseEvent *event);        //单击
    void mouseReleaseEvent(QMouseEvent *event);      //释放
    void mouseDoubleClickEvent(QMouseEvent *event);  //双击
    void mouseMoveEvent(QMouseEvent *event);         //移动
    void wheelEvent(QWheelEvent *event);             //滑轮

 

// 鼠标按下事件
void Widget::mousePressEvent(QMouseEvent *event)
{
    // 如果是鼠标左键按下   改变指针形状,并且存储当前指针位置与窗口位置的差值。
    if(event->button() == Qt::LeftButton){
        ···
    }
    // 如果是鼠标右键按下
    else if(event->button() == Qt::RightButton){
       ···
    }
}
// 鼠标移动事件       默认情况下,触发事件需要点击一下,才能触发。可设置为自动触发:setMouseTracking(true); 


void Widget::mouseMoveEvent(QMouseEvent *event)
{
    // 这里必须使用buttons()
    if(event->buttons() & Qt::LeftButton){  //进行的按位与
       ···
    }
}


// 鼠标释放事件
void Widget::mouseReleaseEvent(QMouseEvent *event)
{
   ···
}


// 鼠标双击事件
void Widget::mouseDoubleClickEvent(QMouseEvent *event)
{
    // 如果是鼠标左键按下
    if(event->button() == Qt::LeftButton){
      
        ···
    }
}


// 滚轮事件
void Widget::wheelEvent(QWheelEvent *event)
{
    // 当滚轮远离使用者时
    if(event->delta() > 0){
        ···
    }else{//当滚轮向使用者方向旋转时
        ···
    }
}
  • 键盘事件:

 

void keyPressEvent(QKeyEvent *event);
void keyReleaseEvent(QKeyEvent *event);
键盘事件使用时,加头文件

#include 

// 键盘按下事件
void Widget::keyPressEvent(QKeyEvent *event)
{
    // 是否按下Ctrl键      特殊按键
    if(event->modifiers() == Qt::ControlModifier){
        // 是否按下M键    普通按键  类似
        if(event->key() == Qt::Key_M)
            ···
    }
    else QWidget::keyPressEvent(event);   //保存默认事件

    //如果是处理两个普通按键,得避免自动重复,释放中也要处理
    if(event->key() == Qt::Key_Up){
        // 按键重复时不做处理
        if(event->isAutoRepeat()) return;
        // 标记向上方向键已经按下
        keyUp = true;
    }else if(event->key() == Qt::Key_Left){
        if(event->isAutoRepeat()) return;
        keyLeft = true;
    }

}


// 按键释放事件
void Widget::keyReleaseEvent(QKeyEvent *event)
{
    ···
	
    //如果是处理两个普通按键,得避免自动重复
   if(event->key() == Qt::Key_Up){
        if(event->isAutoRepeat()) return;
 
 	···       
       
    }
    else if(event->key() == Qt::Key_Left){
        if(event->isAutoRepeat()) return;
       ···
      
   }

}
  • event filter是什么?

EventFilter即所谓事件过滤器,在Qt中是一个比较重要的概念,它的功能是把所有事件在到达watchee(被监控者)之前全部传递给另一个watcher(监控者),由watcher先行处理并决定是否继续传递该事件,如果继续传递,则事件将回传给watchee来处理。 

event filter的常见应用场合
用来处理热键 -- 比如一个界面上可以由用户热键来触发的多个按钮。 由于只有得到焦点的控件才能获得键盘的事件, 如果不用event filter就需要给每个button都加上键盘事件的处理,还要在button里去访问兄弟button的指针,逻辑非常混乱。如果由主窗体做各个按钮的eventFilter,则只需要在主窗体里去处理键盘事件就好,而且主窗体可以很容易的访问到各个button的指针,很方便。

用来代替派生和重写虚函数 -- Qt里的键盘鼠标事件基本上都是以虚函数的方式来处理,要想重写虚函数则必须派生一个子类,这样的话如果只是一个简单的事件处理也去派生子类代价未免大了些,这时候就值得用用eventFilter。比如我的MDI界面想在每个子窗体关闭的时候做一些统一的操作,一般的做法是处理子窗体的closeEvent。但显然给每个子窗体都去派生个子类太不现实,最好的方法是把mainwindow作为子窗体的eventFilter去处理CloseEvent事件。

如何使用event filter处理事件?

event filter的使用有点曲折,有两个步骤要做。

  • 1 调用watchee的installEventFilter以watcher指针为参数

watchee->installEventFilter(watcher);
  • 2 在watcher的类中实现bool eventFilter(QObject*, QEvent*) 这个虚函数,在此函数中处理事件。

 class KeyPressEater : public QObject
{
Q_OBJECT
...
 
protected:
bool eventFilter(QObject *obj, QEvent *event);
};
 
bool KeyPressEater::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast(event);
qDebug("Ate key press %d", keyEvent->key());
return true;
} else {
// standard event processing
return QObject::eventFilter(obj, event);
}
}

其中几点需要注意的地方:
- watchee和watcher必须都是从QObject派生的子类实例
- watcher的类必须是一个自定义的子类(因为需要重新实现虚函数, 用现成的类是不行的。)
watcher类的eventFilter函数返回true时表示该事件处理完毕,不再继续传递;返回false表示该事件仍然传递
eventFilter的实现的最后必须调用watcher基类的eventFilter函数以传递事件。如果不调的话watcher的所有事件都将丢失。
- 注意eventFilter的声明必须和文档里的一模一样, 写的时候注意返回值、大小写和参数类型

在Qt中还有一些应用程序级别的eventFilter函数,是和平台相关的,如x11EventFilter可以截获程序得到的所有X事件。相应的Windows平台下用winEventFilter… 大家不要被函数的名字给误导了,这些函数并不是全局级别的,充其量只能拿到应用程序内部的事件,想做系统级别的事件过滤还是差着档次…

点击LineEditdit弹出软键盘的方法

  • 在.h文件加入:

public:
      KeyBoardDialog v_keyB;//键盘对话框
 
private slots:
    bool eventFilter(QObject *,QEvent *);    //注意这里软件盘相关
  • 在.cpp文件构造函数中加入:

    ui->weightMaxlineEdit->installEventFilter(this);
  • 在.cpp中添加eventFilter函数的实现代码

bool Widget::eventFilter(QObject *watched, QEvent *event)
{
    if (watched==ui->weightMaxlineEdit)         //首先判断控件(这里指 lineEdit1)
    {
        if (event->type()==QEvent::FocusIn)     //然后再判断控件的具体事件 (这里指获得焦点事件)
        {
            QString ret = v_keyB.returnValue();//
            ui->weightMaxlineEdit->setText(ret);
             //QMessageBox::information(this,tr("消息"),"复制完成");
             ui->weightMaxlineEdit->clearFocus();//防止weightMaxlineEdit重新获得焦点再一次激发时间
        }
    }
 
     return QWidget::eventFilter(watched,event);     // 最后将事件交给上层对话框
}

软键盘的设计:

思路:

1 重写输入控件的mousePressEvent方法,在mousePressEvent方法中发射信号,并且将字符串发送出去,主窗口接收到信号后,打开相应的槽函数,在槽函数中打开软键盘界面,并且将信号发送过来的字符串显示在软键盘界面中。

2 打开软键盘后,可以在界面上可以选择中英文输入法,如果是英文输入法,则直接显示出来,如果是中文输入法,则根据输入的英文字符来匹配字库中的字段,然后显示出来。

3 点击软键盘返回按键,则发送信号,将字符串(英文或中文)发送给主窗口的输入组件并显示。

  • 分析:关键点。

1、两个UI之间如何传数。2、软键盘应运行在何种状态能达到想要的效果。3、软键盘按键的槽如何写最简便的取数。

解决:1、两个UI传数可以用函数返回值的方式,这个可以参看我的另一篇博文。具体的是在软键盘的程序中写一个returnvalue();返回输入完毕后输入的数,在主窗口函数中调用该函数,得到返回值。

 

public:

QString returnValue();//keyboard.h声明
QString KeyBoard::returnValue()
{
exec();
return inputBuf;
}//keyboard.cpp返回输入值

 

KeyBoard v_keyB(this);

QString ret = v_keyB.returnValue();//mainwindow.cpp调用该函数,取得返回值
  • 2、exec();

消息循环调用,它是软键盘成为模态对话框,模态对话框(Modal Dialogue Box,又叫做模式对话框),是指在用户想要对对话框以外的应用程序进行操作时,必须首先对该对话框进行响应。如单击【确定】或【取消】按钮等将该对话框关闭。

exec()程序进入消息循环,等待可能输入进行响应。这里main()把控制权转交给Qt,Qt完成事件处理工作,当应用程序退出的时候exec()的值就会返回。在exec()中,Qt接受并处理用户和系统的事件并且把它们传递给适当的窗口部件。done/reject/accept可以结束它。

QString KeyBoard::returnValue()
{
    exec();//消息循环
    return inputBuf;
}//keyboard.cpp
void KeyBoard::on_pushButton_yes_clicked()

{
   KeyBoard v_keyB(this);
   inputBuf = StrBuf;
   if(inputBuf==""){inputBuf = "no_value";}
   int length = inputBuf.size();
   if(inputBuf[length-1]=='.')
   {
       inputBuf.remove(length-1,1);
   }
   done(2);
}//keyboard.cpp按确认时则结束exec()
  • 3、利用字符串拼接方式是最简便的。

void KeyBoard::on_pushButton_1_clicked()

{
    m_ui->lineEdit_keyB->setText("");//清屏
    StrBuf += QString::number(1);//把字符1接到BUFFER中
    if(StrBuf[0] == '0'&&zero_flag==1&&StrBuf[1] != '.')
    {
        StrBuf.remove(0,1);
      }//判断0是否为首位,是首位且后无小数点则去掉
     m_ui->lineEdit_keyB->setText(StrBuf);

}//显示

QLineEdit信号总结:

QLineEdit一共有6个信号函数,并不多,很好理解。

·void cursorPositionChanged( intold, intnew )

当鼠标移动时发出此信号,old为先前的位置,new为新位置。

· void editingFinished()

当 按返回或者回车键时,或者行编辑失去焦点时,发出此信号。

注意:当QLineEdit设置了validator() orinputMask()函数,验证器or输入掩码,并按了返回或回车键,信号只有在 输入内容符合输入掩码 或验证器返回 QValidator::Acceptable时 发出。

· void returnPressed()

当 返回或回车键按下时发出此信号,

注意:当QLineEdit设置了validator() orinputMask()函数,验证器or输入掩码,并按了返回或回车键,信号只有在 输入内容符合输入掩码 或验证器返回 QValidator::Acceptable时 发出。

· void selectionChanged()

当选文本改变时,发出此信号。

· void textChanged( const QString &text )

当QLineEdit中的文本改变时,发出此信号,text是新的文本。当通过程序改变文本时,也会触发此信号,例如,setText()

· void textEdited( const QString &text )

当QLineEdit中的文本改变时,发出此信号,text是新的文本。当通过程序改变文本时,不会触发此信号。
原文:https://blog.csdn.net/u013687602/article/details/19968185 
 

你可能感兴趣的:(QT)