QStyledItemDelegate 部分选择默认 QLineEdit 编辑器的文本
Posted
技术标签:
【中文标题】QStyledItemDelegate 部分选择默认 QLineEdit 编辑器的文本【英文标题】:QStyledItemDelegate partially select text of default QLineEdit editor 【发布时间】:2016-09-23 18:38:01 【问题描述】:我有一个QStyledItemDelegate
的子类,目前它没有重新实现任何功能(为简单起见)。
使用默认的QStyledItemDelegate
实现,当用户开始编辑QTableView
中的文本时,代理会使用模型中的文本绘制QLineEdit
,并选择所有文本(突出显示所有文本以进行编辑)。
文本代表文件名,例如“document.pdf”。允许用户编辑整个文本,但是,我只想首先突出显示基本名称部分(“文档”)而不是后缀(“pdf”)。我怎样才能做到这一点? (我不需要这样做的逻辑,我需要知道如何让QStyledItemDelegate
突出显示部分文本)
我试过了:
在setEditorData()
中使用QLineEdit::setSelection()
突出显示某些文本。这没有任何效果。
在paint()
中尝试根据其他受访者对类似问题的建议进行绘画,但未成功。我对QPainter
的经验很少。这是一个例子:Adjusting the selection behaviour of QStandardItem with QStyledItemDelegate
请提供帮助,并在此先感谢您。非常感谢您选择文本的前 3 个字符的代码 sn-p。
【问题讨论】:
当角色为Qt::EditRole
时,您可以让模型返回不带扩展名的文件名。但这样一来,用户将无法更改扩展名。
如果您希望扩展是可编辑的,您不需要绘制选择,您需要在行编辑上真正设置选择以排除扩展。您提到的第二种方法对您不起作用。
覆盖setEditorData
并设置您想要的选择应该可以正常工作。但是在Qt source code 中,您可以在setEditorData
之后看到对le->selectAll();
的调用。不幸的是,这意味着您在setEditorData
中所做的任何选择都会在该呼叫中发生变化。这就是为什么您的第一种方法行不通的原因。
@Mike 关于如何选择文本的一部分有什么建议吗?
【参考方案1】:
正如我对问题的 cmets 所述,子类化 QStyledItemDelegate
并尝试在 setEditorData
中设置任何默认选择的问题如下:
void setEditorData(QWidget* editor, const QModelIndex &index)const
QStyledItemDelegate::setEditorData(editor, index);
if(index.column() == 0) //the column with file names in it
//try to cast the default editor to QLineEdit
QLineEdit* le= qobject_cast<QLineEdit*>(editor);
if(le)
//set default selection in the line edit
int lastDotIndex= le->text().lastIndexOf(".");
le->setSelection(0,lastDotIndex);
在视图调用我们的setEditorData
here之后(在Qt代码中),当编辑器小部件是QLineEdit
时,它会尝试调用selectAll()
here。这意味着我们在setEditorData
中提供的任何选择都会在之后更改。
我能想到的唯一解决方案是以排队的方式提供我们的选择。因此,我们的选择是在执行回到事件循环时设置的。这是工作示例:
#include <QApplication>
#include <QtWidgets>
class FileNameDelegate : public QStyledItemDelegate
public:
explicit FileNameDelegate(QObject* parent= nullptr)
:QStyledItemDelegate(parent)
~FileNameDelegate()
void setEditorData(QWidget* editor, const QModelIndex &index)const
QStyledItemDelegate::setEditorData(editor, index);
//the column with file names in it
if(index.column() == 0)
//try to cast the default editor to QLineEdit
QLineEdit* le= qobject_cast<QLineEdit*>(editor);
if(le)
QObject src;
//the lambda function is executed using a queued connection
connect(&src, &QObject::destroyed, le, [le]()
//set default selection in the line edit
int lastDotIndex= le->text().lastIndexOf(".");
le->setSelection(0,lastDotIndex);
, Qt::QueuedConnection);
;
//Demo program
int main(int argc, char** argv)
QApplication a(argc, argv);
QStandardItemModel model;
QList<QStandardItem*> row;
QStandardItem item("document.pdf");
row.append(&item);
model.appendRow(row);
FileNameDelegate delegate;
QTableView tableView;
tableView.setModel(&model);
tableView.setItemDelegate(&delegate);
tableView.show();
return a.exec();
这听起来像是一个 hack,但我决定写这个,直到有人有更好的方法来解决这个问题。
【讨论】:
非常感谢迈克。这可以完美地与您的代码进行非常小的修改以删除行 if(index.column() == 0) 因为我正在编辑列> 0。它看起来确实是一种解决方法,您认为值得提交吗向 Qt 报告错误以提供更好的 API 来访问小部件,以便用户可以完全控制它?非常感谢:) @CSLover ,不客气。这就是我所说的意思,如果你有文件名,你需要将它更改为列:) @CSLover ,我不太确定错误报告。但就个人而言,我认为这真的不值得提交错误报告。他们似乎为QLineEdit
s 调用了le->selectAll()
,因此覆盖setEditorData
的用户没有义务调用selectAll()
以默认选择其行编辑中的文本。省略该调用可能会导致许多已编写的代码显示QLineEdit
,默认情况下没有选择。
很公平。再次感谢,非常感谢。
这可以通过覆盖 QLineEdit 的方法来完成吗?我希望默认情况下不选择文本,但我正在努力制作与您的连接调用等效的 python。以上是关于QStyledItemDelegate 部分选择默认 QLineEdit 编辑器的文本的主要内容,如果未能解决你的问题,请参考以下文章
QStyledItemDelegate 在 QTableView 中显示 QComboBox
如何在 QStyledItemDelegate 中绘制整行的背景?
在 QStyledItemDelegate 中显示 QComboBox 文本而不是索引值
Qt表格中的自定义编辑组件---------------自定义代理QStyledItemDelegate