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