如何在可编辑的QTableWidgetItem中捕获按键?

时间:2016-04-12 09:37:47

标签: c++ qt qtablewidget qtablewidgetitem

现在,我可以在函数QTableWidget中处理eventFilter()中的所有按键操作(在构造函数中调用myTable->viewport()->installEventFilter(this);之后)。

唯一不起作用的地方是编辑时的可编辑单元格(因为它会抓取所有按键)。要解决此问题,我无法为表格中的每个项目调用installEventFilter(),因为这些项目不是QObject s(而且我也无法使用connect来处理我的处理按键)。

我唯一的解决方案是将QLineEdit放在这些单元格中,并使用事件过滤器在编辑时捕获按键。但是,仅使用标准物品可以解决它吗? (即仅QTableWidgetItem带有标记Qt::ItemIsEditable

我也可以为grabKeyboard()致电QTableWidget。在这种情况下,我将按下所有按键(即使在用户编辑单元格时),但它会阻止编辑框(即用户无法输入任何内容)。可能是在为表格调用grabKeyboard()后修复损坏的编辑框?

4 个答案:

答案 0 :(得分:2)

这很容易实现。只是子类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的委托。

甚至更好的是继承创建代理类,它接受原始的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. 

答案 1 :(得分:1)

由于QTableWidgetItem没有可以重载的函数keyEvent(),因此无法实现。

您需要做的是使用自定义编辑器工厂设置一个委托,该工厂生成小部件,其中keyEvent被重载。

答案 2 :(得分:1)

  

但是仅使用标准物品可以解决它吗? (即只有带有标志Qt :: ItemIsEditable的QTableWidgetItem)

不是真的。在Qt4中,QTableWidget泄漏了来自单元格编辑器的KeyRelease个事件,但利用这个将是一个丑陋的黑客攻击。

  

可能在调用表的grabKeyboard()之后修复损坏的编辑框?

我曾尝试过这样做,然后将事件发布到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);
}

答案 3 :(得分:1)

另一个替身:

您可以在QApplication对象上安装事件过滤器并捕获所有事件。如果你问我这有点矫枉过正,但它适用于一个小应用程序并且只需要很少的代码。

您所要做的就是:

qApp->installEventFilter(this);

bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
    if(event->type() == QEvent::KeyPress)
    {
        // do something
    }
    return QMainWindow::eventFilter(obj, event);
}