Darstellung auf MAC weicht stark ab

Fragen zu Tkinter.
Antworten
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

Guten Abend

es geht voran mit meiner Anwendung.
Erstellt habe ich meine Anwendung unter Windows.
Unter Linux musst ich die Schriftgröße schon reduzieren, damit es relativ vergleichbar aussieht.
Jedoch auf dem Mac (kann es selbst nicht testen, mangels Mac) macht mir das Design ein Strich durch die Rechnung, dass sogar Buttons nicht zu sehen sind.
Das mit der Schrift lässt sich mit kleinerer Schrift vermutlich lösen.
Habt ihr evtl. Lösungen, dass das Register bzw. die Tabs besser dargestellt werden? So wie ich es erkannt habe, gibt es fürMac nur die built-in Theme "aqua".

Folgend noch paar Screenshots
Windows:
Bild

Linux:
Bild

Mac (Fenster ist maximiert):
Bild
empty Sig
Benutzeravatar
__blackjack__
User
Beiträge: 12984
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@harryberlin: Man benutzt halt kein `place()` um Position und Grösse von allen Elementen anzugeben. Ich glaube das wurde schon mal in einem anderen Thema zu diesem Programm gesagt…
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

Du meinst vermutlich den Thread hier:
viewtopic.php?t=42636

Da stellt sich mir nur die Frage, welche Daseinsberechtigung hat 'place()', wenn es böse ist.
Ich versuch es jetzt mal mit anderen ttkthemes. Mal schaun, ob das dem Ziel näher kommt.
empty Sig
Sirius3
User
Beiträge: 17703
Registriert: Sonntag 21. Oktober 2012, 17:20

Da helfen auch keine anderen ttkthemes. Ich sehe da auch nichts, was man nicht mit einem verschachteln von grid und pack umsetzen könnte.
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

Mit grid ist halt das topic, dass beim Resize des Fensters alles mit geht.
[ironie] Und ist auch irgendwie, wie html-websites aus dem Jahre 1995. [/ironie]

Ich würde sagen, das schaut recht brauchbar aus, mit theme 'scidblue':
Bild
empty Sig
Sirius3
User
Beiträge: 17703
Registriert: Sonntag 21. Oktober 2012, 17:20

Und beim nächsten Rechner mit einer anderen Bildschirmauflösung geht es wieder schief.

Was ist denn das konkrete Problem bei grid? Zeig das Problem mit dem dazugehörigen Code und dann kann man weiterhelfen.
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

Warum sollte es abhängig von der Auflösung sein?

Hab es jetzt mal versucht mit 'grid' und als spacer habe ich frames genommen.
Finde es etwas unglücklich, wenn man etwas einfügt, dann müssen die ganzen columnt umgeschrieben werden, damit sie nachrücken.

Code: Alles auswählen

class App(tk.Tk):

    def __init__(self):
        tk.Tk.__init__(self)
        self.frame0 = tk.Frame(self, width=10)
        self.frame0.grid(row=2, column=0)

        self.frame1 = tk.Frame(self,height=10)
        self.frame1.grid(row=1, column=0)



        self.rdAVR = tk.Radiobutton(self)
        self.rdAVR.configure(activebackground="#ececec")
        self.rdAVR.configure(activeforeground="#000000")
        self.rdAVR.configure(background="#d9d9d9")
        self.rdAVR.configure(disabledforeground="#a3a3a3")
        self.rdAVR.configure(foreground="#000000")
        self.rdAVR.configure(highlightbackground="#d9d9d9")
        self.rdAVR.configure(highlightcolor="black")
        self.rdAVR.configure(indicatoron="0")
        self.rdAVR.configure(justify='left')
        self.rdAVR.configure(selectcolor="#8080ff")
        self.rdAVR.grid(row=2, column=1)
        self.rdAVR.configure(text='''AVR''')
        self.rdAVR.configure(value="0")
        self.rdAVR.bind('<ButtonRelease-1>', lambda e: self.after(1, self.rdAVR_click))
        self.rdAVR.configure(variable=self.avr_mode)

        self.rdIBus = tk.Radiobutton(self)
        self.rdIBus.grid(row=2, column=2)
        self.rdIBus.configure(activebackground="#ececec")
        self.rdIBus.configure(activeforeground="#000000")
        self.rdIBus.configure(background="#d9d9d9")
        self.rdIBus.bind('<ButtonRelease-1>', lambda e: self.after(1, self.rdIBus_click))
        self.rdIBus.configure(disabledforeground="#a3a3a3")
        self.rdIBus.configure(foreground="#000000")
        self.rdIBus.configure(highlightbackground="#d9d9d9")
        self.rdIBus.configure(highlightcolor="black")
        self.rdIBus.configure(indicatoron="0")
        self.rdIBus.configure(justify='left')
        self.rdIBus.configure(selectcolor="#8080ff")
        self.rdIBus.configure(text='''IBus''')
        self.rdIBus.configure(value="1")
        self.rdIBus.configure(variable=self.avr_mode)

        self.frame2 = tk.Frame(self, width=10)
        self.frame2.grid(row=2, column=3)

        self.cbSerialPorts = ttk.Combobox(self)
        self.cbSerialPorts.grid(row=2, column=4)
        self.port_list = ['Select Device...',]
        self.cbSerialPorts.configure(values=self.port_list)
        self.cbSerialPorts.configure(textvariable=self.serialports)
        self.cbSerialPorts.configure(takefocus="")
        self.cbSerialPorts.configure(state="readonly")
        self.cbSerialPorts.bind("<<ComboboxSelected>>", lambda e: self.focus())
        self.cbSerialPorts.current(0)

        self.frame3 = tk.Frame(self, width=10)
        self.frame3.grid(row=2, column=5)

        self.btnOpen = tk.Button(self)
        self.btnOpen.configure(activebackground="#ececec")
        self.btnOpen.configure(activeforeground="#000000")
        self.btnOpen.configure(background="#d9d9d9")
        self.btnOpen.configure(disabledforeground="#a3a3a3")
        self.btnOpen.configure(foreground="#000000")
        self.btnOpen.configure(highlightbackground="#d9d9d9")
        self.btnOpen.configure(highlightcolor="black")
        self.btnOpen.configure(pady="0")
        self.btnOpen.grid(row=2, column=6)
        self.btnOpen.bind('<ButtonRelease-1>', lambda e: self.after(1, self.btnOpen_click))
        self.btnOpen.configure(text='''Open''')

        self.frame4 = tk.Frame(self, width=10)
        self.frame4.grid(row=2, column=7)

        self.btnClose = tk.Button(self)
        self.btnClose.configure(activebackground="#ececec")
        self.btnClose.configure(activeforeground="#000000")
        self.btnClose.configure(background="#d9d9d9")
        self.btnClose.configure(disabledforeground="#a3a3a3")
        self.btnClose.configure(foreground="#000000")
        self.btnClose.configure(highlightbackground="#d9d9d9")
        self.btnClose.configure(highlightcolor="black")
        self.btnClose.configure(pady="0")
        self.btnClose.configure(state='disabled')
        self.btnClose.grid(row=2, column=8)
        self.btnClose.bind('<ButtonRelease-1>', lambda e: self.after(1, self.btnClose_click))
        self.btnClose.configure(text='''Close''')

        self.frame5 = tk.Frame(self, width=10)
        self.frame5.grid(row=2, column=9)

        self.btnCustom = tk.Button(self)
        self.btnCustom.grid(row=2, column=10)
        self.btnCustom.configure(activebackground="#ececec")
        self.btnCustom.configure(activeforeground="#000000")
        self.btnCustom.configure(background="#d9d9d9")
        self.btnCustom.bind('<ButtonRelease-1>', lambda e: self.after(1, self.btnCustom_click))
        self.btnCustom.configure(disabledforeground="#a3a3a3")
        self.btnCustom.configure(foreground="#000000")
        self.btnCustom.configure(highlightbackground="#d9d9d9")
        self.btnCustom.configure(highlightcolor="black")
        self.btnCustom.configure(pady="0")
        self.btnCustom.configure(text='''Custom''')
empty Sig
Benutzeravatar
__blackjack__
User
Beiträge: 12984
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@harryberlin: Weil andere Auflösungen bedeutet, dass die Schrift mehr oder weniger Pixel braucht, Du den Platz und die Position für die Elemente mit Texten aber in Pixeln fest vorgibst, funktioniert das halt nicht wirklich.

WTF? Man muss column-Werte anpassen wenn man eine Spalte einfügen will? Da ist es wirklich viel einfacher Pixelpositionen von allen Elementen neu auszurechnen wenn man mit `place()` arbeitet und eine neue Spalte oder Zeile einfügen will.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Sirius3
User
Beiträge: 17703
Registriert: Sonntag 21. Oktober 2012, 17:20

Warum braucht Du denn Spacer?
Das grid sorgt von selbst dafür, dass Elemente richtig angeordnet werden. Zur Not gibt es Padding.

Warum benutzt Du <ButtonRelease-1> und after? Ereignisfunktionen bei Knöpfen gibt man mit command an.

Ich halte es auch für falsch, alle Farben vorgeben zu wollen. Der Nutzer möchte z.B. das Farbschema gerne selbst angeben, zum Beispiel hoher Kontrast, Und auch sonst würde man alle Konfigurationen gleich beim Erzeugen angeben.

Und schon wird aus dem Codemonster was schön übersichtliches:

Code: Alles auswählen

class App(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.port_list = ['Select Device...',]

        self.avr = tk.Radiobutton(self, text='AVR', value='0', indicatoron="0", command=self.avr_clicked)
        self.avr.grid(row=0, column=0)

        self.ibus = tk.Radiobutton(self, text='IBus', value='1', indicatoron="0", command=self.ibus_clicked)
        self.ibus.grid(row=0, column=1)

        self.serialports = tk.StringVar(self)
        serialports_combobox = ttk.Combobox(self, values=self.port_list, textvariable=self.serialports, state='readonly')
        serialports_combobox.grid(row=0, column=2, padx=10)
        serialports_combobox.bind("<<ComboboxSelected>>", self.focus)
        serialports_combobox.current(0)
        tk.Button(self, text='Open', command=self.open_button_clicked).grid(row=0, column=3)
        tk.Button(self, text='Close', command=self.close_button_clicked, state=tk.DISABLED).grid(row=0, column=4)
        tk.Button(self, text='Custom', command=self.custom_button_clicked).grid(row=0, column=5)
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

Also gut, ich schau mal, ob ich es auf grid ummünze.

Zu den Fragen:
WTF? Ja, finde ich schon.
padx, pady ist des rätsels lösung für die 'spacer'
Mit den Farben hast du recht. Da kann man noch einiges von Page raus nehmen.
<ButtonRelease-1> und after? Weil der Button sonst eingerastet bleibt, bis der befehl durchlaufen ist.

Wie kann ich es mit grid bewerkstelligen, dass sich einige elemente beim Window resize bewegen oder vergrößern, oder auch unterschiedliche Layouts, die ich aktuell über das Menu 'Layout' aufrufe:
Bild

Bild

Bild

Bild

Bild

Bild
empty Sig
Benutzeravatar
__blackjack__
User
Beiträge: 12984
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@harryberlin: Und was ist das Problem dabei das der Button ”eingerastet” bleibt? Solange blockiert ja auch generell die GUI komplett. Dann weiss man wenigstens welche Aktion ist ist die da blockiert und wann die fertig ist. Das ist eine *gewollte*, sinnvolle Rückmeldung an den Nutzer. Und Du machst nicht nur das kaputt, sondern auch noch anderes Verhalten was Nutzer von Schaltflächen erwarten.

Die Empfehlung zu `grid()` meint übrigens nicht das Du den gesamten Fensterinhalt in *ein* Grid stecken solltest. Und für Teile kann man auch gerne `pack()` benutzen.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

Diese Verhalten (hängen von Tasten und gui blockieren) ist völlig ungewohnt, was mir bisher auf keiner Platform so vorkam.
Sollte aus meiner Sicht nur passiern, wenn da wirklich was schief läuft bzw. hängt und nicht normal ist.
empty Sig
Benutzeravatar
__blackjack__
User
Beiträge: 12984
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@harryberlin: Was wären denn das für Plattformen, denn das ist bei PC-Betriebssystemen völlig normales erwartbares verhalten das Rückruffunktionen nur ganz kurz etwas machen dürfen weil sie sonst die GUI blockieren. Und es hängt da ja auch dann auch *wirklich* etwas.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
DeaD_EyE
User
Beiträge: 1011
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

harryberlin hat geschrieben: Montag 29. März 2021, 19:14 Du meinst vermutlich den Thread hier:
viewtopic.php?t=42636

Da stellt sich mir nur die Frage, welche Daseinsberechtigung hat 'place()', wenn es böse ist.
Ich versuch es jetzt mal mit anderen ttkthemes. Mal schaun, ob das dem Ziel näher kommt.
Auch Entwickler einer Sprache/Framework sind nur Menschen und keine Götter. Die machen auch mal Fehler.
Außerdem hat man erst über die Jahre gelernt, wie man GUIs so gestaltet, dass diese unabhängig vom der Größe der Anzeige sind.
Ab dem Punkt wusste man, dass eine Sache nicht mehr kann: Absolut positionieren

Ich würde es mit einem Grid machen. Bei so vielen Feldern ist es auch schon die Überlegung wert, ein modernes GUI Framework zu verwenden.

Das Framework tkinter hat noch einige historische Überbleibsel.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

@blackjack
Windows lastige Anwednugnen wie z.B. VB6, oder VBA in Excel oder einfache HTML Buttons, aber auch richtige Hardwaretaster am Autoradio, starten oft das event nach dem Release.
Z.B. das Öffnen oder Schließen der Serialverbindung dauert etwas. Ein hänger der gui vermittelt mir, dass etwas nicht stimmt, ggf. sogar gleich abstürzt. Zumal tkinter eh so empflindlich scheint. Oder ist es da egal, wenn das Event länger läuft?
Macht es Sinn, das Button-Command nur zu nutzen, um das Ausführen der eigentlichen Funktion in die queue zu puten?

@dead_eye
Welches Framework würde sich anbieten?
Mein Ziel ist, alles in einem python script mit einer Sprache (python) umzusetzen.
Als Einstieg fand ich Page relativ gut, da man gut verfolgen kann, wie etwas zusammen hängt.
empty Sig
Sirius3
User
Beiträge: 17703
Registriert: Sonntag 21. Oktober 2012, 17:20

Für VBA habe ich getestet, dass dem nicht so ist. Das ist auch eigentlich egal, weil man einfach das Standardverhalten des jeweiligen Frameworks nehmen sollte und nicht irgendein unübliches Verhalten simulieren.
Und alle GUIs haben das selbe Verhalten, dass solange ein Event-Handler ausgeführt wird, die GUI einfriert. Das ist also auch nichts tkinter-spezifisches.
Und ja, für lang laufenden Code macht es sinn, mit dem Button-Command nur ein weiteres Ereignis abzusetzen.
Benutzeravatar
DeaD_EyE
User
Beiträge: 1011
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Dann müsste ich dir etwas empfehlen, dass ich bis jetzt selbst noch nicht eingesetzt habe: QT5/QT6.

Damit kann man professionell aussehende GUI Anwendungen entwickeln. Die Einstiegshürde ist höher als bei TK.
Der Teamspeak 3 Client verwendet z.B. das QT-Framework.

Man kann mit dem QT designer ein Layout erstellen, programmieren muss man aber trotzdem noch.

PS: Falls du dein Programm später kostenpflichtig anbieten willst, fallen bei QT Lizenzgebühren an. Für OpenSource ist die Nutzung kostenlos.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Benutzeravatar
sparrow
User
Beiträge: 4144
Registriert: Freitag 17. April 2009, 10:28

@DeaD_Eye: Dem PS muss ich widersprechen. Kostenpflichtig und Opensource schließen sich nicht aus. Und wann bei Qt Lizenzgebühren anfallen, ist gar nicht so einfach zu beantworten.
Benutzeravatar
DeaD_EyE
User
Beiträge: 1011
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

sparrow hat geschrieben: Mittwoch 7. April 2021, 21:18 Und wann bei Qt Lizenzgebühren anfallen, ist gar nicht so einfach zu beantworten.
Stimmt.

Ich glaube, wenn das Programm proprietär ist, dann fallen Lizenzgebühren an.
Teamspeak wird auch Lizenzen bezahlen.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Antworten