Fade-Effekt zum Verstecken einer Reihe eines QTableWidgets?

Alles rund um die Programmierung mit Qt
Antworten
MADsCIENTIST

Fade-Effekt zum Verstecken einer Reihe eines QTableWidgets?

Beitrag von MADsCIENTIST »

Hallo liebe Community,

ich wollte mal nachfragen, ob es bei einem QTableWidget möglicht ist, einen Fade-Effekt für das Verstecken einer Zeile bzw. Spalte einzurichten?

Wenn ich bei mir bestimmte Zeilen verstecke, sollen diese sich von unten nach oben zuklappen und dabei die Opacity prozentual nach der Zeilengröße verringert werden.
Der Gegensatz dazu wäre dann, das die entsprechenden Zeilen sich von oben nach unten wieder aufklappen.

Wie ist das realisierbar?

Bedanke mich schon mal im Voraus :mrgreen:
Zuletzt geändert von MADsCIENTIST am 11. April 2013 15:11, insgesamt 1-mal geändert.
veeman
Beiträge: 280
Registriert: 3. Oktober 2012 01:43
Kontaktdaten:

Re: Fade-Effekt für Verstecken einer Reihe eines QTableWidge

Beitrag von veeman »

Wie man die Opacity verändert weiß ich jetzt nicht, vermutlich muss man da mit selbstgebauten QItemDelegates arbeiten.
Fürs auf und zu klappen kannst du eine Animationssklasse verwenden...

Code: Alles auswählen

class QMyTableRowAnimation : public QVariantAnimation
{
    Q_OBJECT

public:
   QMyTableRowAnimation(QTableWidget *parent, int row) :
    QVariantAnimation(parent), _row(row)
   {
        QHeaderView *rowHeader = parent->verticalHeader();
        rowHeader->setResizeMode(_row, QHeaderView::Fixed);
   }
protected:
    virtual void updateCurrentValue(const QVariant &value)
    {
        QHeaderView *rowHeader = qobject_cast<QTableWidget*>(parent())->verticalHeader();
        rowHeader->resizeSection(_row, value.toInt());
    }
    virtual  void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)
     {
         QVariantAnimation::updateState(newState, oldState);
         if (currentTime() >= totalDuration())
              emit finished(_row);
     }

signals:
    void finished(int index);

private:
    int _row;
};
Und dann so verwenden:

Code: Alles auswählen

void MainWindow::on_pushButtonDelete_clicked()
{
    int currentRow = ui->tableWidget->currentRow();
    if (currentRow < 0)
        return;

    QMyTableRowAnimation *animation = new QMyTableRowAnimation(ui->tableWidget, currentRow);
    ui->tableWidget->connect(animation, SIGNAL(finished(int)), SLOT(removeRow(int)) );
    animation->setDuration(200);
    animation->setStartValue(20);
    animation->setEndValue(0);
    animation->start(QMyTableRowAnimation::DeleteWhenStopped);
}

void MainWindow::on_pushButtonAdd_clicked()
{
    int currentRow = ui->tableWidget->currentRow();
    if (currentRow < 0)
        currentRow = 0;
    ui->tableWidget->insertRow(currentRow);

    QMyTableRowAnimation *animation = new QMyTableRowAnimation(ui->tableWidget, currentRow);
    animation->setDuration(200);
    animation->setStartValue(0);
    animation->setEndValue(20);
    animation->start(QMyTableRowAnimation::DeleteWhenStopped);
}
MADsCIENTIST

Re: Fade-Effekt für Verstecken einer Reihe eines QTableWidge

Beitrag von MADsCIENTIST »

Funktioniert einwandfrei... vielen Dank :D
MADsCIENTIST

Re: Fade-Effekt für Verstecken einer Reihe eines QTableWidge

Beitrag von MADsCIENTIST »

Habe mich jetzt mal mit der Animationsgeschichte (QAbstractAnimation, etc.) auseinandergesetzt und versucht, meine eigene
parallele Animationsgruppe zu erstellen, damit alle entsprechenden Reihen gleichzeitig versteckt werden.

Ich erhalte jedoch bei dem unten aufgeführten Quellcode einen Fehler an der Stelle mit dem "qobject_cast<QTableWidget*>"!
=> Zugriffsverletzung beim Lesen an Position ..., also ein speicherspezifisches Problem mit den Pointern.

In meinem Fall heißt die Klasse, welche QVariantAnimation vererbt bekommt, "Animations".

Quellcodeschnippsel:

Code: Alles auswählen

QParallelAnimationGroup* groupAnimation = new QParallelAnimationGroup(this);
Animations* animation;

for(int i=0; i<list.size(); i++) {
	// For fade-out effect
	animation = new Animations(this, list.at(i) /*for row*/);
	animation->setDuration(200);
	animation->setStartValue( this->rowHeight(list.at(i)) );
	animation->setEndValue(0);
	groupAnimation->addAnimation(animation);
}
groupAnimation->start(Animations::DeleteWhenStopped);

Wie ist das wiederum zu lösen?
[+]
Wie schaffe ich es, das beim Fade-IN/-OUT-Effekt einer Zeile deren Inhalt synchron mitfährt?
Also:

[CLOSED]
+------------------+



[FADE-IN]
+------------------+
du
da!
+------------------+



[FADE-IN END]
+------------------+

Hallo
du
da!
+------------------+

[+]
Wie kann ich dafür sorgen, das die allokierten "Animations" Objekte nach Beenden der Animation wieder gelöscht werden?
Ich weiß das ich vor deren Löschung natürlich mit "removeAnimation(QAbstractAnimation*)" für die QParallelAnimationGroup arbeiten muss.
=> Möchte nicht unnötig Speicher belegen!
veeman
Beiträge: 280
Registriert: 3. Oktober 2012 01:43
Kontaktdaten:

Re: Fade-Effekt für Verstecken einer Reihe eines QTableWidge

Beitrag von veeman »

MADsCIENTIST hat geschrieben: Ich erhalte jedoch bei dem unten aufgeführten Quellcode einen Fehler an der Stelle mit dem "qobject_cast<QTableWidget*>"!
=> Zugriffsverletzung beim Lesen an Position ..., also ein speicherspezifisches Problem mit den Pointern.
Du musst als parent ein QTableWidget übergeben, da sonst auf die HeaderSection'en dieser nicht zugegriffen werden kann.
MADsCIENTIST hat geschrieben: Wie schaffe ich es, das beim Fade-IN/-OUT-Effekt einer Zeile deren Inhalt synchron mitfährt?
Sollte auch mit einer benutzerdefinierten QItemDelegates Klasse gehen. -> Die paint-Methode so umschreiben das der Text am unteren Rand ausgerichtet wird.
MADsCIENTIST hat geschrieben: Wie kann ich dafür sorgen, das die allokierten "Animations" Objekte nach Beenden der Animation wieder gelöscht werden?
Wenn du DeleteWhenStopped angibst dann werden diese automatisch gelöscht. Nicht jedoch die einzelnen Zeilen diese werden nur ausgeblendet und müssen explizit gelöscht werden:

Code: Alles auswählen

ui->tableWidget->connect(animation, SIGNAL(finished(int)), SLOT(removeRow(int)) );
<- Hier, nach dem die Animation beendet wurde und die Zeile nicht mehr sichtbar ist wird diese endgültig gelöscht.
Bei mehrfach Animatioen/Löschung wird wohl die Reihenfolge wie diese Zeilen gelöscht werden müssen eine Rolle spiel (->rückwärts).
MADsCIENTIST

Re: Fade-Effekt für Verstecken einer Reihe eines QTableWidge

Beitrag von MADsCIENTIST »

MADsCIENTIST hat geschrieben: Wie kann ich dafür sorgen, das die allokierten "Animations" Objekte nach Beenden der Animation wieder gelöscht werden?
veeman hat geschrieben: Wenn du DeleteWhenStopped angibst dann werden diese automatisch gelöscht. Nicht jedoch die
einzelnen Zeilen diese werden nur ausgeblendet und müssen explizit gelöscht werden:
...
Zur Info: Ich hatte nie vor eine Zeile zu löschen! Diese wird im weiteren
Programmverlauf noch benötigt. Ich möchte lediglich, das sich jedes einzelne allokierte
Animationsobjekt

Code: Alles auswählen

// within if-clause
// ...
animation = new Animations(this, list.at(i));
// ...
selbstständig aus dem Speicher entfernt, sobald dessen finished() Methode aufgerufen wird.

Es soll nur für die gerade gebrauchten Zeilen, also diejenigen, welche per FADE-IN und -OUT behandelt
werden, ein temporäres Animationsobjekt angelegt werden!


Im Endeffekt muss man dafür aber nur mit dynamischen Listen arbeiten, also nichts Neues :D
MADsCIENTIST

Re: Fade-Effekt zum Verstecken einer Reihe eines QTableWidge

Beitrag von MADsCIENTIST »

Auch wenn die vorherige Frage bis jetzt noch nicht beantwortet wurde, würde ich jetzt gerne wissen,
wie ich (mit der von veeman aufgeführten Animationsklasse) es hinbekomme, das sich meine
letzte Reihe immer der aktuellen Fenstergröße anpasst.

Zurzeit speichere ich beim Hinzufügen einer Reihe deren optimale Größe (für das spätere IN- und OUT-FADING)
mit vorherigem Ausführen von "resizeRowToContents" in deren SizeHint.

Diesen Wert setze ich beim OUT-FADEN als Startwert (setStartValue) und beim IN-FADE logischerweise als
Endwert (setEndValue).

=> Das Problem hierbei ist halt jetzt nur, dass wenn ich das QTableWidget-Fenster resize, sich die Höhe der
letzten Reihe nicht dem unteren rechten Ende des Viewports anhängt.

Wie kann ich automatisch (entsprechend der aktuellen Viewportgröße) die optimale auf den Inhalt der Reihe
abgestimmte Höhe erhalten?


Gibt es denn dafür keine Funktion? (resizeRowToContents bekommt ja auch irgendwie den Wert zusammen)

TRICKY :shock:
Antworten