虚拟键盘——设计思路及event事件处理方法

        前面谈及了虚拟键盘的设计方法,其设计内容及思路如下:

(1)    新建对话框类,在该对话框中有文本框若干、虚拟输入键盘一个。

虚拟键盘——设计思路及event事件处理方法_第1张图片

(2)    在对话框类中定义虚拟键盘子对象、用于文本输入响应的槽函数;定义事件过滤器,安装在对话框上,当对话框接收到event事件时,如果需要则接收(例如用于文本框上下切换的两个按键),如果不需要则转发给键盘(例如用于键盘左右移动的两个按键,用于选择字符的确认键),如此进行事件分发。

虚拟键盘——设计思路及event事件处理方法_第2张图片

(3)    当用户按下确认键选择字符时,会发送一个clicked信号,此信号经过signalMapper转发,将按键上的文本信息传送到(2)中所述的槽函数中,由此设定文本框的输入值。

       上述设计使用了 QSignalMapper类,这个类还是很好用的,但是存在一个缺点:按键类使用在新的对话框时,每次都要在新的对话框类中,定义一个 eventFilter,重写 keyPressEvent,很麻烦。

       下面的改进办法就很好用,该设计方法将按键统一放在VirtualKeyboard类中处理,且在VirtualKeyboard类中定义eventFilter,这样模块复用时就更加简单。

虚拟键盘——设计思路及event事件处理方法_第3张图片

bool VirtualKeyboard::eventFilter(QObject *obj, QEvent *event)
{
    int forwardKey = 0;
    Qt::KeyboardModifier modifier = Qt::NoModifier; // 用于焦点切换时,定义是否按下了shift键
    QString text; 

    if(event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease)
    {
        QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
        switch (keyEvent->key())
        {
            case GENERAL_PURPOSE_KNOB:
                QApplication::sendEvent(this, event); // 旋动旋钮,则直接交给VirtualKeyboard的keypressEvent来处理
                return true;
            case GENERAL_PURPOSE_BUTTON:
                forwardKey = button.at(currentChoice)->text().at(0).toLatin1();
                text = button.at(currentChoice)->text();  // 取按键text,用于sendEvent
                break;
            case KEY_UP:
                forwardKey = Qt::Key_Tab;
                break;
            case KEY_DOWN:
                forwardKey = Qt::Key_Tab;
                modifier = Qt::ShiftModifier;  // shift键按下
                break;
            case KEY_LEFT_FORWARD:
                forwardKey = Qt::Key_Left;
                break;
            case KEY_RIGHT_FORWARD:
                forwardKey = Qt::Key_Right;
                break;
            case KEY_BACKSPACE:
                forwardKey = Qt::Key_Backspace;
                break;
            default:
                break;
        }
    }

    if (forwardKey != 0)
    {
        QWidget *widget = QApplication::focusWidget();
        if (widget)
        {
            QKeyEvent e(event->type(), forwardKey, modifier, text); // 定义keyevent事件
            QApplication::sendEvent(widget, &e);   // 发送给有焦点的QLineEdit,QLineEdit会自行处理这些事件
            return true;
        }
    }

    return QObject::eventFilter(obj, event);
}
       这样用不得不说非常妙,因为QLineEdit可以自行处理上述的按键事件,就用不着再写槽函数了,且焦点可以自由的上下切换,对话框类也无需定义keypressEvent和eventFilter,该类的复用就非常方便。




你可能感兴趣的:(虚拟键盘——设计思路及event事件处理方法)