【问题标题】:How to catch key presses in editable QTableWidgetItem?如何在可编辑的 QTableWidgetItem 中捕捉按键?
【发布时间】:2016-08-02 20:00:47
【问题描述】:

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

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

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

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

【问题讨论】:

  • 你能否实现另一个类,继承QTableWidgetItem,以便拥有QTableWidgetItem的所有功能和你自己的功能来获得你想要的行为?
  • 是的,我可以实现另一个类,但我不明白在这种情况下如何覆盖按键处理。
  • “因为它会抓取所有按键”。不过,您确实获得了关键版本。想知道是什么在抓人。也许有充分的理由?
  • @S.Pinkus 梦想是默默地捕捉按键(即不破坏可编辑单元中的现有进程)。而关于grabKeyboard() 的那些话只是为了解释为什么我希望可以解决这个问题。

标签: c++ qt qtablewidget qtablewidgetitem


【解决方案1】:

这很容易实现。只需继承 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. 

【讨论】:

    【解决方案2】:

    由于 QTableWidgetItem 没有函数 keyEvent() 可以重载这是不可能的。

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

    【讨论】:

    • 感谢您的回答!我不完全确定没有更简单的解决方案。例如,我可以为我的QTableWidget 拨打grabKeyboard()。之后,我将按下所有按键(即使在用户编辑单元格时),但该编辑框也不会按预期工作。
    【解决方案3】:

    但是是否可以仅使用标准项目来解决它? (即只有带有标志 Qt::ItemIsEditable 的 QTableWidgetItem)

    不是真的。在 Qt4 中,QTableWidget 会从单元格编辑器中泄漏 KeyRelease 事件,但利用它会是一个丑陋的 hack。

    是否可以在为表格调用 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);
    }
    

    【讨论】:

    • 谢谢。据我了解,tableWidget->installEventFilter(this); 是不必要的。你同意吗?
    • @Ilya,如果您只想从单元格编辑器小部件中捕获新闻,那么是的,您是对的。
    • 据我了解,我们需要执行tableWidget->viewport()->installEventFilter(this); 来捕获此表中的任何其他按键(不是tableWidget->installEventFilter(this);
    • 当我在tableWidget 上安装它时,它对我有用。您可以尝试两种方法,看看哪一种有效。
    【解决方案4】:

    另一种选择:

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

    你所要做的就是:

    qApp->installEventFilter(this);
    

    还有:

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

    【讨论】:

      猜你喜欢
      • 2012-09-21
      • 1970-01-01
      • 2011-01-16
      • 1970-01-01
      • 1970-01-01
      • 2011-03-03
      • 1970-01-01
      • 2014-01-01
      • 1970-01-01
      相关资源
      最近更新 更多