QTablewidget und QItemDelegate

Alles rund um die Programmierung mit Qt
Antworten
Marco812
Beiträge: 139
Registriert: 22. November 2005 11:28

QTablewidget und QItemDelegate

Beitrag von Marco812 »

Hallo,

mit QItemDelegate versuche ich unterschiedliche Widgets in einem QTablewidget darzustellen. Funktioniert auch zum gößten Teil, Allerdings hätte ich noch ein paar Fragen dazu:

1.) Warum wird in der QComboBox() nicht sofort der erste Eintrag angezeigt, wenn ich mit ui.tableWidget->insertRow(ui.tableWidget->rowCount()); eine neue Zeile einfüge?

2.) Welches Signal kann ich mit welchem Slot verbinden um in Spalte 5 (index.column()==5) einen QDoubbleValidator entsprechend des gewählten Wertes in der QComboBox() zu setzen?

3.) Welches Signal wird von was gesendet, wenn in einer Zelle des QTablewidget ein Wert geändert wurde?

Schon mal danke fürs lesen,

Marco812

Code: Alles auswählen

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

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

void RowDelegate::paint(QPainter *painter,
				const QStyleOptionViewItem &option,
				const QModelIndex &index) const
{
    if (index.column() == 6) {
        int secs = index.model()->data(index, Qt::DisplayRole).toInt();
        QString text = QString("%1:%2")
                       .arg(secs / 60, 2, 10, QChar('0'))
                       .arg(secs % 60, 2, 10, QChar('0'));

        QStyleOptionViewItem myOption = option;
        myOption.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;

        drawDisplay(painter, myOption, myOption.rect, text);
        drawFocus(painter, myOption, myOption.rect);
    } else{
        QItemDelegate::paint(painter, option, index);
    }
}

QWidget *RowDelegate::createEditor(QWidget *parent,
					const QStyleOptionViewItem &option,
					const QModelIndex &index) const
{
	int idx = index.column();
	if (idx == 2){
		QComboBox *combo = new QComboBox( parent );
		combo->addItem( "Eintrag 1" );
		combo->addItem( "Eintrag 2" );
		combo->setCurrentIndex( 0 );
		connect( combo, SIGNAL( activated( int ) ), this, SLOT( emitCommitData() ) );
		return combo; 
	}else if (idx == 6) {
        QTimeEdit *timeEdit = new QTimeEdit(parent);
        timeEdit->setDisplayFormat("mm:ss");
        connect(timeEdit, SIGNAL(editingFinished()), this, SLOT(commitAndCloseEditor()));
        return timeEdit;
    } else {
        return QItemDelegate::createEditor(parent, option, index);
    }
}

void RowDelegate::setEditorData(QWidget *editor,
				const QModelIndex &index) const
{
	int idx = index.column();
	if (idx == 2){
		QComboBox *combo = qobject_cast<QComboBox *>(editor);
		int pos = combo->findText( index.model()->data(index).toString(), Qt::MatchExactly );
		combo->setCurrentIndex(pos); 
	}else if (idx == 6){
        int secs = index.model()->data(index, Qt::DisplayRole).toInt();
        QTimeEdit *timeEdit = qobject_cast<QTimeEdit *>(editor);
        timeEdit->setTime(QTime(0, secs / 60, secs % 60));
    } else {
        QItemDelegate::setEditorData(editor, index);
    }
}

void RowDelegate::setModelData(QWidget *editor,
				QAbstractItemModel *model,
				const QModelIndex &index) const
{
	int idx = index.column();
	if (idx == 2){
		QComboBox *combo = qobject_cast<QComboBox *>(editor);
		model->setData(index, combo->currentText());
	}else if (idx == 6){
        QTimeEdit *timeEdit = qobject_cast<QTimeEdit *>(editor);
        QTime time = timeEdit->time();
        int secs = (time.minute() * 60) + time.second();
        model->setData(index, secs);
    } else {
        QItemDelegate::setModelData(editor, model, index);
    }
}

void RowDelegate::commitAndCloseEditor()
{
	emit commitData( qobject_cast<QWidget *>(sender()) );
}
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Man kann statt

Code: Alles auswählen

index.model()->data(index, Qt::DisplayRole).toInt();
auch

Code: Alles auswählen

index.data(Qt::DisplayRole).toInt();
schreiben.

Für Zelländerungen wird das dataChanged(...)-Signal gesendet: QTableWidget ist von QTableView, QAbstractItemView, QObject abgeleitet...

Punkt 2 ist unverständlich...

Punkt 1: Die Daten, die im Model stehen, überschreiben sofort deine Editor-Daten. Schreib die richtigen Daten ins Model.
Marco812
Beiträge: 139
Registriert: 22. November 2005 11:28

Beitrag von Marco812 »

Schon Mal Danke!

... zu Punkt 2, wenn in der QComboBox() der Eintrag 1 gewählt wird, wie kann ich dann z.B. in der ersten Reihe in Zelle 5 nur Eingaben von 0-35 und bei Eintrag 2 Eingaben von 0-15 erlauben? So verständlich erklärt?
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Du kannst doch bei erstellen des Editors auch abfragen, was in den anderen Zellen steht und entsprechend darauf reagieren.
Marco812
Beiträge: 139
Registriert: 22. November 2005 11:28

Beitrag von Marco812 »

Du kannst doch bei erstellen des Editors auch abfragen, was in den anderen Zellen steht und entsprechend darauf reagieren.
Genau das ist mein Problem, wie kann ich dabei auf die anderen Zellen(Widgets) und die Werte der Widgets bzw. Zellen zugreifen?

Kannst Du es mir vielleicht mit eins bis zwei Zeilen Code zeigen wie man dann auf die Zellen zugreifen kann. Ich war der Meinung in createEditor() wird nur das aktuelle Widget bzw. die eine Zelle übergeben und mir ist nicht klar wie ich auf die anderen zugreifen kann!
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Es gibt immer nur ein Widget zur selben Zeit, somit kannst du auf deine QComboBox nicht zugreifen. Und auf die Daten deines Models kannst du jederzeit zugreifen. Z.B. über QModelIndex::sibling(...)
Marco812
Beiträge: 139
Registriert: 22. November 2005 11:28

Beitrag von Marco812 »

Irgendwie will es nicht gelingen...

Punkt 1, ich habe versucht in createEditor() die Daten in das Model zu schreiben um gleich den ersten Eintrag anzuzeigen:

Code: Alles auswählen

index.model()->setData(index, combo->currentText());
Macht für mich keinen Sinn an setData() nochmal den QModelIndex zu übergeben, geht auch nicht: "cannot convert 'this' pointer from 'const QAbstractItemModel' to 'QAbstractItemModel &'" Wie geht es richtig?

Punkt2, wenn ich in createEditor mit QModelIndex::sibling(...) auf die Daten zugreifen kann, ist aber immer noch nicht der richtige Validator in der entsprechenden Zelle gesetzt. Mache ich das dann im QItemDelegate oder vielleicht in dem nachfolgenden SLOT unter Punkt3? aber wie???

Punkt 3, wie folgt wollte ich eine Zelländerung mit dem Signal dataChanged() prüfen:

Code: Alles auswählen

connect( ui.tableWidget, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(dataWasChanged(QModelIndex, QModelIndex)) );
geht bei mir leider nicht, ich bekomme als Meldung Object::connect: No such signal QTableWidget::dataChanged(QModelIndex, QModelIndex). Was ist daran falsch?
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Schau doch mal bitte in der Doku nach, wie das Signal wirklich aussieht.

Und warum willst du im createEditor Daten zurückschreiben. Das Model sollte schon richtig vorbelegt sein.
Marco812
Beiträge: 139
Registriert: 22. November 2005 11:28

Beitrag von Marco812 »

Schau doch mal bitte in der Doku nach, wie das Signal wirklich aussieht.
Habe ich ja auch gemacht, als es nicht Funktioniert hat, habe ich einfach getestet und den letzten versuch genommen, da dass Ergebnis immer das gleiche war. Funktioniert jetzt, der Fehler war, dass ich ui.tableWidget und nicht ui.tableWidget->model() verwendet hatte. Das konnte ich der Doku, leider nicht entnehmen.
Und warum willst du im createEditor Daten zurückschreiben. Das Model sollte schon richtig vorbelegt sein.
Da hatte ich was falsch verstanden. Jetzt schreibe ich in setEditorData() die richtigen Daten in das Model:

Code: Alles auswählen

combo->setCurrentIndex(index.model()->data(index).toInt());
Soweit so gut, aber der erste Eintrag wird in der ComboBox immer noch nicht angezeigt. Das macht man dann anscheinend auch unter paint(), wie ich es mit der Zeit gemacht habe. Allerdings ist mir immer noch nicht klar, wie ich dann den entsprechenden Eintrag anzeigen kann, da ja nur der Index der ComboBox im QModelIndex vorhanden ist. Wie geht das?
Antworten