我创建了一个自定义项目委托(delegate),该委托(delegate)使用户可以编辑文件路径列表:

我已经通过自定义类DirEdit实现了这一点。现在,提交选定的路径,并在用户按下Enter键时关闭编辑器,但是我想补充两种情况,即在用户不必按下Enter键时应关闭编辑器:

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

  • 我一直在尝试使用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();
    }
    

    最佳答案

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

    关于c++ - 如何关闭由自定义QItemDelegate::createEditor()创建的编辑器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30752007/

    10-16 17:38