0

我想制作 8 个按钮(2x4)的网格,并能够使用键盘箭头在这些按钮中移动。如果我只是简单地进行网格布局并将按钮放在相应的坐标中,我会得到看起来应该的布局,但我只能左右移动,当我到达第一行的末尾时,焦点会跳转到第一个按钮在第二行(即向上按钮不会向下移动焦点,而是与按钮 RIGHT 相同)。我注意到焦点(光标)通过按钮移动的方式并没有连接到它们在网格中的位置,而是为了订购我在代码中创建它们。

如何覆盖此行为并允许用户在按钮网格中移动?

4

1 回答 1

0

您可以为每个按钮安装一个事件过滤器并在那里捕获按键。

这是如何实现此类导航的示例:

Widget::Widget(QWidget *parent) :
    QWidget(parent)
{
    grid = new QGridLayout;

    for (int row = 0; row < 4; ++row)
    {
        for (int col = 0; col < 4; ++col)
        {
            QString text = QString("btn %1/%2").arg(row).arg(col);
            QPushButton *btn = new QPushButton(text);
            btn->installEventFilter(this);

            grid->addWidget(btn, row, col);
        }
    }

    setLayout(grid);
}

bool Widget::eventFilter(QObject *obj, QEvent *event)
{
    QPushButton *btn = dynamic_cast<QPushButton*>(obj);
    if (btn != NULL && event->type() == QEvent::KeyPress)
    {
        QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);

        int index = grid->indexOf(btn);
        int row, col, rowSpan, colSpan;
        grid->getItemPosition(index, &row, &col, &rowSpan, &colSpan);

        int nextRow = row;
        int nextCol = col;

        bool keyArrow = true;
        int key = keyEvent->key();
        switch (key)
        {
        case Qt::Key_Up:
        {
            nextRow--;
            if (nextRow < 0)
            {
                nextRow = grid->rowCount() - 1;
            }
            break;
        }
        case Qt::Key_Down:
        {
            nextRow++;
            if (nextRow >= grid->rowCount())
            {
                nextRow = 0;
            }
            break;
        }
        case Qt::Key_Right:
        {
            nextCol++;
            if (nextCol >= grid->columnCount())
            {
                nextCol = 0;
            }
            break;
        }
        case Qt::Key_Left:
        {
            nextCol--;
            if (nextCol < 0)
            {
                nextCol = grid->columnCount() - 1;
            }
            break;
        }
        default:
        {
            keyArrow = false;
        }
        }

        if (keyArrow)
        {
            grid->itemAtPosition(nextRow, nextCol)->widget()->setFocus();
        }

        return true;

    }

    return QWidget::eventFilter(obj, event);
}
于 2013-10-03T08:19:59.220 回答