Objektreihenfolge in Qt5

  • Hallo!

    Ich möchte gerne in Qt5 die Reihenfolge der Widgets in einem QGraphicsView ändern.

    Grundlage ist dieses Codebeispiel, mit dem man die Widgets (farbige Kreise) mit der Maus auf der Oberfläche bewegen kann.

    In dem Objekt "view" der Klasse GraphicView habe ich mehrere farbige Elypse-Widgets (moveObject, moveObject2, moveObject3) angelegt. Mit der Maus kann man diese Kreise nun verschieben. Die Reihenfolge bleibt aber immer gleich - der zuletzt erzeugte Kreis verdeckt die anderen.

    Ich möchte nun, dass der Kreis, den ich anklicke, nach vorne kommt und ggf. die anderen verdeckt, wenn ich ihn verschiebe. In die Funktion mousePressEvent() habe ich deshalb statt "pass" folgende Zeilen geschrieben:

    Code
    self.setBrush(Qt.green)
    self.raise()            # Ich habe es auch mit raise_() versucht, weil raise in Python schon ein reserviertes Wort ist. Klappt aber auch nicht.

    Die zweite Zeile sollte eigentlich das angeklickte Widget in den Vordergrund holen, führt aber zum Programmabbruch. Wenn ich die Zeile auskommentiere, läuft das Programm fehlerfrei und das angeklickte Objekt wird grün, so wie man das nach dem Code auch erwartet.

    Ich hab noch ein wenig gegoogelt und mir scheint, dass raise() nur auf Fenster angewandt werden kann.

    Wie kann ich einem Widget sagen, dass es in der Reihenfolge der Widgets ganz oben stehen, also in den Vordergrund kommen soll?

    Oh, man kann hier unliebsame Nutzer blockieren. Wie praktisch!

  • Hallo,


    eine fertige Lösung habe ich nicht gefunden. Aber so wie 'SetBrush' gibt es auch 'setFocus' eventuell findest du dazu was passendes.


    Grüße

    Dennis

    ... ob's hinterm Horizont wirklich so weit runter geht oder ob die Welt vielleicht doch gar keine Scheibe ist?

  • Focus heißt aber nur, dass das Widget aktiv ist - das hat keinen Einfluss auf die Reihenfolge.

    Oh, man kann hier unliebsame Nutzer blockieren. Wie praktisch!

  • Gnom Wie bist Du denn auf `raise_()` gekommen?


    Schau Dir mal die Dokumentation zu `GQraphicsItem` an und da speziell den Abschnitt „Sorting“.

    “The most likely way for the world to be destroyed, most experts agree, is by accident. That's where we come in; we're computer professionals. We cause accidents.” — Nathaniel Borenstein

  • Na, das ist ja easy...

    Ich hatte irgendwo gelesen, in Qt gäbe es keinen Z-Vektor. Deshalb hab ich danach gar nicht gesucht. Naja, das war wohl eine Fehlinformation.

    So zähle ich jetzt z einfach mal hoch. Ich nehme ja an, das geht bis 2^32 - so viele Mausklicks wird wohl keiner machen... ;)

    Oh, man kann hier unliebsame Nutzer blockieren. Wie praktisch!

  • Ohne das jetzt nach zu bauen, wäre es nicht möglich durch den Klick auf das Widget den zugehörigen 'z'-Wert um eins zu erhöhen und das andere um eins zu minimieren? Dann kann einer bei Bedarf tagelang durch klicken.


    Grüße

    Dennis

    ... ob's hinterm Horizont wirklich so weit runter geht oder ob die Welt vielleicht doch gar keine Scheibe ist?

  • Wenn du nur zwei Objekte hast, kannst du das mit dem Wechseln machen. Aber was machst du bei 20 oder 200 Objekten? Ich glaube, da ist es einfacher, man stellt das Objekt 64 auf 201, als dass man das Objekt 200 sucht und das mit 64 tauscht. (Was übrigens auch gar nicht der Sinn der Sache wäre. Vielmehr müsste 65 zu 64 werden, 66 zu 65, 67 zu 66, ... 200 zu 199 und 64 zu 200. Etwas aufwändig, oder?


    Bei 2^32 Zahlen kann man auch so tagelang, eher jahrelang klicken. Bis man damit fertig ist, ist der Rechner an Altersschwäche gestorben.

    Wenn man ganz paranoid ist, kann man ja noch eine Routine schreiben, die alle Objekte von 0 beginnend neu nummeriert, wenn (falls) man mal bei 2^32 angekommen ist.


    `

    Oh, man kann hier unliebsame Nutzer blockieren. Wie praktisch!

  • Etwas aufwändig, oder?

    Vielleicht kann man eine Funktion schreiben, die bei jedem Klick aufgerufen wird und mit einer Schleife alle Objekte überprüft. Wenn ich dich richtig verstanden habe, dann brauchst du so etwas ähnlich ja sowieso? Wenn du 200 Objekte hast und sich die z-Richtung von Objekt zu Objekt um 1 unterscheidet und du klickst zum Beispiel das Objekt mit z=3 an, dann muss erst der höchste z-Wert ermittelt werden und dann Objekt 3 um soviel erhöhen, das es den höchsten z-Wert hat.


    Ich will das jetzt nicht irgendwie schlecht reden oder eine unnötige Diskussion anfangen, waren nur meine Gedanken dazu.


    Grüße

    Dennis

    ... ob's hinterm Horizont wirklich so weit runter geht oder ob die Welt vielleicht doch gar keine Scheibe ist?

  • Natürlich kann man das in einer Schleife machen aber das kostet doch nur sinnlos Rechenzeit. Es geht ohne Schleife genauso.

    Der höchste Wert ist am Anfang 0. Alle Objekte haben den z-Wert 0 und werden in der Reihenfolge ihrer Instanziierung gezeichnet.

    Wenn ich einfach hochzähle und dem angeklickten Objekt die jeweils nächste Zahl als z-Wert gebe, ist das Problem gelöst - funktioniert auch einwandfrei.

    Und da die Zahl bist 2^32 gezählt werden kann, kann man 136 Jahre lang jede Sekunde einmal klicken - das wird nie einer erreichen.

    Oh, man kann hier unliebsame Nutzer blockieren. Wie praktisch!

  • Gnom: Du könntest auch die Methode stackBefore von QGraphicsItem verwenden, das manipuliert direkt die Reihenfolge auf gleicher Z-Ebene und sollte sich somit beliebig oft ausführen lassen. Dann haben Deine Nutzer auch im 137. Jahr noch Freude...


    Achtung: "Vorher" in diesem Sinne heißt, weiter vorne in der Erzeugungsreihenfolge und damit weiter hinten auf dem Bildschirm. Du müsstest also sowas wie topmostItem.stackBefore(self) in Deiner Funktion haben.

  • StackBefore bringt mich nicht weiter. Damit kann ich das Objekt hinter das oberste Objekt (sofern ich das identifiziert habe) schieben oder das oberste Objekt hinter mein gewünschtes Objekt, aber das nützt mir alles nichts.

    Mit removeItem() und anschließendem addItem() kann ich das Objekt nach vorne holen. Allerdings ist dann die self-Referenz weg, so dass die nächste Methode (Objekt mit der Maus verschieben) nicht mehr funktioniert. Das mouseMoveEvent bezieht sich noch auf das alte, gelöschte Objekt. Kann man das irgendwie geradebiegen?

    Oh, man kann hier unliebsame Nutzer blockieren. Wie praktisch!

  • StackBefore bringt mich nicht weiter.

    Ich fürchte, da hast Du recht, sorry. Ich hatte nur mit zwei Objekten experimentiert, da ging das, bei mehr als zwei sehe ich aber auch keine Möglichkeit. Da ich eigentlich überhaupt keine Ahnung von Qt habe und nur aus Neugier mal gewebsucht hatte, kann ich auch nicht weiterhelfen, sondern nur viel Erfolg wünschen. Aber mit der Z-Methode hast Du ja auch schon eine Lösung, die prinzipiell funktioniert.