Layout Algorithmen für UI



  • Hallo erstmal,

    ich bin neu hier und habe schon Grundkenntnisse in C++. Als Lernprojekt möchte ich eine eigenen kleine UI schreiben. Nun bin ich auf der Suche nach geeigneten Layout-Algorithmen, die dann so Sachen behandeln wie: Ein Element soll min 50px und max 100px breit sein, oder ein Element soll sich immer horizontal zentrieren und solche Dinge halt. Ich suche nach Erklärungen, die mir gängigen Datenstrukturen und Algorithmen, die dieses Thema behandeln , leicht verständlich näher bringen.

    Hat da jemand eine guten Link und kann eine Lösung für so ein Layout Problem beschreiben?

    Danke im voraus



  • Das Grundlegende sind ja einfache mathematische Operationen, aber wenn du es wissenschaftlich haben willst, dann lies (bzw. schau dort rein): Domain Specific High-Level Constraints for User Interface Layout [Grundlage ist also Lineare Programmierung].

    Evtl. helfen dir auch folgende C++ Libraries: Layout sowie The Ultimate Toolbox Layout Manager
    Und spez. für GTK+ noch Emeus.



  • Vielen Dank, zur Not muss ich mir doch das Paper antun, da brauche ich sicher Wochen für um das zu verstehen, aber wenn es einfacher nicht richtig geht ok. Danke für die Libs, ich möchte es ja selbst machen, da kann man sicher sich da eine oder andere abschauen.



  • Es kommt eben auf die Anforderungen an, d.h. welche Bedingungen erfüllt sein sollen.
    Grundsätzlich gibt es ja zwei Möglichkeiten: 'Parent'-Objekte passen sich an die der 'Children' an und umgekehrt.
    Beides zusammen (bei komplexem UI-Layout) in Einklang zu bringen, ist dann die Schwierigkeit bei der Umsetzung.

    Du kannst ja einfach mal mit der Bottom-Up-Methode ('Autosize') beginnen, d.h. jedes ' Parent'-Objekt bestimmt seine Größe entsprechend der untergeordneten 'Child'-Elemente.
    Und dann baust du nach und nach weitere Eigenschaften (wie MinSize, MaxSize sowie Ausrichtungen) hinzu.



  • Danke für den Tipp, werde ich mal probieren.



  • @Padawan
    Links zu guten Beschreibungen kann ich leider keine anbieten. Aber ich kann so ein bisschen was dazu schreiben. Mit einigen der Begriffen solltest du dir auch ein paar anschauliche Bilder/weitere Erklärungen ergoogeln können.


    Bei UI Layouts werden häufig Grids verwendet.

    Eine recht übliche Variante ist dabei dass man für jede Grid-Spalte und Grid-Zeile zwei Werte angeben kann: fixed_size und star_size. Die fixed_size gibt an wie gross die Spalte/Zeile mindestens ist. Und die star_size gibt an welchen Anteil die Spalte/Zeile vom verbleibenden Platz (nachdem alle fixed_size Werte abgezogen wurden) bekommen soll. Wichtig dabe ist dass es erlaubt ist dass Zeilen/Spalten sowohl fixed_size als auch star_size Werte haben können. Übliche Schreibweise wäre z.B. 5+10* für fixed_size=5, star_size=10.

    Das ist soweit auch sehr einfach zu implementieren. Dinge wie Maximalgrösse kann man auch dazubasteln wenn nötig. Dabei wird die Implementierung allerdings etwas aufwendiger - man braucht halt mehr Durchläufe und muss mehr Randbedingungen abdecken.

    Das skalierte Grid verwendet man dann um die vorläufigen Layout-Boxen der Widgets zu platzieren. Dabei ist wiederrum üblich dass ein Widget nicht nur in einer Grid-Zelle sein kann, sondern sowohl horizontal als auch vertikal mehrere Grid-Zellen belegen kann.

    Auch sehr üblich ist dass man dann pro Element angeben kann wie sie innerhalb des zu verfügung stehenden Platzes platziert werden sollen. z.B. indem man pro Achse (X und Y) auswählen kann: align_near, align_far, center, stretch. Wenn der Wert nicht stretch ist, dann nimmt man die bevorzugte Grösse des Controls statt des zu verfügung stehenden Platzes und verschiebt/verkleinert die Layout-Box entsprechend in der jeweiligen Achse.

    Weiters sehr üblich sind pro Control margin, padding und manchmal noch border zu definieren. Das sind jeweils Strukturen mit je einem Wert für left, top, right und bottom.

    margin ist ein Bereich den man innerhalb der Layout-Box des Controls bis zum "Rahmen" des Control frei lässt. D.h. wenn das Control nen margin von 10, 10, 10, 10 gesetzt hat, dann heisst das dass es mit jeweils 10 Pixel Abstand zum linken, oberen, rechten und unteren Rand der Layout-Box platziert wird.

    border ist dann die Breite des Rahmen auf den jeweiligen 4 Seiten. border 4, 2, 4, 2 heisst also z.B. dass der Rahmen des Controls links und rechts 4 Pixel breit ist und oben und unten 2 Pixel.

    Und padding ist der Bereich der zwischen der Innenseite des Rahmens und dem Inhalt des Controls frei gelassen wird. D.h. wenn das Control ein Image-Control ist und padding 5, 10, 5, 5 hat, dann werden oben zwischen dem Rahmen des Controls und dem eigentlichen Bild 10 Pixel freigelassen und auf den 3 anderen Seiten jeweils 5. padding wird genau so auch für Container-Controls verwendet, z.B. sowas wie Flow-Layout Panel. Ausgehend von der Layout-Box des Flow-Layout Panels kommt also als erstes (von aussen nach innen) der margin des Panels, dann der border des Panels und dann das padding des Panels. In den verbleibenden Bereich werden dann die Layout-Boxen der Child-Controls eingepasst. Innerhalb dieser ist dann wieder die selben Reihenfolge: erst margin dann border und zuletzt padding.

    Dann muss man sich noch überlegen wie man die Hit-Box eines Controls platziert. Für klassische Maus-Bedienung ist es wohl am üblichsten hier den border Bereich eines Controls zu nehmen. Für Touch-Bedienung wird es vermutlich eher Sinn machen die ganze Layout-Box bzw. den margin Bereich zu verwenden.



  • @Th69 sagte in Layout Algorithmen für UI:

    Du kannst ja einfach mal mit der Bottom-Up-Methode ('Autosize') beginnen, d.h. jedes ' Parent'-Objekt bestimmt seine Größe entsprechend der untergeordneten 'Child'-Elemente.

    Ich hätte das eher als Top-Down bezeichnet 🙂



  • ps: Und was das Feature angeht dass Parent-Controls sich an die Wünsche der Children anpassen: das ist recht praktisch wenn man es braucht, aber auch eher schwer zu implementieren.

    U.a. weil die Wunschbreite und Wunschhöhe eines Controls oft von einander abhängige Grössen sind. Wenn z.B. ein Text-Panel gerne 100x100 gross wäre, aber nur 50 Pixel in der Breite zur Verfügung stehen, dann wäre es gut das Control ca. 50x200 zu machen. Bei einem Image-Control das sein Bild mit korrektem Aspect-Ratio darstellen möchte, wäre es aber gut das Control nur 50x50 zu machen. Gute allgemeine Lösung gibt es da keine. Entweder man findet sich damit ab dass gewisse Controls einen unpassenden Bereich bekommen können, oder man muss dem Parent erlauben für mindestens eine der Achsen die vorgegebene Grösse zu sprengen. Oder anfangen alles inklusive Text dynamisch zu verkleinern wenn nötig - was auch überhaupt nicht gut ist.



  • Vielen vielen Dank, eure Erklärungen sind ja großartig, sobald ich etwas Freizeit habe, werde ich die Sachen mal ausprobieren.


  • Mod

    Es gibt sehr viele arten zu Layouten, von "alles automatisch" bis "der entwickler kontrolliert jedes detail".
    Ich denke es waere gut wenn du es wirklich lernen willst, schau dir existierende libs an, die unterscheiden sich dann nicht nur in algorithmen/technischen, sondern in der philosopie. z.b. definierst du das layout im code oder in externen dateien? gibt es ein UI tool dafuer? benutzt du OS native widgets oder custom? wie passt es sich an verschiedene Aufloesungen und vor allem aspect ratios an? etc.

    wenn du paar libs probiert hast, bekommst du sicher ein gefuehl dafuer was du magst und was nicht (bevor du etwas implementierst was du nicht magst).

    als zweiten schritt wuerde ich empfehlen dass du in einer existierenden lib einen neuen layouter einfuegst. Das ist dann nicht nur algorithmisch gut zu lernen, sondern auch wie es von der software architektur funktioniert, und wieder wirst du sicher rausfinden welche fehler andere machen und was du gelungen findest.
    Hier kannst du auch von den anderen layoutern die algorithmen sehen.

    und im dritten schritt dann selbst damit anfangen :).


Anmelden zum Antworten