我想制作 8 个按钮(2x4)的网格,并能够使用键盘箭头在这些按钮中移动。如果我只是简单地进行网格布局并将按钮放在相应的坐标中,我会得到看起来应该的布局,但我只能左右移动,当我到达第一行的末尾时,焦点会跳转到第一个按钮在第二行(即向上按钮不会向下移动焦点,而是与按钮 RIGHT 相同)。我注意到焦点(光标)通过按钮移动的方式并没有连接到它们在网格中的位置,而是为了订购我在代码中创建它们。
如何覆盖此行为并允许用户在按钮网格中移动?
我想制作 8 个按钮(2x4)的网格,并能够使用键盘箭头在这些按钮中移动。如果我只是简单地进行网格布局并将按钮放在相应的坐标中,我会得到看起来应该的布局,但我只能左右移动,当我到达第一行的末尾时,焦点会跳转到第一个按钮在第二行(即向上按钮不会向下移动焦点,而是与按钮 RIGHT 相同)。我注意到焦点(光标)通过按钮移动的方式并没有连接到它们在网格中的位置,而是为了订购我在代码中创建它们。
如何覆盖此行为并允许用户在按钮网格中移动?
您可以为每个按钮安装一个事件过滤器并在那里捕获按键。
这是如何实现此类导航的示例:
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);
}