2016-09-23 104 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