Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何关闭由自定义QItemDelegate::createEditor()创建的编辑器_C++_Qt_Qitemdelegate_Qabstractitemview - Fatal编程技术网

C++ 如何关闭由自定义QItemDelegate::createEditor()创建的编辑器

C++ 如何关闭由自定义QItemDelegate::createEditor()创建的编辑器,c++,qt,qitemdelegate,qabstractitemview,C++,Qt,Qitemdelegate,Qabstractitemview,我创建了一个自定义项委托,允许用户编辑文件路径列表: 我通过自定义类DirEdit实现了这一点。现在,选定的路径已提交,当用户按enter键时,编辑器将关闭,但我想添加两种情况,在这种情况下,用户无需按enter键即可关闭编辑器: 当用户通过激活组合框条目(通过单击或按return键)选择文件时 当用户通过单击“省略号”工具按钮选择文件时 我一直在使用clearFocus()和其他方法进行演示,但似乎没有任何效果。下面是一个完整的示例: #include <QtWidgets>

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

我通过自定义类DirEdit实现了这一点。现在,选定的路径已提交,当用户按enter键时,编辑器将关闭,但我想添加两种情况,在这种情况下,用户无需按enter键即可关闭编辑器:

  • 当用户通过激活组合框条目(通过单击或按return键)选择文件时
  • 当用户通过单击“省略号”工具按钮选择文件时
  • 我一直在使用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();
    }
    
    #包括
    类DirEdit:publicqwidget
    {
    QLineEdit*lineEdit=nullptr;
    公众:
    DirEdit(QWidget*parent=nullptr)
    :QWidget(父项)
    {
    新的QHBoxLayout(本);
    布局()->setMargin(0);
    layout()->addWidget(lineEdit=newqlineedit(this));
    QCompleter*completer=新的QCompleter(本);
    自动模型=新的QDirModel(完成器);
    model->setFilter(QDir::AllDirs | QDir::nodotanddot);
    完成器->设置模型(模型);
    lineEdit->setCompleter(完成器);
    连接(completer,static_cast(&QCompleter::activated),[this](const QString&text)
    {
    太长了,读不下去了,编辑编辑就要做了。
    将TODO替换为

    QApplication::postEvent(this, new QKeyEvent(QKeyEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier));
    
    动机: 我在这里找到了答案的关键:

    有一个用于查找特定事件的事件过滤器,因此我只需触发其中一个事件:

    // 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;
        }
    }
    
    //为简洁起见进行了编辑。
    bool QItemDelegate::eventFilter(QObject*对象,QEvent*事件)
    {
    QWidget*editor=qobject\u cast(对象);
    如果(事件->类型()==QEvent::按键){
    开关(静态转换(事件)->key()){
    案例Qt::键输入:
    案例Qt::键返回:
    QMetaObject::invokeMethod(这是“\u q\u CommitData和CloseEditor”,
    Qt::QueuedConnection,Q_ARG(QWidget*,编辑器));
    返回false;
    }
    }
    

    在另一篇文章中,我尝试先发布一个FocusOut事件,如@fasked建议,但在本例中没有起作用

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

    QTreeView*树;
    // ...
    // ...
    QObject::connect(outsideButton,&QPushButton::单击,[tree](){
    树->设置当前索引(QModelIndex());
    });
    
    也许
    qabstractemview::closepersisteneditor()
    能帮上忙吗?@vahancho我不这么认为,因为它不是一个持久编辑器(由qabstractemview::openpersisteneditor()创建),嗯,我想你需要关闭
    QCompleter::popup()
    ?调用
    completer->popup()->close()怎么样
    ?单击某个项目或按enter键时,弹出窗口关闭。问题是行编辑保持焦点并保持打开状态。