[Nim] Fragen zu einem Frame (Window)

    • Offizieller Beitrag

    Ich habe mir mal aus mehreren Beispielcodes ein Programm erstellt. Nichts nützliches, nur etwas zu experimentieren.


    Hier erstmal der Code:

    Und hier die Fragen:- Was macht "app.mainloop()"? Ist das nur eine Endlosschleife, weil das Programm ja auf die Events reagiert? Also wie in AutoIt mit dem OnEventMode?

    - Wenn ich das richtig verstanden habe, dann muss man sich bei Nim nicht um die Freigabe der Ressourcen kümmern?

    - Ich erstelle einen Frame (Window). Wozu dann noch ein Panel?

    - Gibt es irgendwo eine Erklärung, wie das mit dem (Auto-)Layout funktioniert?

    • Offizieller Beitrag

    Erst mal zum AutoLayout - für mich auch noch immer hartes Brot.

    Das stammt aus der Apple-Welt: https://developer.apple.com/li…oc/uid/TP40010853-CH7-SW1

    Zum Testen gibt es einen Online-Editor: https://rawgit.com/IjzerenHein…or/master/dist/index.html


    Die Erstellung der Fenster mit den Ctrl läßt sich mit der Malerei vergleichen.

    - als Erstes brauchst du einen Bilderrahmen --> Frame

    - den bespannst du mit dem Leinen --> Panel

    - und auf dem Leinen wird gemalt --> Positionieren der Ctrl

    Es gibt noch andere GUI-Module, die zusätzlich auf dem Panel noch Container positionieren, in denen die Ctrl platziert werden. Vereinfacht die Ausrichtung


    "app.mainloop()" - das schätze ich genauso ein, wie du. Ich habe aber noch nicht versucht den Aufruf in den Ressourcen nachzuverfolgen, zumal ich davon ausgehe, dass das irgendwo in einer Dll endet.


    Ressourcenfreigabe ist angenehmerweise nicht erforderlich.

  • Was macht "app.mainloop()"?

    Code
    proc mainLoop(self: wApp): int {...}

    Execute the main GUI event loop. The loop will exit after all top-level windows is deleted.

    https://khchen.github.io/wNim/wApp.html#App


    Ich erstelle einen Frame (Window). Wozu dann noch ein Panel?

    A frame is a top-level window in wNim. A panel is a window on which controls are placed. It is usually placed within a frame.

    https://khchen.github.io/wNim/wFrame.html

    https://khchen.github.io/wNim/wPanel.html


    Gibt es irgendwo eine Erklärung, wie das mit dem (Auto-)Layout funktioniert?

    https://khchen.github.io/wNim/autolayout.html


    let statusBar = StatusBar(frame)

    Problem: "'statusBar' is declared but not used


    Ja... ich denke, mit Nim/wNim werde ich noch viel Spaß haben. ;)

    • Offizieller Beitrag

    BugFix : Danke, für die Erklärungen! Vor allem für den Link zum Layout-Online-Editor. So kann man wenigstens die Einstellungen testen, ohne jedes Mal compilieren zu müssen.


    Bitnugger: Auch Dir ein Dankeschön! Die Referenz kannte ich zwar schon, aber da fehlt mir dann oft ein Beispielcode.


    Zum Beispiel, würde es mich interessieren, wie ich ein Bild (JPG) laden und auf einem Panel anzeigen lassen kann. Am besten noch so, dass es automatisch an die Größe angepasst wird.

    Oder überhaupt irgendwelche kleine Programme, die etwas (mehr oder weniger) Sinnvolles tun. Einfach nur, um mal zu sehen, wie man sowas mit Nim umsetzt.

    Das hat mir beim lernen von AutoIt sehr geholfen, dass in der Hilfe viele Beispiel-Scripte enthalten sind. So kann man sich durch rumexperimentieren vorantasten.

    • Offizieller Beitrag

    Hier mal ein Bsp. um ein PNG anzuzeigen (Dateipfad anpassen), Funktioniert auch mit anderen Bildformaten.



    Die Funktionsdetails findest du alle in der Online-Doku wNim.


    Übrigens, wenn nur die ID "idExit" benötigt wird, kann man sich die Typdeklartion sparen. Dann reicht völlig:

    const idExit = wIdUser

    (oder man nimmt gleich wIdExit :Face:, naja - auch für mich noch neu)

    • Offizieller Beitrag

    Ah ja, genau so ein kurzes Beispiel habe ich gesucht. Danke!

    Ich hab's bei mir jetzt mal so eingefügt:

    Code
    const myJpg = staticRead(r"test.jpg")
    let myImage = Image(myJpg).scale(600, 480)
    let staticbitmap = StaticBitmap(panel, bitmap=Bitmap(myImage))

    Also Bild laden, auf 600x480 skalieren und im StaticBitmap anzeigen.

    Das meinte ich oben, mit kleinen Programmen, die sehr hilfreich sind.

    • Offizieller Beitrag

    Mein Testprogramm sieht jetzt so aus:

    Wie kann ich den Style der Gui-Elemente beeinflussen?

    Ich hätte gern, dass die Schrift transparent auf dem Hintergrundbild ist.

    Und das Hintergrundbild verhindert das betätigen der Buttons. Also muss wohl irgendwie der Klick auf das Bild deaktiviert werden (wie in AutoIt). Aber wie?

    • Offizieller Beitrag

    Und das Hintergrundbild verhindert das betätigen der Buttons. Also muss wohl irgendwie der Klick auf das Bild deaktiviert werden (wie in AutoIt). Aber wie?

    Das ist ausnahmsweise einfach. Wir müssen nicht wie in AutoIt denken. Hier ist alles auch ein Fenster. D.h. die Referenz für die Button und alle Ctrl, die über dem Bild liegen sollen, muss dann auch das Bild sein:

    let button = Button(staticbitmap, label="Font", pos=(0, 80)) etc.


    Wegen der anderen Sachen werde ich mal schauen.


    Edit:

    Ich habe es mal versucht mit: style=wTransparentWindow und staticText.setTransparent() - beides ohne Erfolg. Bsp. habe ich dazu auch nicht entdecken können.

    Da es wohl nicht trivial ist, habe ich eine Anfrage an den Autor gestellt: https://github.com/khchen/wNim/issues/55

    • Offizieller Beitrag

    Das ist ausnahmsweise einfach. Wir müssen nicht wie in AutoIt denken. Hier ist alles auch ein Fenster. D.h. die Referenz für die Button und alle Ctrl, die über dem Bild liegen sollen, muss dann auch das Bild sein:

    Ah, ok! Das funktioniert! Danke! :thumbup:



    Ich habe es mal versucht mit: style=wTransparentWindow und staticText.setTransparent() - beides ohne Erfolg. Bsp. habe ich dazu auch nicht entdecken können.

    Da es wohl nicht trivial ist, habe ich eine Anfrage an den Autor gestellt: https://github.com/khchen/wNim/issues/55

    Oh! Da habe ich wohl etwas aufgedeckt.

    Das mit dem "style=wTransparentWindow" hatte ich auch ausprobiert, aber da das nicht funktionierte, dachte ich, ich frage mal nach.

    • Offizieller Beitrag

    So, Antwort vom Autor:

    "You can deal with wEvent_Paint event and try to paint what you want. For example:"

    • Offizieller Beitrag

    So, Antwort vom Autor:

    "You can deal with wEvent_Paint event and try to paint what you want. For example:"

    Ein "neu malen" bei WM_PAINT ist jetzt irgendwie nicht das, was ich mir vorgestellt habe. :/

    Dann lässt sich der StaticText nicht mehr als "Button" gebrauchen und man muss das resizen selbst übernehmen.

    Bei AutoIt funktioniert das doch auch einfach durch setzen der "Hintergrundfarbe": GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT).

    • Offizieller Beitrag

    OK, das Resizen geht nicht mehr automatisch. Das Klickevent auf den Text zu erkennen, ist sicher durch Eventzuordnung zum Rect realisierbar, aber auch erhöhter Aufwand.

    Ich werde mich mal in die Tiefen des Moduls eingraben. Vielleicht finde ich die Lösung.

    • Offizieller Beitrag

    So, Resizen und Transparenz konnte ich lösen. Ich habe die Prozedur zum Zeichnen des StaticText-Ctrl überschrieben. Nur Klickevent geht damit (noch) nicht:


    Code
    staticText.wEvent_Paint do ():
      var
        dc = PaintDC(staticText)
        rect = (0, 0, staticText.getBestSize().width, staticText.getBestSize().height)
    
      dc.backgroundTransparent = true
      dc.font = staticText.getFont()
      dc.drawLabel(staticText.label, rect, wCenter)
    • Offizieller Beitrag

    Jetzt habe ich noch einen eigenen Mouse-Handler eingefügt. Funktioniert nur noch nicht so, wie erwartet. Ich kann dort eine Terminalausgabe mit "echo" ausführen, aber keine eigenen Prozeduren ausführen (also z.B. den TextEntryDialog aufrufen), da fehlt mir momentan noch der Hintergrund.




    EDIT: Oscar

    Oh man, das Standardverfahren zum Erkennen der Events funktioniert ja. Es ist der Dialog, der sich nicht starten ließ!

    Ich kann zwar nicht genau erkennen, was an deiner Dialogzeile falsch sein soll, aber hiermit funktioniert es, wie gewollt:

    Code
    staticText.wEvent_CommandLeftClick do ():
      let dialog = TextEntryDialog(frame, value=staticText.label, message="Input text", caption="Modaless TextEntryDialog", style=wDefaultDialogStyle)
      dialog.showModaless()

    Vor lauter Auskommentierungen bei mir übersehen: Es fehlte doch was: dialog.showModaless()


    EDIT2: Oscar

    Hier noch mal kpl. mit Übernahme Eingabe + Neuzeichnen.

    Code
    staticText.wEvent_CommandLeftClick do ():
      let dialog = TextEntryDialog(frame, value=staticText.label, message="Input text", caption="Change The Text", style=wDefaultDialogStyle)
    
      dialog.wEvent_DialogClosed do ():
        if dialog.returnCode == wIdOk and dialog.value.len != 0:
          staticText.label = dialog.value
          panel.refresh()
    
      dialog.showModaless()
    • Offizieller Beitrag

    Oh man, das Standardverfahren zum Erkennen der Events funktioniert ja. Es ist der Dialog, der sich nicht starten ließ!

    Ich wollte Dir auch gerade schreiben, dass das Label jetzt doch als Button funktioniert.

    Ich hatte hier Verschiedenes ausprobiert, verschoben, gelöscht, wiederhergestellt und plötzlich ging es dann.

    Obwohl ich der Meinung bin, dass ich das so schon mal hatte und es nicht funktionierte.

    Hier jetzt mal die Version, die bei mir funktioniert:

    Wobei mir jetzt noch etwas aufgefallen ist, was ich nicht verstehe.

    Wenn ich den Text anklicke, kann ich ihn ja ändern. Wenn ich einen anderen Text eingebe, dann erscheint wieder der weiße Hintergrund. Trotz staticText.refresh(). Wird da nicht die "wEvent_Paint" ausgeführt?


    Und wenn ich die Fontgröße ändere, dann bleibt die Schrift in der kleinen Variante bestehen und es wird die große Variante zusätzlich geschrieben. Ändere ich dann aber die Größe des Fenster bewirkt der Refresh das löschen der kleinen Variante (erwünscht).


    Bei "wEvent_Size" wird ja eigentlich nur die Proc "layout()" aufgerufen. Wenn ich das aber nach der Änderung der Fontgröße manuell tue, dann bleibt es bei der falschen Darstellung. Wahrscheinlich macht "wEvent_Size" wohl noch mehr (im Hintergrund).

    Wie kann ich den Event denn manuell aufrufen?

    • Offizieller Beitrag

    Du mußt refresh für das Panel aufrufen. Wenn du nur das Text-Ctrl neuzeichnest bleibt dafür der alte Inhalt noch bestehen, erst mit Neuzeichnen des Panel wird auch das Ctrl neu berechnet.

    Was bisher aber amit nicht funktioniert, ist dass das Layout angepasst wird. Ich hatte den Text mit centerX/Y am Panel ausgerichtet. Das wird bei Aufruf von Layout aber nicht mit der neuen Textlänge korrigiert.

    • Offizieller Beitrag

    Falls du mehrere StaticText hast, die du transparent zeichnen möchtest, kann man das so lösen: