如何在可编辑的 QTableWidgetItem 中捕捉按键?
How to catch key presses in editable QTableWidgetItem?
现在我可以在函数 eventFilter()
中处理 QTableWidget
中的所有按键(在构造函数中调用 myTable->viewport()->installEventFilter(this);
之后)。
唯一不起作用的地方是编辑时的 editable 单元格(因为它抓住了所有按键)。要修复它,我不能为 table 中的每个项目调用 installEventFilter()
,因为这些项目不是 QObject
(而且我不能使用 connect
来放置我对按键的处理)。
我唯一的解决办法是在这些单元格中放入 QLineEdit
s 并在编辑时使用事件过滤器捕捉按键。但是是否可以仅使用标准项目来解决它? (即只有 QTableWidgetItem
带有标志 Qt::ItemIsEditable
)
我也可以为我的 QTableWidget
打电话 grabKeyboard()
。在这种情况下,我将按下所有按键(即使在用户编辑单元格时),但它会阻止编辑框(即用户无法输入任何内容)。在为 table?
调用 grabKeyboard()
后,是否可以修复损坏的编辑框
由于 QTableWidgetItem 没有可以重载的函数 keyEvent(),因此这是不可能的。
您需要做的是设置一个带有自定义编辑器工厂的委托,该工厂在 keyEvent 过载的情况下生成小部件。
这很容易实现。只需 subclass QStyledItemDelegate
覆盖 createEditor
方法,如下所示:
QWidget *AlterEditorDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const {
QWidget *result = QStyledItemDelegate::createEditor(parent, option, index);
result->installEventFilter(new YourEventFilter(result));
return result;
}
然后为您的 QTableWidget 替换委托。
或者更好的是 subclass 创建代理 class 接受原始 QAbstractItemDelegate
(更多的写作,但更通用,可以与其他修改组成)。
AlterEditorProxyDelegate::AlterEditorProxyDelegate(QAbstractItemDelegate *original, QObject *parent)
: QAbstractItemDelegate(parent)
, original(original)
{}
QWidget *AlterEditorProxyDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const {
QWidget *result = original->createEditor(parent, option, index);
result->installEventFilter(new YourEventFilter(result));
return result;
}
// other methods which invokes respective methods for `original` style.
But is it possible to solve it using only standard items? (i.e. only QTableWidgetItem with a flag Qt::ItemIsEditable)
不是真的。在 Qt4 中 QTableWidget
从单元格编辑器中泄漏 KeyRelease
事件,但利用它会是一个丑陋的 hack。
May be it is possible to fix broken edit boxes after calling of grabKeyboard() for the table?
我曾经尝试这样做,然后将事件发布到 QTableWidget
但 运行 也遇到了麻烦。
正确的做法是创建自己的委托并在 createEditor
函数中安装事件过滤器。你可以这样做:
class FilterDelegate : public QStyledItemDelegate
{
public:
FilterDelegate(QObject *filter, QObject *parent = 0) :
QStyledItemDelegate(parent), filter(filter)
{ }
virtual QWidget *createEditor(QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
QWidget *editor = QStyledItemDelegate::createEditor(parent, option, index);
editor->installEventFilter(filter);
return editor;
}
private:
QObject *filter;
};
然后你的 MainWindow
构造函数看起来像这样:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
setupUi(this);
tableWidget->setItemDelegate(new FilterDelegate(this));
tableWidget->installEventFilter(this);
}
你的事件过滤器:
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if(event->type() == QEvent::KeyPress)
{
// do something
}
return QMainWindow::eventFilter(obj, event);
}
另一种选择:
您可以在 QApplication
对象上安装事件过滤器并捕获所有事件。如果你问我,这有点矫枉过正,但它适用于小型应用程序并且需要最少的代码。
您只需:
qApp->installEventFilter(this);
并且:
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if(event->type() == QEvent::KeyPress)
{
// do something
}
return QMainWindow::eventFilter(obj, event);
}
现在我可以在函数 eventFilter()
中处理 QTableWidget
中的所有按键(在构造函数中调用 myTable->viewport()->installEventFilter(this);
之后)。
唯一不起作用的地方是编辑时的 editable 单元格(因为它抓住了所有按键)。要修复它,我不能为 table 中的每个项目调用 installEventFilter()
,因为这些项目不是 QObject
(而且我不能使用 connect
来放置我对按键的处理)。
我唯一的解决办法是在这些单元格中放入 QLineEdit
s 并在编辑时使用事件过滤器捕捉按键。但是是否可以仅使用标准项目来解决它? (即只有 QTableWidgetItem
带有标志 Qt::ItemIsEditable
)
我也可以为我的 QTableWidget
打电话 grabKeyboard()
。在这种情况下,我将按下所有按键(即使在用户编辑单元格时),但它会阻止编辑框(即用户无法输入任何内容)。在为 table?
grabKeyboard()
后,是否可以修复损坏的编辑框
由于 QTableWidgetItem 没有可以重载的函数 keyEvent(),因此这是不可能的。
您需要做的是设置一个带有自定义编辑器工厂的委托,该工厂在 keyEvent 过载的情况下生成小部件。
这很容易实现。只需 subclass QStyledItemDelegate
覆盖 createEditor
方法,如下所示:
QWidget *AlterEditorDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const {
QWidget *result = QStyledItemDelegate::createEditor(parent, option, index);
result->installEventFilter(new YourEventFilter(result));
return result;
}
然后为您的 QTableWidget 替换委托。
或者更好的是 subclass 创建代理 class 接受原始 QAbstractItemDelegate
(更多的写作,但更通用,可以与其他修改组成)。
AlterEditorProxyDelegate::AlterEditorProxyDelegate(QAbstractItemDelegate *original, QObject *parent)
: QAbstractItemDelegate(parent)
, original(original)
{}
QWidget *AlterEditorProxyDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const {
QWidget *result = original->createEditor(parent, option, index);
result->installEventFilter(new YourEventFilter(result));
return result;
}
// other methods which invokes respective methods for `original` style.
But is it possible to solve it using only standard items? (i.e. only QTableWidgetItem with a flag Qt::ItemIsEditable)
不是真的。在 Qt4 中 QTableWidget
从单元格编辑器中泄漏 KeyRelease
事件,但利用它会是一个丑陋的 hack。
May be it is possible to fix broken edit boxes after calling of grabKeyboard() for the table?
我曾经尝试这样做,然后将事件发布到 QTableWidget
但 运行 也遇到了麻烦。
正确的做法是创建自己的委托并在 createEditor
函数中安装事件过滤器。你可以这样做:
class FilterDelegate : public QStyledItemDelegate
{
public:
FilterDelegate(QObject *filter, QObject *parent = 0) :
QStyledItemDelegate(parent), filter(filter)
{ }
virtual QWidget *createEditor(QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
QWidget *editor = QStyledItemDelegate::createEditor(parent, option, index);
editor->installEventFilter(filter);
return editor;
}
private:
QObject *filter;
};
然后你的 MainWindow
构造函数看起来像这样:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
setupUi(this);
tableWidget->setItemDelegate(new FilterDelegate(this));
tableWidget->installEventFilter(this);
}
你的事件过滤器:
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if(event->type() == QEvent::KeyPress)
{
// do something
}
return QMainWindow::eventFilter(obj, event);
}
另一种选择:
您可以在 QApplication
对象上安装事件过滤器并捕获所有事件。如果你问我,这有点矫枉过正,但它适用于小型应用程序并且需要最少的代码。
您只需:
qApp->installEventFilter(this);
并且:
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if(event->type() == QEvent::KeyPress)
{
// do something
}
return QMainWindow::eventFilter(obj, event);
}