2012-08-02 14 views
7

Ich habe eine Tabelle mit QTableview und QAbstractTableModel erstellt. In einer der Zellen möchte ich eine Hilfeschaltfläche hinzufügen (rechte Ecke dieser Zelle).Schaltfläche zu QTableview hinzufügen

Gibt es eine Möglichkeit, das oben genannte zu erreichen?

Antwort

16

Sie müssen Ihren eigenen Delegaten dafür implementieren.

In Qt, neben den Daten, dem Modell und der Ansicht, haben Sie Ihre Delegierten. Sie stellen Eingabefähigkeiten bereit und sie sind auch dafür verantwortlich, "spezielle" Elemente in der Ansicht darzustellen, was Sie brauchen.

Qt doc hat eine gute Abdeckung auf diesen (Schlüsselwörter: Model/View programming), und Sie können auch einige Beispiele here und here finden.

Auch (ein wenig Off-Thema, aber ich denke, ich sollte darauf hinweisen), wenn Sie eine gewöhnliche QTableWidget verwenden, können Sie alles in jede Zelle mit seiner setCellWidget() Funktion einfügen.

UPD

hier ist ein leicht modifiziertes Beispiel von Qt-Dokumentation (I mit Model/View-Sachen in Qt saugen so schlägt mich für diesen Code nicht schwer). Es wird eine Schaltfläche in jeder Zelle auf der rechten Seite zeichnen und die Klickereignisse in Zellen abfangen, um zu überprüfen, ob der Klick auf dem "Button" war, und entsprechend reagieren.

Wahrscheinlich ist dies nicht der beste Weg, um es zu tun, aber wie gesagt, ich bin nicht gut mit Qt Modelle und Ansichten.

Um die Dinge richtig zu machen und eine ordnungsgemäße Bearbeitung zu ermöglichen, müssen Sie auch die Funktionen createEditor(), setEditorData() und setModelData() implementieren.

Um Ihre Sachen in eine bestimmte Zelle statt aller Zellen zu zeichnen, fügen Sie einfach eine Bedingung in die paint() Funktion (beachten Sie, dass es den Modellindex als Argument erhält, so dass Sie immer wissen, in welcher Zelle Sie malen, und entsprechend malen).


delegate.h:

class MyDelegate : public QItemDelegate 
{ 
    Q_OBJECT 

public: 
    MyDelegate(QObject *parent = 0); 
    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; 
    bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index); 
}; 

delegate.cpp:

#include <QtGui> 
#include "delegate.h" 

MyDelegate::MyDelegate(QObject *parent) 
    : QItemDelegate(parent) 
{ 
} 


void MyDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const 
{ 
    QStyleOptionButton button; 
    QRect r = option.rect;//getting the rect of the cell 
    int x,y,w,h; 
    x = r.left() + r.width() - 30;//the X coordinate 
    y = r.top();//the Y coordinate 
    w = 30;//button width 
    h = 30;//button height 
    button.rect = QRect(x,y,w,h); 
    button.text = "=^.^="; 
    button.state = QStyle::State_Enabled; 

    QApplication::style()->drawControl(QStyle::CE_PushButton, &button, painter); 
} 

bool MyDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) 
{ 
    if(event->type() == QEvent::MouseButtonRelease) 
    { 
     QMouseEvent * e = (QMouseEvent *)event; 
     int clickX = e->x(); 
     int clickY = e->y(); 

     QRect r = option.rect;//getting the rect of the cell 
     int x,y,w,h; 
     x = r.left() + r.width() - 30;//the X coordinate 
     y = r.top();//the Y coordinate 
     w = 30;//button width 
     h = 30;//button height 

     if(clickX > x && clickX < x + w) 
      if(clickY > y && clickY < y + h) 
      { 
       QDialog * d = new QDialog(); 
       d->setGeometry(0,0,100,100); 
       d->show(); 
      } 
    } 

    return true; 
} 

main.cpp

#include "delegate.h" 

int main(int argc, char *argv[]) 
{ 
    QApplication app(argc, argv); 

    QStandardItemModel model(4, 2); 
    QTableView tableView; 
    tableView.setModel(&model); 

    MyDelegate delegate; 
    tableView.setItemDelegate(&delegate); 

    tableView.horizontalHeader()->setStretchLastSection(true); 
    tableView.show(); 
    return app.exec(); 
} 

Das Ergebnis wird wie folgt aussehen:

result

+0

Ich verwende QTableview. Ich möchte diesen Knopf in eine bestimmte Zelle setzen (rechte Ecke der Zelle). Könnten Sie bitte einige Codes teilen? danke in adv .. – Learner

+0

@vikuseth, aktualisierte meine Antwort – SingerOfTheFall

+0

@vikuseth, Oo ist es immer sichtbar für mich. – SingerOfTheFall

0

Wenn die Ansicht um eine Zelle ziehen will es die Farbe des Delegierten() aufruft Funktion mit einigen Informationen darüber, wie, was und wo die Inhalte ziehen die Zelle. Der Standarddelegat zeichnet nur den Qt :: DisplayRole-Text und den Auswahlstatus. Wenn Sie den Delegaten ersetzen, ersetzen Sie das Standardverhalten vollständig: Sie können zeichnen, was Sie möchten. Wenn Sie den Text wollen, müssen Sie ihn arrangieren.Sie können es selbst tun oder mit Standard-C++ - Mechanismen können Sie zuerst den Standard-Zeichnungscode aufrufen und dann oben zeichnen. Es funktioniert nach dem Hinzufügen von QItemDelegate :: Paint (Maler, Option, Index); zu Beginn meiner paint() Methode.

0

habe ich die Lösung .. Alte Farbe Methode:

void MyDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const 
{ 
    QStyleOptionButton button; 
    QRect r = option.rect;//getting the rect of the cell 
    int x,y,w,h; 
    x = r.left() + r.width() - 30;//the X coordinate 
    y = r.top();//the Y coordinate 
    w = 30;//button width 
    h = 30;//button height 
    button.rect = QRect(x,y,w,h); 
    button.text = "=^.^="; 
    button.state = QStyle::State_Enabled; 

    QApplication::style()->drawControl(QStyle::CE_PushButton, &button, painter); 
} 

hier ist die aktualisierte Farbe (Methode).

void MyDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const 
{ 
     QItemDelegate::paint(painter, option, index); 
    if(index.row()==8)//since i have to make it display only at (8,0) position . 
{ 
    if(index.column()==0) 
    { 
    QStyleOptionButton button; 
    QRect r = option.rect;//getting the rect of the cell 
    int x,y,w,h; 
    x = r.left() + r.width() - 20;//the X coordinate 
    y = r.top();//the Y coordinate 
    w = 15;//button width(based on the requirement) 
    h = 15;//button height(based on the requirement) 
    button.icon= QIcon(QString::fromUtf8("Resources/HelpIcon.png")); 
    button.iconSize = QSize(20,20); 
    button.rect = QRect(x,y,w,h); 
    button.text = "";//no text . since if text will be given then it will push the icon to left side based on the coordinates . 
    button.state = QStyle::State_Enabled; 

    //QApplication::style()->drawControl(QStyle::CE_PushButton, &button, painter); 

    QApplication::style()->drawControl(QStyle::CE_PushButtonLabel, &button, painter);//To make the Button transparent . 

    } 
    } 
} 
4

setIndexWidget arbeitete für mich. Beispiel:

QPushButton* helpButton = new QPushButton("Help"); 

tableView->setIndexWidget(model->index(position,COLUMN_NUMBER), helpButton); 

Wenn Sie nur eine Schaltfläche hinzufügen möchten, und tun etwas auf Klick davon, das Hinzufügen einer Schaltfläche setIndexWidget mit() funktioniert gut. Ich glaube, wir brauchen die umständliche Malmethode oder die Implementierung von Delegierten nicht.

5

Ich habe eine Lösung OHNE komplexe Neu-Erfindung der gesamten Lackierprozesse. Ich habe eine TableView, in der ich eine Schaltfläche in jeder Zeile habe. Beachten Sie, dass in meinem Fall die for-Schleife durch jede Zeile läuft.

QSignalMapper *signalMapper = new QSignalMapper(this); 

for(int i=0; i<rows.length(); i++) { //replace rows.length with your list or vector which consists of the data for your rows. 
    //do something with your data for normal cells...   
    auto item = model->index(i, COLUMN_FOR_WHATEVER_YOU_WANT); 
    model->setData(item, QVariant::fromValue(yourObject.getSpecificInformation())); 

    //make new button for this row 
    item = model->index(i, COLUMN_BUTTON); 
    QPushButton *cartButton = new QPushButton("Add"); 
    ui->table_view->setIndexWidget(item, cartButton); 

    signalMapper->setMapping(cartButton, i); 
    connect(cartButton, SIGNAL(clicked(bool)), signalMapper, SLOT(map())); 
} 
connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(doSomething(int))); 

Dann erhalten Sie automatisch den Index der Zeile, in der der Benutzer auf die Schaltfläche geklickt hat. Sie müssen nur Ihre eigenen Slot machen:

private SLOTS: 
    void doSomething(int row); 

Wenn Sie bestimmte Zellen haben, wäre es ähnlich funktionieren.

Beachten Sie, dass mir Speicherlecks in diesem Beispiel nicht wichtig waren, und ich weiß nicht genau, was passieren würde, wenn Sie Ihr TableView aktualisieren ... (Es funktioniert gut, aber es löscht möglicherweise nicht den alten Button- Zeiger, wenn neue erstellt werden)

+0

In Qt5 müssen Sie nicht einmal QSignalMapper verwenden; Sie können das Signal der Taste an ein Lambda mit dem Gehäuse Ihrer Wahl anschließen. –

Verwandte Themen