【问题标题】:How to close an editor created by a custom QItemDelegate::createEditor()如何关闭由自定义 QItemDelegate::createEditor() 创建的编辑器
【发布时间】:2015-06-10 09:11:42
【问题描述】:

我创建了一个自定义项目委托,它允许用户编辑文件路径列表:

我通过自定义类 DirEdit 实现了这一点。现在选择的路径被提交并且当用户按下回车时编辑器被关闭,但是我想添加两种情况,编辑器应该在用户不必按下回车的情况下关闭:

  1. 当用户通过激活组合框条目(通过单击或按回车键)选择文件时
  2. 当用户通过单击“省略号”工具按钮选择文件时。

我一直在尝试使用 clearFocus() 和其他方法,但似乎没有任何效果。下面是一个完整的例子:

#include <QtWidgets>

class DirEdit : public QWidget
{
    QLineEdit* lineEdit=nullptr;
public:
    DirEdit(QWidget* parent=nullptr)
        : QWidget(parent)
    {
        new QHBoxLayout(this);
        layout()->setMargin(0);
        layout()->addWidget(lineEdit=new QLineEdit(this));

        QCompleter *completer = new QCompleter(this);

        auto model = new QDirModel(completer);
        model->setFilter(QDir::AllDirs|QDir::NoDotAndDotDot);
        completer->setModel(model);

        lineEdit->setCompleter(completer);
        connect(completer, static_cast<void (QCompleter::*)(const QString&)>(&QCompleter::activated), [this](const QString& text)
            {
// >>>>>>>>>>>>>>>>>>>>>>> TODO: Make the editor close here <<<<<<<<<<<<<<<<<<<<<<<<<<<<
            });

        QToolButton* dotDotDot;
        layout()->addWidget(dotDotDot=new QToolButton(this));
        dotDotDot->setText("...");
        connect(dotDotDot, &QToolButton::clicked, this, [this]()
            {
                QString dir = QFileDialog::getExistingDirectory(window(), "Select Directory", lineEdit->text());
                if(dir!="")
                {
                    lineEdit->setText(dir);
// >>>>>>>>>>>>>>>>>>>>>>> TODO: Make the editor close here <<<<<<<<<<<<<<<<<<<<<<<<<<<<
                }
            });
        setFocusProxy(lineEdit);
    }
    void setPath(const QString& path)
    {
        lineEdit->setText(path);
    }
    QString path()const
    {
        return lineEdit->text();
    }
};

class MyDelegate : public QItemDelegate
{
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &index) const
    {
        return new DirEdit(parent);
    }

    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem& option, const QModelIndex &)const
    {
        editor->setGeometry(option.rect);
    }

    void setEditorData(QWidget *editor, const QModelIndex &index) const
    {
        QVariant value = index.model()->data(index, Qt::DisplayRole);

        if (DirEdit *dirEdit = dynamic_cast<DirEdit *>(editor))
            dirEdit->setPath(value.toString());
    }

    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
    {
        if (DirEdit *dirEdit = dynamic_cast<DirEdit *>(editor))
            model->setData(index, dirEdit->path());
    }
};

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
    QListWidget listWidget;

    listWidget.setItemDelegate(new MyDelegate);

    listWidget.addItem(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation));
    listWidget.addItem(QStandardPaths::writableLocation(QStandardPaths::MusicLocation));
    listWidget.addItem(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation));
    listWidget.addItem(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation));

    for (int i = 0; i<listWidget.count(); i++)
        listWidget.item(i)->setFlags(listWidget.item(0)->flags()|Qt::ItemIsEditable);

    listWidget.show();
    return app.exec();
}

【问题讨论】:

  • 也许QAbstractItemView::closePersistentEditor() 可以帮忙?
  • @vahancho 我不这么认为,因为它不是持久编辑器(由 QAbstractItemView::openPersistentEditor() 创建)
  • 嗯,我想你需要关闭QCompleter::popup()?打电话给completer-&gt;popup()-&gt;close()怎么样?
  • 当我点击一个项目或按下回车键时弹出窗口关闭。问题是行编辑保持焦点并保持打开状态。

标签: c++ qt qitemdelegate qabstractitemview


【解决方案1】:

TL;DR

将 TODO 替换为

QApplication::postEvent(this, new QKeyEvent(QKeyEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier));

动机:

我在这里找到了答案的关键:Why pressing of "Tab" key emits only QEvent::ShortcutOverride event?

有一个事件过滤器在寻找某些事件,所以我只需要触发其中一个:

// Edited for brevity.
bool QItemDelegate::eventFilter(QObject *object, QEvent *event)
{
    QWidget *editor = qobject_cast<QWidget*>(object);

    if (event->type() == QEvent::KeyPress) {
        switch (static_cast<QKeyEvent *>(event)->key()) {
        case Qt::Key_Enter:
        case Qt::Key_Return:
            QMetaObject::invokeMethod(this, "_q_commitDataAndCloseEditor",
                                      Qt::QueuedConnection, Q_ARG(QWidget*, editor));
            return false;
    }
}

我尝试先发布一个像 @fasked 在其他帖子中建议的 FocusOut 事件,但在这种情况下不起作用

【讨论】:

    【解决方案2】:

    我通过setCurrentIndex(QModelIndex())解决了类似的问题。

    QTreeView *tree;
    // ...
    // ...
    QObject::connect(outsideButton, &QPushButton::clicked, [tree](){
        tree->setCurrentIndex(QModelIndex());
    });
    

    【讨论】:

      猜你喜欢
      • 2022-01-15
      • 2017-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-28
      • 2013-06-10
      • 2014-05-21
      相关资源
      最近更新 更多