Gui Designer auf GitHub

Fragen zu Tkinter.
BlackJack

@Alfons Mittelmeyer: Natürlich ändert sich was wenn Du explizit nur `tkinter.TclError` behandelst. Du siehst dann alle anderen Ausnahmen mit denen Du nicht rechnest mit Traceback. Das Du damit nicht rechnest heisst ja nicht das es sie nicht gibt. Wenn man sich mal nur die Methoden ansieht kann da *jede* Ausnahme kommen die es unter der Sonne gibt, nicht nur der `AttributeError` (nicht `NameError`) falls jemand eine der Methoden entfernt hätte.

Alleine ein `MemoryError` ist eine Ausnahme die man in der Regel gar nicht sinnvoll behandeln kann, schon gar nicht durch ignorieren, weil das Problem ja nicht weggehen wird.

Jede beliebige Ausnahme kann deswegen auftreten weil dort Objekte an Tk übergeben werden und die für Tk in Zeichenketten umgewandelt werden (müssen). Und dabei kann je nach Objekt alles mögliche an Ausnahmen auftreten.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

@BlackJack und andere: *seufz* Als wenn man gegen eine Wand redete...

@Alfons: IdR. vermeide ich auch "immer" und "nie", denn in der Tat geht es meist eher um Prinzipien und nicht um absolut gültige Reglen (<Sexismus Modus> Wer eine Freundin hat, weiß wovon ich rede, denn die Worte "immer" und "nie" sind bei Streitereien mit dem weibichen Geschlecht offenbar sehr beliebt und fallen "immer" :mrgreen: </Sexismus Modus>)

Aber: Ich schrieb "eigentlich" - das ist imho Einschränkung genug an der Stelle. Wer in eine Situation kommt, in der man eine Ausnahme davon machen kann, der ist so gut, dass er weiß, was er tut. Das ist bei Dir übrigens noch nicht der Fall, denn bei Dir liegt eine andere Situation vor und Du zeigst fortwährend, dass Du den Sinn von Exceptions immer noch nicht verstanden hast!

Mich stört an Dir Thread übergreifend folgendes: Du "entdeckst" ein Dir total sinnvoll erscheinendes Muster und wendest es dann auf Teufel komm raus an. Wenn man Dir dann Schwächen oder Fehler daran nennt, stellst Du Dich zunächst überhaupt nicht in Frage und vertraust darauf, dass viele Regulars hier deutlich mehr Wissen und Erfahrung bezüglich Python haben als Du, und Dir folgerichtig *richtige und gute* Tipps geben, sondern Du verteidigst Deine Idee auf Teufel komm raus und suchst Quellen, die (vermeindlich) belegen, was Du behauptest. Denkst Du wirklich, dass Du Dich damit sinnvoll verbessern wirst?

Auch ein Albert Einstein hat die Grundlagen der Physik durch das Wissen von anderen gelernt, wie alle Schüler dieser Welt. Erst später hat er neue Ideen formuliert, die bis dato keiner hatte. Hingegen sind Leute, die das Rad komplett neu erfinden und sogar verbessern aufgrund von Isolation oder dem nicht vorhandenen Zugang zu Bildung, *extrem* selten. Zudem gehörst Du ja nicht zu letzteren, wie Deine aktive Teilnahme in diesem Forum beweist. Bleibt also nur der erste Fall...

Als intelligenter Mensch sollte man folgerichtig leicht zur Einsicht gelangen, dass man leichter und sicherer vorankommt, wenn man auf Ratschläge von anderen zurückgreift! Dabei muss man auch nicht alles als Gott gegeben hinstellen; kritisch hinterfragen sollte man Dinge durchaus. Aber dazu gehört es zunächst, diese Dinge genau zu durchleuchten und deren Intention zu verstehen. Mindestens diesen letzten Schritt machst Du sehr selten, wenn überhaupt einmal!

Und das nervt so gewaltig!

Natürlich könnte man das auch ignorieren, aber leider lesen hier ja auch nicht registrierte Menschen mit bzw. könnte falsche Aussagen finden und sich diesen Mist selber aneignen. Und das muss man eben verhindern, was leider nur durch eine aktive Teilnahme zu erreichen ist. Wäre das nicht der Fall, wären solche Threads von Dir wesentlich kürzer und eher Monologe - denn wer mag es schon wirklich, sture und beratungsresistente Menschen zu überzeugen? Ich glaube davon gibt es nicht allzu viele Regulars hier...
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Hyperion hat geschrieben:Das ist bei Dir übrigens noch nicht der Fall, denn bei Dir liegt eine andere Situation vor und Du zeigst fortwährend, dass Du den Sinn von Exceptions immer noch nicht verstanden hast!
Natürlich hat alles seinen Sinn. Python Programmmierer sind gewohnt, dass Python ihnen Fehler anzeigt und die wollen dass die auch immer angezeigt werden. C Programmierer sind gewohnt, dass sie eine Exception nur bekommen, wenn sie durch 0 teilen oder in einen geschützten Speicherbereich schreiben oder den Speicher zum Überlauf gebracht haben. Assembler Programmierer sind gewohnt, dass sie leicht einen Systemabsturz bekommen, wenn sie etwa statt in den Kodebereich in Daten springen, die der Prozessor natürlich nicht richtig als Programm ausführen kann.

Und ich bin gewohnt, Programme fast immer fehlerfrei so zu schreiben, dass sie funktionieren. Allerdings hat mein GUI Designer, da ein paar Stellen noch nicht ganz fertig sind, noch Fehler. Habe etwa die Laderoutine geändert, die nun eine main-Funktion erwartet und die save-Routine noch nicht nachgezogen. Also ein paar Baustellen, sind da noch. Und Überarbeitung ist noch nötig.

Es gibt auch Programmierer die soweit gehen:

Code: Alles auswählen

a = 5
if a != 5:
    print("Error: a = ",a," instead of 5")
Es gibt also auch übertriebene Fehlerbehandlung. Wo ist da der Mittelweg? Ich sehe natürlich ein, dass solche Exceptions und die empfohlene Behandlung schon sinnvoll sind, und an den besagten Stellen könnten natürlich schon Fehler auftreten, wenn etwa statt einem Widget eine Referenz auf etwas anderes übergeben wird. Und viele programmieren sehr unsauber, dass so etwas des Öfteren passiert. Also mache ich es eben auch so, zufrieden?
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Alfons Mittelmeyer hat geschrieben:Und ich bin gewohnt, Programme fast immer fehlerfrei so zu schreiben, dass sie funktionieren.
Das ist ja direkt Comedygold. Die Art und Weise wie du da Exceptions handhabst ist gerade ein Beispiel, dass du fehlerhafte Programme schreibst.

Wenn du nur eine bestimme Art von Exception erwartest und/oder behandeln kannst, dann behandelst du nur diese bestimmte Art. *Alles andere* ist fehlerhafter und unsauber programmierter Code.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

cofi hat geschrieben:
Alfons Mittelmeyer hat geschrieben:Und ich bin gewohnt, Programme fast immer fehlerfrei so zu schreiben, dass sie funktionieren.
Das ist ja direkt Comedygold. Die Art und Weise wie du da Exceptions handhabst ist gerade ein Beispiel, dass du fehlerhafte Programme schreibst.
Nein das ist kein Beispiel für fehlerhaft. Das ist ein Beispiel, dass ich ganz gut auf jede Art von Fehlermeldung verzichten kann. Oder meinst Du ich hätte irgendeine Fehlermeldung bekommen, als ich mal ein Arztpraxisverwaltungsprogramm in Assembler geschrieben hatte?

Das heißt auf alle Fehlermeldungen kann man natürlich nicht verzichten. Syntaxfehler muss ein Compiler oder Assembler melden. Und das erwarte ich auch von Python.
BlackJack

@Alfons Mittelmeyer: Du denkst Du kannst auf Fehlermeldungen verzichten weil Du hier unter grenzenloser Selbstüberschätzung leidest. *Kein* Programmierer kann auf die Meldung von Fehlern verzichten mit denen er nicht rechnet wenn er saubere Programme schreiben will.

Das bestimmte Sprachen keine besondere Unterstützung für Fehler- und Ausnahmesituationen bieten ist kein Argument, denn genau in diesen Sprachen ist es deswegen ja auch so schwer Fehler zu finden und oft überhaupt zeitnah zu bemerken.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@BlackJack Ich leide nicht an grenzenloser Selbstüberschätzung, ich bin nur Spezialist im Fehlerfinden. Und ich weiss, dass sich da andere sehr schwer tun. Ich habe mal ein Projekt gemacht. Beim Nachfolgeprojekt waren es dann zehn Programmierer und die haben länger gebraucht, als ich vorher allein. Und ich war hauptsächlich damit beschäftigt, ihnen ihre Fehler mitzuteilen, die sie selber nicht gefunden haben. Statt die einfach kurzerhand rauszumachen, mußte ich Ihnen emails schreiben und ihnen klar machen, wo die Fehler sind, denn es war ja ihr Code.

Und statt über drei exceptions oder Sternchenimporte zu sprechen, sollte mann sich auf wirkliche Fehler konzentrieren.

Heute ging mein Programm nicht, Da hatte ich noch einen Murks reingemacht: if tkClass() == "PanedWindow" statt if tkClass == tk.PanedWindow
Und bekomme ich da eine Exception? Nein! Da wundert man sich nur, dass da ständig ein neues tkinter Fenster aufgeht.

Und was ist mit 'Problem: beim 2. Sash nimmt tkinter die Koordinaten nicht' anscheinend interessieren echte Fehler niemanden. Und wenn ein User ein fehlerhaftes Programm hat, was schreibt Ihr ihm dann?

Sternchenimporte soll man nicht machen, vier Leerzeichen einrücken statt Tab, Klassen nehmen, Exceptions richtig behandeln, gute Namenswahl. Also meist nichts von dem, was der Fehler ist, oder wie das Problem gelöst werden kann.

Mit vier Leerzeichenn statt Tab geht der Fehler sicher nicht weg, mit anderer Namenswahl auch nicht!
BlackJack

@Alfons Mittelmeyer: Auch wenn man Spezialist im Fehlerfinden ist, macht es keinen Sinn Fehlermeldungen mit denen man nicht rechnet, mutwillig zu unterdrücken. Das an sich ist ein Fehler, den Du offensichtlich nicht siehst obwohl Du doch Spezialist im Fehlerfinden bist. Insbesondere verstehe ich nicht warum man sich da so hartnäckig gegen sträuben muss es richtig zu machen, wenn das doch so verdammt *einfach* ist.

Sich an Konventionen zu halten hilft bei der Kommunikation. Leerzeichen statt Tabulatorzeichen verhindern schwer sichtbare Einrückfehler, und gute Namenswahl verhindert in sofern Fehler, als dass einem leichter auffällt wenn man etwas unsinniges macht, weil sich der Code dann in häufig einfach falsch ”anhört” wenn man ihn liest. Bei der Fehlersuche helfen gut gewählte Namen auch weil man von dem zusätzlichen Schritt kryptische Namen im Kopf erst auf die eigentliche Bedeutung abzubilden, befreit ist und man sich mehr auf das eigentliche Problem konzentrieren kann. Zudem ist es oft ein Zeichen das man etwas noch nicht richtig durchdacht hat wenn es schwer fällt einen passenden Namen für ein Objekt zu finden.

Klassen helfen Code sinnvoll zu strukturieren und Daten und Code zu kapseln, was Fehler vermeidet und bei der Fehlersuche hilfreich ist.

Ausnahmen sorgen dafür das man Fehler nicht übersehen kann weil sie in der Aufrufhierarchie nach oben weiter gereicht werden ohne das man etwas dafür tun muss, und gemeldet werden, wenn man sie nicht behandelt. Dadurch fallen eben jene Fehler auf mit denen man nicht gerechnet hat, wenn sie auftreten.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Neue GUI Designer Version auf Github: https://github.com/AlfonsMittelmeyer/py ... -messaging

Jetzt auch mit Menu und Menubutton. Damit ist es die erste Vollversion.

Bitte noch nichts runterladen, denn Github fetcht immer noch.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi Alfons

Noch ein kleiner Tipp betreffs den Layout Options padx und pady. Dies betrifft also nur die padx und pady, welche als Layout Options verwendet werden! Nebst dem symetrischen padding kann auch ein asymetrisches definiert werden.

Für symetrisches padding z.B.:
padx=4
pady=6

Für asymetrisches padding z.B:
padx=(4, 10)
pady=(2, 10)

Gruss wuf :wink:
Take it easy Mates!
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@wuf Danke, dass Du mir das mit dem asymmetrischen paddding schreibst, wollte nämlich schon Spinboxen statt Entries machen für folgende Einträge:

Code: Alles auswählen

Spinbox instead of Entry for Integers and Floats in Config Options and Layout Options:

Integers ind Floats in Config Options:

"from", # Spinbox (decimal default 0.0)
"to",   # Spinbox, Scale (decimal Spinbox default 0,0, Scale default 100.0)
"increment", # Spinbox, (decimal default 1.0)
"resolution", # Scale (decimal default 1.0)
"bigincrement", # Scale (decimal default 0.0)
"tickinterval", # Scale (decimal default 0.0)
"digits", # Scale (Integer default 0)
"underline", # Label, Button (Integer starting at -1)
"width", # often (Integer default 0)
"height", # often (Integer default 0)
"length", # Spinbox (Integer default 100)
"sliderlength", # Spinbox (Integer default 30)
"wraplength", # often (Integer default 0)
"padx", # often (Label: Integer default 0, Button ? default 3m)
"pady", # often (Label: Integer default 0, Button ? default 1m)
"bd", # often (Integer default 1)
"insertwidth", # Entry (Integer default 2)
"insertborderwidth", # Entry (Integer default 0)
"insertontime", # Entry (Integer default 600)
"selectborderwidth", # Entry (Integer default 0)
"sashwidth", # PanedWindow (Integer default 3)
"sashpad", # PanedWindow (Integer default 0)
"opaqueresize", # PanedWindow (Integer default 1)
"handlesize", # PanedWindow (Integer default 8)
"handlepad", # PanedWindow (Integer default 8)

Integers in Layout Options:

"x", # Place Layout
"y", # Place Layout
"column", # Grid Layout
"row", # Grid Layout
"columnspan", # Grid Layout (Integer default 1)
"rowspan", # Grid Layout (Integer default 1)
"width", # Place Layout (Default leer "" oder Integer)
"height", # Place Layout (Default leer "" oder Integer)
"expand", # Pack Layout (Integer default 0)
"padx", # Pack Layout und Grid Layout (Integer default 0)
"pady", # Pack Layout und Grid Layout (Integer default 0)
"ipadx", # Pack Layout und Grid Layout (Integer default 0)
"ipady", # Pack Layout und Grid Layout (Integer default 0)
"relx", # Place Layout (Integer default 0)
"rely", # Place Layout (Integer default 0)
"relwidth", # Place Layout (Default leer "" oder Integer)
"relheight",  # Place Layout (Default leer "" oder Integer)
Muss mir dazu noch überlegen: from, to, increment
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

wuf hat geschrieben:Hi Alfons
Noch ein kleiner Tipp betreffs den Layout Options padx und pady. Dies betrifft also nur die padx und pady, welche als Layout Options verwendet werden! Nebst dem symetrischen padding kann auch ein asymetrisches definiert werden.
Hi wuf. Hab gesehen, dass man das eingeben kann. Einfach zwei Werte mit Leerzeichen dazwischen.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi Alfons
Alfons Mittelmeyer hat geschrieben:Hi wuf. Hab gesehen, dass man das eingeben kann. Einfach zwei Werte mit Leerzeichen dazwischen.
Super! Funktioniert bestens. Habe zu wenig Varianten ausprobiert. Noch eine Frage. Bei der configuration von z.B. dem root-Fenster oder Frame verwendest du die Option link diese aber nicht bei z.B. Labels, Entries oder Checkboxes. Ich dachte zuerst es sei der Referenzname für die Instanz dieser Widgets die du dann in den Skripts verwendest um diese GUI-Widgets anzusprechen. Dann aber müsste die Option link aber doch für alle Widgets verfügbar sein?

Gruss wuf :wink:
Take it easy Mates!
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@wuf Nein, die Option 'link' gibt es nur für Container Widgets und sie bedeutet etwas völlig Anderes. Was denkst Du, was hier im Script Modules.py bassiert?

Code: Alles auswählen

Frame('CreateFrame',link="guidesigner/CreateFrame.py")
grid(sticky='n',row='0')

Frame('CreateAndLayout',link="guidesigner/CreateAndLayout.py")
grid(column='1',sticky='n',row='0')

LabelFrame("ConfigOptions",text="Config",link="guidesigner/ConfigOptions.py")
rcgrid(0,2,sticky=N)

Frame("DetailedLayout",link="guidesigner/DetailedLayout.py")
rcgrid(0,3,sticky=N)

LabelFrame("Selection",text="Selection",link="guidesigner/Selection.py")
rcgrid(0,4,sticky=N)

### CODE ===================================================

widget("ConfigOptions").unlayout()
widget("DetailedLayout").unlayout()

### ========================================================
Die Option 'link' lädt diese Scripts nach, füllt also den Inhalt der Frames und so lade ich den kompletten GUI Designer. - Sozusagen Script Import als Widget Option :wink:

Ich sollte dann auch die andere Save Routine - eigentlich dieselbe - wieder mit hineinnehmen - mit der man die Scripts zerteilen kann. Nur hatte die automatisch beim Speichern den Link gesetzt. Und dann war alles doppelt. Muss das automatische Link setzen herausnehmen sowohl beim Laden als auch beim Speichern. Soll man händisch machen.

Das Problem ist, wenn ein Script Links enthält, wird dann alles geladen und man soll die Widgets nicht speichern oder wird ein Teil der Widgets geladen? Aber welche soll man dann speichern?
Nö da habe ich noch einen Denkfehler drin, denn wenn man nur Inhalt des Containers nachlädt, dann gehören die Widgets ja nur zum Subcontainer und das Problem besteht nicht. Hatte nur gestern statt einen Container Inhalt den Container gespeichert. Und beim Reinladen war es dann doppelt.

Ist eigentlich lustig, wenn man etwa ein Menü entwirft und hat aber auch noch Anderes, dass man dann speziell nur das Menü speichert. Und das ist dann durch den Link abgetrennt in einer eigenen Datei.

Man sollte aber da noch die Entscheidung einbauen, nur diesen Teil speichern oder gleich dabei mit abtrennen.

Und bei den Expert Laderoutinen, die ich vorläufig herausgenommen habe, kann man dann auch gezielt Teile hereinladen. Das kann man aber auch, wenn man den Link manuell setzt. Allerdings speichere ich zur Zeit die Links nicht in der Nicht-Expert Save Funktion, sondern speichere alle Widgets.

Die Expert Save Funktion dagegen darf dann den betreffenden Subcontainer Inhalt nicht speichern, sondern nur einfach den Link. Dabei ist aber dumm, wenn jemand darin etwas geändert hat und von Anfang an speichert und sich dann wundert, wenn seine Änderungen nicht gespeichert wurden. Da hätte er den Container Inhalt extra noch speichern müssen.

Ohne Dokumentation sollte man diese Funktionen daher nicht anbieten, weil dann einer nicht weiss, was passiert und zerschießt sich vielleicht etwas und ärgert sich dann.

Manuell lange Scripts im Editor zerteilen macht aber auch keinen Spass. Mit der Save Funktion, die automatisch den Link setzt, geschieht es Ruck Zuck.
Zuletzt geändert von Alfons Mittelmeyer am Mittwoch 30. September 2015, 09:07, insgesamt 2-mal geändert.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi Alfons

Danke! Sorry jetzt hat es gedämmert. Du vergibst die Referenznamen ja beim erstellen der Widgets im Feld Create Widget in der Eingabe für Namen

Gruss wuf :wink:
Take it easy Mates!
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@wuf Ja, der erste Parameter ist der Widgetname, da wo normalerweise der Parent steht. DynTkInter kann aber auch den Parent Parameter als Parent behandeln und ist daher kompatibel mit tkinter Scripts.
Der Gui Designer kann allerdings noch keine tkinter Panels und Menüs erfassen. Da muss ich erst noch die betreffenden tkinter Methoden ergänzen..
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@wuf Bräuchte noch eine Lösung für padx und padx in den Config Options. Schön wäre auch da eine Spinbox. Nur da gibt es die Angabe in Pixel und Millimeter und wenn ich eine Spinbox nehme ist das 'm' weg.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi Alfons

Hier habe ich etwas zusammengebastelt. Schau es dir einmal an:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from functools import partial

try:
    # Tkinter for Python 2.xx
    import Tkinter as tk
    import tkFont as fnt
except:
    # Tkinter for Python 3.xx
    import tkinter as tk
    import tkinter.font as fnt

APP_TITLE = "Dimension-Creator"
APP_BACK_GND = "#d1d19d"
APP_XPOS = 100
APP_YPOS = 100
APP_WIDTH = 300
APP_HEIGHT = 200

DIMENSIONS = ('pixel', 'centimeter', 'inches', 'millimeter')
MIN_VAL = 0
MAX_VAL = 20

class DimensionValueCreator(tk.Spinbox):
    
    def __init__(self, parent, min_val, max_val, callback=None, **options):
        self.parent = parent
        self.min_val = min_val
        self.max_val = max_val
        self.value = 0
        self.unit = DIMENSIONS[0]
        self.callback = callback

        self.var = tk.StringVar()
        self.var.trace_variable('w', self.update_value)
        
        tk.Spinbox.__init__(self, parent, from_=min_val, to_=max_val,
            textvariable=self.var, **options)
        
    def set_value(self, value=0):
        if self.min_val <= value <= self.max_val:
            self.var.set('{} {}'.format(value, self.unit))
            self.value = value
    
    def set_unit(self, unit=''):
        if unit in DIMENSIONS:
            value = self.get_value_only()
            self.change_unit(unit)
            self.set_value(value)
            
    def get_value_only(self):
        mixed_value = self.get()
        value = int(mixed_value.replace(self.unit, ''))
        return value
                
    def change_unit(self, new_unit=''):
        old_unit = self.unit
        old_dim_value = self.var.get()

        new_dim_value = old_dim_value.replace(old_unit, new_unit)
        value = new_dim_value.replace(new_unit, '')
        self.unit = new_unit
                
    def update_value(self, *args):
        mixed_value = self.get()
        self.value = self.get_value_only()
        try:
            self.var.set('{} {}'.format(self.var.get(), self.unit))
        except AttributeError:
            return False
        else:
            self.creator_callback()
            return True        

    def creator_callback(self):
        if self.callback != None:
            self.callback(self.unit, self.value)
            
class Application(tk.Frame):

    def __init__(self, master):
        self.master = master
        self.master.protocol("WM_DELETE_WINDOW", self.close)
        tk.Frame.__init__(self, master)

        dim_value_frame = tk.LabelFrame(self, text="Dimension-Value")
        dim_value_frame.pack(expand=True)
        
        self.dimension_value_creator = DimensionValueCreator(dim_value_frame,
            MIN_VAL, MAX_VAL, callback=self.creator_callback, width=10,
                bg='khaki1')
        self.dimension_value_creator.pack(padx=4, pady=4)
        
        unit_frame = tk.LabelFrame(self, text="Test-Unit (Dimensions)")
        unit_frame.pack(expand=True)
        
        self.unit_spinbox = tk.Spinbox(unit_frame, values=DIMENSIONS,
            command=self.update_unit)
        self.unit_spinbox.pack(padx=4, pady=4)

        value_frame = tk.LabelFrame(self, text="Test-Value (padx & pady)")
        value_frame.pack(expand=True)

        self.value_spinbox = tk.Spinbox(value_frame, from_=0, to_=100,
            command=self.update_value)
        self.value_spinbox.pack(padx=4, pady=4)
    
    def creator_callback(self, unit, value):
        print(unit, value)
        
    def update_unit(self):
        unit = self.unit_spinbox.get()
        self.dimension_value_creator.set_unit(unit)
        
    def update_value(self):
        value = int(self.value_spinbox.get())
        self.dimension_value_creator.set_value(value)
        
    def close(self):
        print("Application-Shutdown")
        self.master.destroy()
    
def main():
    app_win = tk.Tk()
    app_win.title(APP_TITLE)
    app_win.geometry("+{}+{}".format(APP_XPOS, APP_YPOS))
    app_win.geometry("{}x{}".format(APP_WIDTH, APP_HEIGHT))
    
    app = Application(app_win).pack(fill='both', expand=True, padx=6, pady=6)
    
    app_win.mainloop()
 
 
if __name__ == '__main__':
    main()
N.B. Kann sicher noch optimiert werden.

Gruss wuf :wink:
Take it easy Mates!
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@wuf Danke, hast Dir da aber grosse Mühe gegeben. Ich habe mich heute mal mit dem Grid Konzept beschäftigt. Und zwar in Form einer sichtbaren Tabelle. Und man kann dann die Widgets einfach mit der Maus ziehen. Das sieht super aus. Zuvor muss ich allerdings noch ein wenig Konzeptänderung machen. Das Konzept bisher beim Place Layout war, dass man das Bewegen mit der Maus für einzelne Widgets ein und ausgeschaltet hatte.

Ich hatte gedacht, wenn jemand bereits Events drauf hat, sollte man sie nicht zerstören. Aber dieses Konzept muss jetzt geändert werden. Selektion mit der Maus und eventuell auch noch bewegen für alle Widgets im betreffenden Container, ob nun Pack oder Grid oder Place oder Pane - aber nicht bei Menüs, weil das dort nicht geht.

Dann kann man beliebig Widgets selektieren oder gar mit der Maus bei grid oder place verschieben.
Naja, das mit einer schönen Grid Implementierung gibt es bisher nirgends.

Ach übrigends habe ich heute bei Github die Änderung draufgespielt, dass es bei Zahlenwerten - bis auf wenige Ausnahmen - jetzt Spinboxen gibt.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Habe mir heute das neue Grid ausgedacht. Sollte nicht schwer zu verstehen sein:

Bild
Antworten