![](/img/trans.png)
[英]QListView set Custom Editor via QStyledItemDelegate::createEditor
[英]How to close an editor created by a custom QItemDelegate::createEditor()
我創建了一個自定義項目委托,它允許用戶編輯文件路徑列表:
我通過自定義類 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();
}
將 TODO 替換為
QApplication::postEvent(this, new QKeyEvent(QKeyEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier));
我在這里找到了答案的關鍵: 為什么按“Tab”鍵只發出 QEvent::ShortcutOverride 事件?
有一個事件過濾器在尋找某些事件,所以我只需要觸發其中一個:
// 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 事件,但在這種情況下不起作用
我通過setCurrentIndex(QModelIndex())
解決了類似的問題。
QTreeView *tree;
// ...
// ...
QObject::connect(outsideButton, &QPushButton::clicked, [tree](){
tree->setCurrentIndex(QModelIndex());
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.