QTableView SpinBoxen

Alles rund um die Programmierung mit Qt
Antworten
dazedly
Beiträge: 197
Registriert: 3. Oktober 2010 15:38
Kontaktdaten:

QTableView SpinBoxen

Beitrag von dazedly »

Hallo. Ich beiß mir schon seit ner Ewigkeit die Zähne aus. Ich suche eine Möglichkeit, wie man !einfach! eine Vollwertige SpinBox mit signals und slots in ein QTableView stopfen kann. Ich hatte mir schon das SpinBox example angesehen, aber das ist überhauptnicht, was ich will.

Ich brauche die SpinBox immer. Momentan kann man einfach mit dem Mauszeiger drüber gehen und Werte verändern.
Bei einem delegate fehlen mir anscheinend diverse funktionen.

Ich habe ein Bild im Anhang, welches Zeigt, wie ich das ganze mit QTableWidget gemacht habe. Ich konnte ganze einfach mit setCellWidget die SpinBox einfügen.

Mir wurde hier schon empfohlen folgendes zu benutzen:

Code: Alles auswählen

void QAbstractItemView::setIndexWidget (const QModelIndex & index, QWidget *widget) 
Aber das ganze zu schlecht dokumentiert, bzw. zu schlecht, als dass ich damit zurecht käme.

Ich habe die Namen von den Behandlungen entfernt.
Dateianhänge
snapshot1.png
snapshot1.png (36.38 KiB) 8054 mal betrachtet
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: QTableView SpinBoxen

Beitrag von franzf »

dazedly hat geschrieben:Bei einem delegate fehlen mir anscheinend diverse funktionen.
Wie kommst du darauf?!? Ein delegate ist genau dazu da.
Schau dir doch mal das delegate-example.(examples/itemviews/spinboxdelegate), da wirst du geholfen. Evtl. noch den editTrigger der View ändern.
Vllt. brauchst du auch gar keinen eigenen Delegate, aber das kannst nur du wissen.
dazedly
Beiträge: 197
Registriert: 3. Oktober 2010 15:38
Kontaktdaten:

Re: QTableView SpinBoxen

Beitrag von dazedly »

franzf hat geschrieben:
dazedly hat geschrieben:Bei einem delegate fehlen mir anscheinend diverse funktionen.
Wie kommst du darauf?!? Ein delegate ist genau dazu da.
Schau dir doch mal das delegate-example.(examples/itemviews/spinboxdelegate), da wirst du geholfen. Evtl. noch den editTrigger der View ändern.
Vllt. brauchst du auch gar keinen eigenen Delegate, aber das kannst nur du wissen.
Bei delegate ist die einzige funktion, welche ein QWidget zurückgibt "createEditor" Ich möchte aber keinen Editor, weil es in dem Fall unzumutbar ist, dass die User erst einen Doppelclick machen, bevor sie Daten verändern können. In dem example ist auch nicht abgedeckt, wie ich mit den Signalen und den Slots arbeiten kann.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: QTableView SpinBoxen

Beitrag von franzf »

dazedly hat geschrieben:Bei delegate ist die einzige funktion, welche ein QWidget zurückgibt "createEditor" Ich möchte aber keinen Editor, weil es in dem Fall unzumutbar ist, dass die User erst einen Doppelclick machen, bevor sie Daten verändern können. In dem example ist auch nicht abgedeckt, wie ich mit den Signalen und den Slots arbeiten kann.
Ähm... EditTrigger wäre das Stichwort gewesen, so kannst du das Editieren so zumutbar wie möglich gestalten (AnyKeyPressed findest du vllt. schön)...
dazedly
Beiträge: 197
Registriert: 3. Oktober 2010 15:38
Kontaktdaten:

Beitrag von dazedly »

Schau ich mir mal an, aber dann hab ich trotzdem noch ein paar Probleme.

Ich hab eine Ableitung für die QSpinBox geschrieben.
Die SpinBox bekommt ein Object übergeben, welches sie bei einem Change in einem Signal schicken soll. Dieses Object sammel ich in einer Liste um diverse Daten verwenden zu können. Da es nicht nur eine Spinbox ist, sondern mehrere ist das auch sehr wichtig.

Momentan sieht das so aus:

Code: Alles auswählen


                therapyTable->setItem(row, 0, new QTableWidgetItem(therapy->getName()));
		TherapySelectorSpinBox *therapySpinBox = new TherapySelectorSpinBox;
		therapyTable->setCellWidget(row, 1, therapySpinBox);
		therapySpinBox->setObjectToEmit(therapy);        ////// hier übergebe ich das Objekt
		this->allTherapySelectorSpins.append(therapySpinBox);   //// hier werden die spinboxen gesammelt damit man sie zurücksetzen kann
		connect(therapySpinBox,SIGNAL(valueChanged(int,Therapy*)), this, SLOT(changeSelectedTherapy(int,Therapy*)));
Ich müsste aber auch wieder an dieser Stelle das Objekt setzen können. Hast du eine Idee?

Wenn ich bedenke, dass ich diesen ganzen Aufwand betreiben muss, damit ich "nur" richtig nach dem Preis sortieren kann :(
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Hast du denn überhaupt schon ein fertiges Model, das du in dem QTableView anzeigen könntest? Dein Code ist ja wieder nur für ein QTableWidget.

Und das QAbstractItemView::setIndexWidget() sollte natürlich auch gehen, wenn du solche Hacks weiter betreiben möchtest (ich versteh den Sinn dahinter immer noch nicht). Ich finde permanente Widgets in einer View aber unangenehm, wenn ich mit der Maus über der View Scrolle, kann es durchaus passieren, dass ich einen Wert in einer Spinbox ändere. Das dann wieder zurück ändern - gute Nacht!

Kannst du vielleicht einfach kurz erklären, warum du diese Griffe anwenden willst? Dein Ziel? Wirklich nur sortieren? Ein eigenes ProxyModel wäre nicht besser?
dazedly
Beiträge: 197
Registriert: 3. Oktober 2010 15:38
Kontaktdaten:

Beitrag von dazedly »

Ich habe an einer anderen Stelle schon ein Tableview mit proxymodel zum sortieren, aber da brauche ich so etwas nicht.

Die Tabelle von dem Bild oben ist für einen Wizard um neue Rezepte zu erstellen. So wie er jetzt ist, ist es optimal, bis auf die Tatsache, dass QTableWidget zu dämlich ist für nach einen zweiten Datensatz zu sortieren.
Die Tabelle hat immer diese Behandlungen drin mit leeren SpinBoxen und sie sind ausschließlich dafür gedacht die Anzahl, bzw den Aufschlag ein zu stellen. Die Tabelle wird auch an keiner Stelle angezeigt um irgendwelche mengen zu zeigen.
Da die Anzahl und der Typ der Behandlungen variieren, muss die Liste/Tabelle voll dynamisch bleiben.
dazedly
Beiträge: 197
Registriert: 3. Oktober 2010 15:38
Kontaktdaten:

Beitrag von dazedly »

QAbstractItemView::setIndexWidget()
trotzdem ne idee, wie man das verwendet?
dazedly
Beiträge: 197
Registriert: 3. Oktober 2010 15:38
Kontaktdaten:

Beitrag von dazedly »

*Push* Hat jetzt jemand eine Idee, wie ich QAbstractItemView::setIndexWidget() benutze? Viele empfehlen es und keiner kann mir sagen, wie ich es benutze. Ich habe auch mit google keine passende Antwort gefunden.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Das sollte doch eindeutig sein! Schon mal versucht Model/View zu verstehen? Dabei sreht sich alles um QModelIndex. Der Index gibt ein "Datenfeld" des Models zurück. Wenn du jetzt ein solches Feld hast, hast du einen Index, dann sollte doch klar sein, wie die Methode anzuwenden ist, oder?
Über dein Model einen index() für row/column/parent holen, diesen dann für setIndexWidget einsetzen, fertig. (Ich habs noch nie gemacht, aber so geht es sicher).
dazedly
Beiträge: 197
Registriert: 3. Oktober 2010 15:38
Kontaktdaten:

Beitrag von dazedly »

Naja:

Code: Alles auswählen

		QAbstractItemView::setIndexWidget(model->indexFromItem(sub7), new QSpinBox);
cannot call member function ´QAbstractItemView::setIndexWidget(const QModelIndex&, QWidget*)´ without object

Code: Alles auswählen


QAbstractItemView iv;
		iv.setIndexWidget(model->indexFromItem(sub7), new QSpinBox);

cannot declare variable ´iv´ to be of abstract type ´QAbstractItemView´

Code: Alles auswählen

QAbstractItemView *iv = new QAbstractItemView;
		iv->setIndexWidget(model->indexFromItem(sub7), new QSpinBox);
error cannot allocate an object of abstract type ´QAbstractItemView´

[/code]

Ganz einfach? Ich würde gerne wissen, wie ich es richtig mache.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Sry, aber das hat nix mit Qt zu tun, das ist C++. QAbstractItemView hat pure virtual Funktionen, drum kann man davon kein Objekt instantiieren. Du kannst aber sehr wohl Instanzen von abgeleiteten Klassen bilden - so wie deine QTableView. Und DA sollst du dann setItemWidget drauf aufrufen.
Den ersten Versuch ordne ich einfach mal unter "Verzweiflung" ein...
dazedly
Beiträge: 197
Registriert: 3. Oktober 2010 15:38
Kontaktdaten:

Beitrag von dazedly »

Code: Alles auswählen

		
                QStandardItem *sub7 = new QStandardItem;
		view->setIndexWidget(model->indexFromItem(sub7),new QSpinBox);
		qDebug()<< model->indexFromItem(sub7);
Das wird Kompiliert und ausgeführt. Mein qDebug gibt mir auch ein ModelIndex zurück, welches auch richtig aussieht. Aber irgendwie interessiert sich meine Tabelle überhaupt nicht dafür.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Wenn die drei Zeilen so hintereinander stehen, wundert mich nicht dass es nicht geht. Dein item ist nicht im model, deshalb sollte der ModelIndex auch nicht valid sein. Bau das mal ins qDebug() ein. Oder poste deinen Original-Code.

// edit:
Hab das schnell mit nem QStandardItemModel in der Python-Konsole probiert und - wen wunderts - es funktioniert. Fehler liegt also in deinem Code.
Antworten