如何禁用 QTableWidget 中的箭头键导航?

How to disable the arrow keys navigation in QTableWidget?

目前,我正在为类 DnD 游戏编写战斗管理器。在战斗中活跃的角色显示在 table 中。为此 table,我使用 QTableWidget
现在我实现了一项功能,允许用户使用 Enter 键在 table 中导航。如果用户到达 table 的末尾并再次点击 Enter,则下一个突出显示的行是第一行,因此下一轮开始。
除了 Enter-键,目前还可以使用 Arrow-键(UpDown)在行中导航。但我不想要这个。仅使用 Enter-Key 即可导航。
因此我的问题是:如何禁用 QTableWidget 中的 Arrow-Keys?到目前为止我尝试过的是:

  1. 实现 keyPressEvent 函数,该函数还处理 Enter 键。如果按下 Arrow 键之一,此功能应该只是 return,但仍然可以使用这些键进行导航(这意味着选择行)。代码在这里:
void TableWidget::keyPressEvent(QKeyEvent *event) {
     // ...
     // Code for the other keys
     // ...
     if(event->key() == Qt::Key_Down || event->key() == Qt::Key_Up) {
          return;
     }
}

如果我使用以下代码添加 ignore 函数,情况也是如此:

if(event->key() == Qt::Key_Down || event->key() == Qt::Key_Up) {
     event->ignore();
     return;
}
  1. 我试图实现一个 eventFilter 函数(例如 here)。在这种情况下,如果按下 UpDown 键,此函数 returns false,但仍然可以导航行。

现在,我别无选择。甚至可以在 QTableWidget 中禁用这些键吗?还是我错过了什么?使用 QTableWidget 是最好的主意吗?感谢您的回答!

编辑 2:现在我已经尝试使用 QTableWidget 的子 class。 class 的代码如下:

MyTableWidget.h

#include <QtWidgets>

class MyTableWidget : public QTableWidget {
    Q_OBJECT

public:
    MyTableWidget(QWidget *parent = nullptr);
    ~MyTableWidget();

private:
    void setupTable();
    void keyPressEvent(QKeyEvent *event);

    QTableWidget *tableWidget;
};

MyTableWidget.cpp

#include "MyTableWidget.h"

MyTableWidget::MyTableWidget(QWidget *parent)
{
    setupTable();
}

void MyTableWidget::setupTable() {
    // Allocate widget and create a column
    tableWidget = new QTableWidget(this);
    tableWidget->setColumnCount(1);
    // Create some rows
    tableWidget->insertRow( tableWidget->rowCount() );
    tableWidget->insertRow( tableWidget->rowCount() );
}

// This function calls some functions for certain keys
void MyTableWidget::keyPressEvent(QKeyEvent *event) {
    if(event->key() == Qt::Key_Down || event->key() == Qt::Key_Up) {
        event->ignore();
        return;
    }
}

MyTableWidget::~MyTableWidget()
{
}

修改后的mainwindow.h现在只有构造函数,代码如下:

myTableWidget = new MyTableWidget(this);
setCentralWidget(myTableWidget);

编辑 1:将提供一个最小示例。这将创建一个具有 1 列和 2 行的小 table。

main.cpp:

#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QtWidgets>

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    void setupTable();
    void keyPressEvent(QKeyEvent *event);

    QTableWidget *tableWidget;
};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    setupTable();
}

void MainWindow::setupTable() {
    // Allocate widget and create a column
    tableWidget = new QTableWidget();
    tableWidget->setColumnCount(1);
    // Set this widget to central
    setCentralWidget(tableWidget);
    // Create some rows
    tableWidget->insertRow( tableWidget->rowCount() );
    tableWidget->insertRow( tableWidget->rowCount() );
}

void MainWindow::keyPressEvent(QKeyEvent *event) {
    if(event->key() == Qt::Key_Down || event->key() == Qt::Key_Up) {
        event->ignore();
        return;
    }
}

MainWindow::~MainWindow()
{
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.5)

project(TablTest LANGUAGES CXX)

set(CMAKE_INCLUDE_CURRENT_DIR ON)

set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets REQUIRED)

add_executable(TableTest
    main.cpp
    mainwindow.cpp
    mainwindow.h
)

target_link_libraries(TableTest PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)

原因

您正在重新实现 QMainWindowkeyPressEvent,而不是 QTableWidget:

void MainWindow::keyPressEvent(QKeyEvent *event) {
    if(event->key() == Qt::Key_Down || event->key() == Qt::Key_Up) {
        event->ignore();
        return;
    }
}

解决方案

  1. 子类 QTableWidget,例如MyTableWidget
  2. 在子类 MyTableWidget 中重新实现 QTableWidget::keyPressEvent
  3. 而不是 tableWidget = new QTableWidget(); 创建子类的对象,MyTableWidget,即 tableWidget = new MyTableWidget();

例子

这是我为您编写的示例,用于演示如何实施建议的解决方案:

MyTableWidget.h

#include <QTableWidget>

class MyTableWidget : public QTableWidget {
    Q_OBJECT
public:
    MyTableWidget(QWidget *parent = nullptr);

protected:
    void keyPressEvent(QKeyEvent *event) override;
};

MyTableWidget.cpp

MyTableWidget::MyTableWidget(QWidget *parent)
{
}

void MyTableWidget::keyPressEvent(QKeyEvent *event) {
    if (event->key() == Qt::Key_Down
        || event->key() == Qt::Key_Up) {
        event->ignore();
        return;
    } else {
        QTableWidget::keyPressEvent(event);
    }
}

MainWindow.cpp

#include "MyTableWidget.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    setupTable();
}

void MainWindow::setupTable() {
    tableWidget = new MyTableWidget();
    tableWidget->setColumnCount(1);
    setCentralWidget(tableWidget);
    // Create some rows
    tableWidget->insertRow( tableWidget->rowCount() );
    tableWidget->insertRow( tableWidget->rowCount() );
}