如何关闭由自定义QItemDelegate :: createEditor()

时间:2015-06-10 09:11:43

标签: c++ qt qitemdelegate qabstractitemview

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

screenshot

我通过自定义类DirEdit实现了这一目标。现在,当用户按下回车键时,提交所选路径并关闭编辑器,但我想添加两种情况,即编辑器应关闭而用户不必按Enter键:

  1. 当用户通过激活组合框条目(通过单击或按返回)选择文件时
  2. 当用户通过单击"省略号"选择文件时工具按钮。
  3. 我用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();
    }
    

2 个答案:

答案 0 :(得分:0)

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事件,但在这种情况下不起作用

答案 1 :(得分:0)

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

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