2016-09-23 2 views
2

Ich habe eine Unterklasse von QStyledItemDelegate, die im Moment keine Funktionen neu implementiert (zur Vereinfachung der Frage).QStyledItemDelegate teilweise Text des voreingestellten QLineEdit Editors

Mit Standard QStyledItemDelegate Implementierung, wenn der Benutzer Text in einem QTableView zu bearbeiten beginnt, zieht der Delegierte eine QLineEdit mit dem Text aus dem Modell und wählt alle davon (hebt alle für die Bearbeitung).

Der Text steht für Dateinamen wie "document.pdf". Der Benutzer darf den gesamten Text bearbeiten, ich möchte jedoch nur den Basisnamensteil ("Dokument") und nicht das Suffix ("pdf") markieren. Wie kann ich das machen? (Ich weiß nicht, die Logik müssen, wie dies zu tun, ich muss wissen, wie die QStyledItemDelegate zu bekommen einen Teil des Textes zu markieren)

Ich habe versucht:

  • in setEditorData() verwendet QLineEdit::setSelection() um etwas Text hervorzuheben. Dies hat keine Auswirkung.

  • paint() in paint() versucht zu malen basierend auf was andere Befragten zu ähnlichen Fragen empfohlen haben, aber keinen Erfolg. Ich habe wenig Erfahrung mit QPainter. Hier ein Beispiel: Adjusting the selection behaviour of QStandardItem with QStyledItemDelegate

Bitte helfen Sie, und danke im Voraus. Ein Codeschnipsel mit sagen, die ersten 3 Zeichen des Textes auswählen würde sehr geschätzt werden.

+0

Sie können Ihr Modell den Dateinamen ohne Erweiterung zurückgeben, wenn die Rolle 'Qt :: EditRole' ist. Auf diese Weise kann der Benutzer die Erweiterung nicht ändern. – Mike

+0

Wenn Sie möchten, dass die Erweiterung bearbeitbar ist, müssen Sie die Auswahl nicht malen. Sie müssen die Auswahl wirklich auf die Zeilenbearbeitung setzen, um die Erweiterung auszuschließen. Der zweite Ansatz, den Sie erwähnen, wird für Sie nicht funktionieren. – Mike

+0

überschreiben 'setEditorData' und setzen Sie die Auswahl, die Sie wollen, sollte es gut funktioniert haben. Aber in [Qt-Quellcode] (https://code.woboq.org/qt5/qtbase/src/widgets/itemviews/qabstractitemview.cpp.html#4217) können Sie einen Aufruf von 'le-> selectAll() sehen ; 'nach' setEditorData'. Leider bedeutet dies, dass die Auswahl, die Sie in 'setEditorData' eingeben, sich bei diesem Aufruf ändert. Deshalb funktioniert dein erster Ansatz nicht. – Mike

Antwort

4

Was die Frage in meinen Kommentaren erwähnt, das Problem mit Subklassifizieren QStyledItemDelegate und in setEditorData wie dies jede Standard-Auswahl zu versuchen:

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

ist, dass (in Qt-Code), nachdem die Ansicht ruft unsere setEditorDatahere versucht es selectAll()here aufzurufen, wenn das Editor-Widget ein QLineEdit ist. Das bedeutet, dass die Auswahl, die wir in setEditorData vornehmen, später geändert wird.

Die einzige Lösung, die mir einfiel, war, unsere Auswahl in einer Warteschleife anzubieten. Damit ist unsere Auswahl festgelegt, wenn die Ausführung wieder in die Ereignisschleife eintritt. Hier arbeitet Beispiel:

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

Dieses wie ein Hack klingen mag, aber ich beschloss, dies zu schreiben, bis jemand eine bessere Annäherung an das Problem hat.

+0

Vielen Dank Mike. Dies funktioniert perfekt mit einer sehr kleinen Änderung an Ihrem Code, um die Zeile if (index.column() == 0) zu entfernen, da ich eine Spalte> 0 bearbeite. Es sieht wie eine Arbeit aus, denken Sie, dass es sich lohnt, zu übergeben ein Fehlerbericht an Qt, um eine bessere API für den Zugriff auf das Widget bereitzustellen, damit der Benutzer die volle Kontrolle darüber hat? Vielen Dank :) – CSLover

+0

@CSLover, Sie sind willkommen. Das ist, was ich meinte, indem ich es setze, Sie müssen es in die Spalte ändern, in der Sie Dateinamen haben :) – Mike

+0

@CSLover, ich bin mir nicht wirklich sicher über den Fehlerbericht. Aber persönlich denke ich, dass es sich wirklich nicht lohnt, einen Fehlerbericht einzureichen. Sie scheinen den Aufruf von 'le-> selectAll()' für 'QLineEdit' zu setzen, so dass Benutzer, die 'setEditorData' außer Kraft setzen, nicht' selectAll() 'aufrufen müssen, um den Text in ihrer Zeilenbearbeitung auszuwählen Standard. Das Auslassen dieses Aufrufs kann dazu führen, dass eine Menge bereits geschriebenen Codes ein 'QLineEdit' ohne Auswahl standardmäßig anzeigt. – Mike

Verwandte Themen