QGraphicsProxyWidget aus QGraphicsScene löschen

Alles rund um die Programmierung mit Qt
Antworten
Psychomax
Beiträge: 52
Registriert: 29. Dezember 2008 13:28

QGraphicsProxyWidget aus QGraphicsScene löschen

Beitrag von Psychomax »

Hallo zusammen!

Dies würde ich gern machen. Liege ich richtig in der Annahme das ein QGraphicsItem auf den Proxy zeigt? Wenn ich nämlich den Zeiger aus der Scene lösche ist auch das Widget weg. Soweit genau das was ich will. Allerdings, wenn ich das Widget jetzt nochmal mittels addWidget() einfüge kommt folgender Fehler:

GraphicsProxyWidget::setWidget: cannot embed widget 0x88acb80; already embedded

Darauf hin habe ich versucht das GraphicsItem zu erst zu löschen und danach noch mal mittel delete das Proxy Widget. Anschließend das Widget wieder einzufügen. Leider ohne Erfolg. Denn das Programm hängt sich dann auf.

LG Max
AuE
Beiträge: 918
Registriert: 5. August 2008 10:58

Beitrag von AuE »

Ähm.... mit elchen Code hast es denn gemacht? Kurzes sample?
Psychomax
Beiträge: 52
Registriert: 29. Dezember 2008 13:28

Beitrag von Psychomax »

Code: Alles auswählen

void ViewEngine::setSceneContent(QWidget *newC)
{
    QList <QGraphicsItem*> items = this->scene->items(Qt::DescendingOrder);
    if(newObj != NULL)
    {
        qDebug("HUHU");
        if(items.contains(dynamic_cast <QGraphicsItem*> (oldProxyWidget)))
        {
            qDebug("deleteObj");
            for(int i=0;i<items.count();i++)
            {
               qDebug("%d",i);
            }
            this->scene->removeItem(dynamic_cast <QGraphicsItem*> (oldProxyWidget));
        }
        oldObj = newObj;
        oldProxyWidget = newProxyWidget;
    }
    newObj = newC;
    newProxyWidget = this->scene->addWidget(newC);
    this->animatedSwitchScene();
}
Ja das wäre eventuell hilfreich. Vielleicht auch noch was zum Hintergrund. Ich habe jede Menge QWidgets, die mittels einen Automaten verknüpft sind. Für das Anzeigen wollte ich mit eine Engine bauen. (Um später auch mal beim Wechsel Effekte hinzu zu fügen.)

In meiner Scene sind sollen effektiv nur zwei Widgets sein. Eines das eingeblendet wird und eine was ausgeblendet wird. Lasse ich

this->scene->removeItem(dynamic_cast <QGraphicsItem*> (oldProxyWidget));

weg. Funktioniert das Programm wie gewünscht. Allerdings habe ich zwei Nachteile, die ich als kritisch empfinde. Zum einen bekomme ich immer die Fehlermeldung

QGraphicsProxyWidget::setWidget: cannot embed widget 0x93b4b08; already embedded

und die Liste der QGraphicsItem innerhalb der QGraphicsScene steigt stätig an.
Psychomax
Beiträge: 52
Registriert: 29. Dezember 2008 13:28

Beitrag von Psychomax »

Aso. Das Löschen funktioniert so weit, dass das Widget nicht mehr angezeigt wird. Allerdings bekomme ich dennoch das Warning, dass das Widget vorhanden ist.
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

das ganze ist etwas verwirren (keine Strategie bei der Vergabe von Variabelnbezeichner, unnötige this-Pointer, IMHO unnötige dynamic_casts, usw.), weswegen ich einfach ungeordnet ein paar Hinweise gebe:

1. Das Widget zeigt nicht auf den Proxy, sondern umgekehrt. Das Proxy "verwaltet" quasi das Child-Widget und gibt sich aus Sicht der View als normales "QGraphicsItem" aus.

2. Das Proxy wird bei "addWidget()" erstellt, weswegen bei jedem Durchgang immer mehr Proxies existieren.

3. du löscht nirgendwo was (weder ein Proxy noch ein Widget). Du entfernst es lediglich (remove... löscht keine Instanzen) aus der Scene.

4. Wenn du einmal ein Proxy hast (und dieses mit remove... entfernst), wäre es vermutlich besser, dieses Proxy wieder mit "addItem" einzufügen, als ein neues zu generieren...?

5. Von der Vorgehensweise her: wenn du einen Automaten nachbilden möchtest, ginge es denn nicht, die Unterschiedlichen Widgets einfach sichtbar/unsichtbar zu schalten? So im Stil:

Code: Alles auswählen

switch (_state) {
  case StateA:
     _proxyA->show(); _proxyB->hide(); break;
  case StateB:
     _proxyA->hide(); _proxyB->show(); break;
   ...
}
Ich habe keine Erfahrung in der QGraphicsView, aber wäre sowas nicht effizienter?
Psychomax
Beiträge: 52
Registriert: 29. Dezember 2008 13:28

Beitrag von Psychomax »

Code: Alles auswählen

 newProxyWidget = this->scene->addWidget(newC);
    this->scene->removeItem(dynamic_cast <QGraphicsItem*> (newProxyWidget));

    newObj = newC;
    newProxyWidget = this->scene->addWidget(newC);
    this->animatedSwitchScene();
auch wenn nur das in der Methode steht bekomm ich folgenden Fehler.

QGraphicsProxyWidget::setWidget: cannot embed widget 0x93b4b08; already embedded

Im Quellcode steht folgendes. Sprich wenn er die obige Fehlermeldung ausgibt, wird kein neues Widget erstellt. Auch wenn ich mittels delete den Proxy löschen möchte.

Code: Alles auswählen

// Register this proxy within the widget's private.

619 	

    // ### This is a bit backdoorish

620 	

    QWExtra *extra = newWidget->d_func()->extra;

621 	

    if (!extra) {

622 	

        newWidget->d_func()->createExtra();

623 	

        extra = newWidget->d_func()->extra;

624 	

    }

625 	

    QGraphicsProxyWidget **proxyWidget = &extra->proxyWidget;

626 	

    if (*proxyWidget) {

627 	

        if (*proxyWidget != q) {

628 	

            qWarning("QGraphicsProxyWidget::setWidget: cannot embed widget %p"

629 	

                        "; already embedded", newWidget);

630 	

        }

631 	

        return;

632 	

    }

633 	

    *proxyWidget = q;
Also ich kann kurz um, dass GraphicsItem aus der Scene löschen aber nicht aus dem Proxy. Trotz eines delete proxy. :(

@solarix

1. ja so hab ich das auch verstanden. Deswegen wollte ich auch das Proxy löschen.

Ich probiere morgen nochmal rum. Hab jetzt schon soviel im Code rumgemacht. Eventuell bringt eine Nacht Schlaf Besserung. Die Müdichkeit sieht man scheins schon in meinem Code! :D
Psychomax
Beiträge: 52
Registriert: 29. Dezember 2008 13:28

Beitrag von Psychomax »

So ich hab jetzt nochmal in Ruhe den Code aufgelöst. Fakt ist, wenn ich das Proxy Objekt lösche, es auch mein Widget löscht. Doof ist das, aber ist halt so. Muss ich mir jetzt eine andere Strategie überlegen! Trotzdem danke!!! :)
Antworten