2016-09-23 99 views
2

我有一个QStyledItemDelegate的子类,它目前不重新实现任何功能(为了简化问题)。QStyledItemDelegate部分选择默认的QLineEdit编辑器的文本

在默认QStyledItemDelegate实现,当用户开始在QTableView编辑文本,委托绘制一个QLineEdit从模型中的文本,并选择它的所有(突出显示所有编辑)。

该文本表示文件名,如“document.pdf”。用户可以编辑这整个文本,但是,我只想在最初突出显示基本名称部分(“文档”)而不是后缀(“pdf”)。我怎样才能做到这一点? (我不需要的如何做到这一点的逻辑,我需要知道如何让QStyledItemDelegate突出文本的一部分)

我已经试过:

请帮助,并提前致谢。我们将非常感谢带有说选择文本的前3个字符的代码片段。

+0

当角色为'Qt :: EditRole'时,您可以让模型返回文件名而不用扩展名。但这样,用户将无法更改扩展名。 – Mike

+0

如果您希望扩展程序可编辑,您不需要绘制选择内容,您需要在行编辑中真正设置选择以排除扩展程序。你提到的第二种方法不适合你。 – Mike

+0

重写'setEditorData'并设置你想要的选择应该工作得很好。但是在[Qt源代码](https://code.woboq.org/qt5/qtbase/src/widgets/itemviews/qabstractitemview.cpp.html#4217)中,您可以看到对'le-> selectAll() ;'setEditorData'后面。不幸的是,这意味着你在'setEditorData'中的选择会随着该调用而改变。这就是为什么你的第一种方法不起作用。 – Mike

回答

4

正如我的意见的问题,与子类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); 
     } 
    } 
} 

的是,(在Qt代码)视图调用我们setEditorDatahere,当编辑器小部件是QLineEdit时,它试图呼叫selectAll()here。这意味着我们在setEditorData中提供的任何选择都会在之后更改。

我能想出的唯一解决方案就是以排队的方式提供我们的选择。因此,我们的选择是在执行回到事件循环时设置的。这里是工作示例:

screenshot

#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(); 
} 

这听起来像一个黑客,但我决定写这一点,直到有人有这个问题的更好的方法。

+0

非常感谢Mike。由于我编辑的列大于0,因此,如果(index.column()== 0)对代码进行非常小的修改以完全正常工作,它看起来像是一种工作,你认为值得提交一个错误报告给Qt提供更好的API来访问小部件,以便用户完全控制它?非常感谢:) – CSLover

+0

@CSLover,欢迎您。这就是我的意思,你需要将其更改为列,如果你有文件名:) – Mike

+0

@CSLover,我不太确定这个错误报告。但个人而言,我认为这不值得提交错误报告。他们似乎把''le-> selectAll()'调用为'QLineEdit',这样覆盖'setEditorData'的用户就不必调用'selectAll()'来让他们的行编辑中的文本被选中默认。省略该调用可能会导致很多已编写的代码默认显示“QLineEdit”,并且没有选择。 – Mike