Registriert: Di Okt 03, 2006 14:07 Beiträge: 1277 Wohnort: Wien
Ich habe eine Frage in Bezug auf das Einrichten einer ComboBox. Die Frage betrifft nicht das Zeichnen des Widgets, sondern den Hittest.
Ich lasse einen Hittest über den GUI-Baum los, um zu finden, welches Widget der Benutzer angeklickt hat. Das funktioniert ausgezeichnet, solange die Widgets sich schön brav auf der Zeichenfläche ihres Parents aufhalten (ein Button sitzt auf einem Panel, welches sein Parent ist: Im Zuge des Hittest befragt das Fenster das Panel, das wiederum seinen Button befragt.
Bei einer ComboBox ist es aber so, das sie sich während des Programmbetriebs in der Größe ändern kann. Wenn sie ihr Item-Panel ausfährt, dann befindet sich das Panel möglicherweise nicht mehr auf der Parent-Zeichenfläche - sogar nicht mal mehr im Fenster (das kann Windows, ich kann das nicht).
Und mein schöner Hittest ist im Eimer. Denn wenn der Benutzer das ComboBox-Panel anklickt, fühlt sich das Parent nicht angesprochen, da der Panel-Hittest "nicht getroffen" liefert. Deswegen befragt das Panel seine Kinder gar nicht mehr, ob sie getroffen wurden. Folge: Die ComboBox ist "tot": sie setzt keine Reaktionen mehr.
Eine mögliche Abhilfe wäre, die ComboBox ans Fenster zu hängen, nicht an das Panel, wo es drauf sitzt. Diese Lösung gefällt mir aber nicht besonders. Weiß jemand etwas besseres?
Zuletzt geändert von Traude am Mi Apr 18, 2007 12:29, insgesamt 1-mal geändert.
Registriert: Do Sep 25, 2003 15:56 Beiträge: 7810 Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
Gute Frage. Bei meiner GUI würde ich vielleicht folgendes Probieren.
Ich speichere die aktuell gewählte Komponente (um Exit-Events und sowas zu machen). Da könnte man beim start des Clickhandlers einfach mal gucken was für ne Komponente das ist. Und wenn es eine "SelfSizingComponent" ist, dann prüf ich als aller erstes ganz speziell nach, ob die angeklickt wurde.
Ein Sonderfall könnte aber dabei Probleme machen:
ComboBox geht auf -> in dem Moment wird ein (GUI internes) Ereignisfenster angezeigt welches genau drüber liegt. Klick ich jetzt aufs Fenster, wird zuert die CB getestet -> Falsch. Man müsste Ereignisfenster in einem übergeordneten layer behandeln.
_________________ Blog: kevin-fleischer.de und fbaingermany.com
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
In Windows wird dafür ein extra Fenster erstellt. Dieses Fenster wiederrum hat keinen direkten Parent mehr. Die Zugehörigkeit ist aber natürlich trotzdem noch irgendwo gegeben. Das wird dann aber intern geregelt. Bei allen anderen Möglichkeiten müsste man sich ja doch recht stark aus dem Fenster lehnen bzw den HitTest irgendwie verbiegen.
Da eigentlich NIE etwas über einer aufgeklappten Combobox liegen sollte, da diese sich immer schließt, wenn sie den Focus verliert und ansonsten topmost ist, sehe ich das nicht unbedingt als Problem.
Eine alternative wäre, den aufgeklappten Bereich als eigenes 'fenster' zu sehen, das irgendwo registriert wird (sprich beim Aufklappen wirds registriert, beim Zuklappen wieder unregistriert). Wenn dann beim Hittest ein registriertes fenster existiert, dann läuft der Test ausschließlich für dieses. Brauch man ja auch dafür, um zu gucken, ob jemand ausserhalb clickt, ums per 'cancel' zu schließen.
_________________ Manchmal sehen Dinge, die wie Dinge aussehen wollen, mehr wie Dinge aus, als Dinge.
<Esmerelda Wetterwax>
Es kann vorkommen, dass die Nachkommen trotz Abkommen mit ihrem Einkommen nicht auskommen und umkommen.
Registriert: Sa Jan 01, 2005 17:11 Beiträge: 2068
Programmiersprache: C++
Ich habe es bei meiner auch so ähnlich wie die Leute über mir gelöst:
Da die Combobox nur offen sein kann wenn es das Focus hat, so wird das Klick-Event erst an die Combobox geliefert und erst im Negativfall durch die restlichen Komponenten gejagt.
Desweiteren ist das mit der Combobox noch nicht mal ein Sonderfall, da man der Komponente mit dem Focus eh eine Nachricht schickt wenn es den Focus verliert.
Registriert: Di Okt 03, 2006 14:07 Beiträge: 1277 Wohnort: Wien
@Flash: Layer....., ich verstehe. Wenn man aber mit Layern anfängt, müsste man den einzelnen Layern eine Priorität verpassen. Wie wäre es damit:
SelfSizingComponents könnten z.B. immer drin hängen, zunächst mit der höchsten Priorität (weil sonst keiner da ist). Wenn ein Meldungsfenster aufgefahren wird, darf es sich vordrängen, indem es sich die höchste Priorität nimmt. Wie die Prioritäten verteilt werden, steht auf einem anderen Blatt.
@EDIT:
@Lossy: Das könnte zwar das Problem lösen, dass eine CB übers Fenster hinausragen kann; aber ich müsste mich erst mit der Vorstellung anfreunden, dafür ein "echtes" Windows-Fenster zu erstellen.
@Sidorion: Das ist irgendwie so ähnlich wie Flashs Vorschlag: abstrakt ausgedrückt wird die CB gesondert (bevorzugt) behandelt
@i0n0s: Das ist m.E. ein neuer Vorschlag: Du fragst bei einem Mausklick erst das gerade fokussierte Element: "Kannst Du das brauchen?" bevor es den Fokus verliert. Gefällt mir eigentlich am besten. Kostet gar nicht viel Rechenzeit und man kann das ganze in den normalen Ablauf einbinden.
Ich versuche, so lang wie möglich um Layer herumzukommen. Der Hittest arbeitet sich durch den Baum, und man kann steuern, ob er sich bei den Children von vorne nach hinten oder umgekehrt durcharbeitet (ich erinnere mich, in einer früheren Version von hinten nach vorne GEZEICHNET zu haben, das sollte ich für Meldungsfenster wieder einführen).
Bei einem Meldungsfenster würde ich das so realisieren, dass ein Panel mit Label drauf erzeugt wird und in die höchste Hierarchiestufe des GUI-Baums (also direkt ein Child des Fensters) gesteckt wird und zwar an die erste Stelle (das Child mit der Nummer Null). Auf "Hit" getestet wird von vorne nach hinten (Child 0->n), gezeichnet wird von hinten nach vorn (Child n->0).
Registriert: Do Sep 25, 2003 15:56 Beiträge: 7810 Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
Das was ionis schreibt meinte ich auch. Und das mit dem Ereignis ein Fokusverlust einhergeht hatte ich nicht beachtet. Dadurch brauch man nicht unbedingt einen Layer.
Obwohl. Man benötigt einen für Modale Fenster. Also welche die nicht nach hinten verschwinden. Wenn alle Modale fenster in einem Layer liegen, und sich nur untereinander verdrängen können, dann wäre der layer sicherlich ne Möglichkeit. Man müsste dann nur gucken, ob was im layer drinnen liegt. Falls nicht, dann ist alles wie bisher, falls doch, wird nur der layer ausgewertet.
_________________ Blog: kevin-fleischer.de und fbaingermany.com
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Traude: Ich weiß nicht genau wie das in eurem Projekt gelöst ist. Ich bin wohl gerade von etwas Falschem ausgegangen. Unter Windows wird jedes Fenster auf den Desktop gezeichnet. Und damit wäre ein Windowsfenster nur wiederrum ein zusätzlicher Bereich in dem gezeichnet werden kann. Wenn bei euch jetzt aber ein Fenster wiederrum ein echtes Windowsfenster wäre, dann wäre das natürlich schon reichlich kompliziert und dann kann ich das verstehen, warum du das eher nicht möchtest. Wenn ich das richtig verstanden habe. Und da bin ich mir nicht wirklich sicher.
Ich bin da eher von meiner ausgegangen bei der bei OpenGL RC meinen "Desktop" darstellt.
Registriert: Di Okt 03, 2006 14:07 Beiträge: 1277 Wohnort: Wien
Ich habe Multiwindow-Support aufs Auge gedrückt bekommen. Daher kann ich es nicht mit SDL machen. Bei Multi-Window-Support wäre Dein Vorschlag grundsätzlich möglich (ich fordere ein Betriebssystem-Fenster an und versuche, es möglichst genau einzupassen), aber ein Fremdkörper in meinem sonstigen System.
Mitglieder in diesem Forum: 0 Mitglieder und 18 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.