如何禁用 QTableWidget 中的箭头键导航?
How to disable the arrow keys navigation in QTableWidget?
目前,我正在为类 DnD 游戏编写战斗管理器。在战斗中活跃的角色显示在 table 中。为此 table,我使用 QTableWidget
。
现在我实现了一项功能,允许用户使用 Enter
键在 table 中导航。如果用户到达 table 的末尾并再次点击 Enter
,则下一个突出显示的行是第一行,因此下一轮开始。
除了 Enter
-键,目前还可以使用 Arrow
-键(Up
和 Down
)在行中导航。但我不想要这个。仅使用 Enter
-Key 即可导航。
因此我的问题是:如何禁用 QTableWidget
中的 Arrow
-Keys?到目前为止我尝试过的是:
- 实现
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;
}
- 我试图实现一个
eventFilter
函数(例如 here)。在这种情况下,如果按下 Up
或 Down
键,此函数 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)
原因
您正在重新实现 QMainWindow
的 keyPressEvent
,而不是 QTableWidget
:
void MainWindow::keyPressEvent(QKeyEvent *event) {
if(event->key() == Qt::Key_Down || event->key() == Qt::Key_Up) {
event->ignore();
return;
}
}
解决方案
- 子类
QTableWidget
,例如MyTableWidget
- 在子类
MyTableWidget
中重新实现 QTableWidget::keyPressEvent
- 而不是
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() );
}
目前,我正在为类 DnD 游戏编写战斗管理器。在战斗中活跃的角色显示在 table 中。为此 table,我使用 QTableWidget
。
现在我实现了一项功能,允许用户使用 Enter
键在 table 中导航。如果用户到达 table 的末尾并再次点击 Enter
,则下一个突出显示的行是第一行,因此下一轮开始。
除了 Enter
-键,目前还可以使用 Arrow
-键(Up
和 Down
)在行中导航。但我不想要这个。仅使用 Enter
-Key 即可导航。
因此我的问题是:如何禁用 QTableWidget
中的 Arrow
-Keys?到目前为止我尝试过的是:
- 实现
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;
}
- 我试图实现一个
eventFilter
函数(例如 here)。在这种情况下,如果按下Up
或Down
键,此函数 returnsfalse
,但仍然可以导航行。
现在,我别无选择。甚至可以在 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)
原因
您正在重新实现 QMainWindow
的 keyPressEvent
,而不是 QTableWidget
:
void MainWindow::keyPressEvent(QKeyEvent *event) {
if(event->key() == Qt::Key_Down || event->key() == Qt::Key_Up) {
event->ignore();
return;
}
}
解决方案
- 子类
QTableWidget
,例如MyTableWidget
- 在子类
MyTableWidget
中重新实现QTableWidget::keyPressEvent
- 而不是
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() );
}