轻量级Qt键盘-实现篇

2019-07-30 20:08:19 浏览数 (2)

介绍该键盘项目的代码实现。

1.布局

采用垂直布局

代码语言:javascript复制
QHBoxLayout *h1();
QHBoxLayout *h2();
QHBoxLayout *h3();
QHBoxLayout *h4();

QVBoxLayout *layout = new QVBoxLayout();
layout->setSpacing(BUTTON_SPACING_RATIO*height());
layout->addLayout(h1());
layout->addLayout(h2());
layout->addLayout(h3());
layout->addLayout(h4());

mainLayout->addStretch();
mainLayout->addLayout(layout);
mainLayout->addStretch();

2.KeyButton生成

  • 从第一行的键盘布局代码中可以看到,使用for循环创建KeyButton。
代码语言:javascript复制
QHBoxLayout *Keyboard::h1()
{
    QHBoxLayout *h = new QHBoxLayout;
    ...
    for (int i = 0; i < modeListBar1.count(); i  ) {
        KeyButton *button = createButton(modeListBar1.at(i));
        h->addWidget(button);
    }

    ...
}
  • 创建createButton中传递按键的三个状态信息(以第一行为例)。
代码语言:javascript复制
KeyButton *Keyboard::createButton(QList<KeyButton::Mode> modes)
{
    KeyButton *button = new KeyButton(modes, this);
    button->onReponse(this, SLOT(onKeyPressed(const int&, const QString&)));
    button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    return button;
}
  • 每一行内容分别分为小写状态,大写状态,字符状态。
代码语言:javascript复制
const QList<Modes> modeListBar1 = {
    {{Qt::Key_Q, "q"}, {Qt::Key_Q, "Q"}, {Qt::Key_1, "1"}},
    {{Qt::Key_W, "w"}, {Qt::Key_W, "W"}, {Qt::Key_2, "2"}},
    {{Qt::Key_E, "e"}, {Qt::Key_E, "E"}, {Qt::Key_3, "3"}},
    {{Qt::Key_R, "r"}, {Qt::Key_R, "R"}, {Qt::Key_4, "4"}},
    {{Qt::Key_T, "t"}, {Qt::Key_T, "T"}, {Qt::Key_5, "5"}},
    {{Qt::Key_Y, "y"}, {Qt::Key_Y, "Y"}, {Qt::Key_6, "6"}},
    {{Qt::Key_U, "u"}, {Qt::Key_U, "U"}, {Qt::Key_7, "7"}},
    {{Qt::Key_I, "i"}, {Qt::Key_I, "I"}, {Qt::Key_8, "8"}},
    {{Qt::Key_O, "o"}, {Qt::Key_O, "O"}, {Qt::Key_9, "9"}},
    {{Qt::Key_P, "p"}, {Qt::Key_P, "P"}, {Qt::Key_0, "0"}},
};
  • 根据传递的信息默认显示小写状态的内容。
代码语言:javascript复制
KeyButton::KeyButton(const QList<KeyButton::Mode> modes, QWidget *parent) :
    QPushButton(parent)
{
    ...
    if (!modes.isEmpty()) {
        m_preMode = m_mode = m_modes.first();
        setText(m_mode.display);
    }

    connect(this, SIGNAL(pressed()), this, SLOT(onPressed()));
}

3.按键状态切换

  • 键盘存在三种形态,小写状态,大写状态,字符状态。
  • 一个按键存在三种状态,意味按键有三种状态切换,当键盘Keyboard类绑定切换状态的按键,进行响应的操作。
  • 通过按键的状态值来绑定Keyboard的处理信号(switchCapsLock(),switchSpecialChar())。
代码语言:javascript复制
void Keyboard::resizeButton()
{
    foreach (KeyButton *button, findChildren<KeyButton *>()) {
        ...

        switch (button->mode().key) {
          case Qt::Key_CapsLock:
              ...
              connect(button, 
                      SIGNAL(pressed()), 
                      this, 
                      SLOT(switchCapsLock()), 
                      Qt::UniqueConnection);
              break;
          case Qt::Key_Mode_switch:
              ...
              connect(button, 
                      SIGNAL(pressed()), 
                      this, 
                      SLOT(switchSpecialChar()), 
                      Qt::UniqueConnection);
              break;
          default:
              break;
        }
    }

    ...
}
  • 触发切换大写状态,遍历设置每个按键的switchCapsLock()函数。
代码语言:javascript复制
void Keyboard::switchCapsLock()
{
    QList<KeyButton *> buttons = findChildren<KeyButton *>();
    foreach(KeyButton *button, buttons)
        button->switchCapsLock();
}
  • KeyButton的switchCapsLock()函数切换按键显示的内容。
代码语言:javascript复制
void KeyButton::switchCapsLock()
{
    if (m_mode.type == SpecialChar)
        return;

    m_preMode = m_mode;
    m_mode = find(m_mode.type == LowerCase ? UpperCase : LowerCase);
    setText(m_mode.display);
}

4.发送模拟事件到焦点窗口

  • 当创建按键的同时也会绑定AbstractKeyboard的onKeyPressed槽函数。
代码语言:javascript复制
KeyButton *button = new KeyButton(modes, this);
button->onReponse(this, SLOT(onKeyPressed(const int&, const QString&)));
  • 使用QApplication的sendEvent发送按键事件到焦点窗口。
代码语言:javascript复制
void AbstractKeyboard::onKeyPressed(int key, QString value) 
{
    QWidget *receiver = QApplication::focusWidget();
    if (!receiver)
        return;

    QKeyEvent keyPress(QEvent::KeyPress,     key, Qt::NoModifier, value);
    QKeyEvent keyRelease(QEvent::KeyRelease, key, Qt::NoModifier, value);

    QApplication::sendEvent(receiver, &keyPress);
    QApplication::sendEvent(receiver, &keyRelease);
}

0 人点赞