Fenstergröße paßt sich nicht an auf Raspberry Pi3 nach columnconfigure und rowconfigure innerhalb mainloop

Fragen zu Tkinter.
Antworten
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Das passiert mit python 3.4.2 und tkinter 8.6 auf Ubuntu mit tkinter 8.6 passiert es aber nicht.

Wenn man hier mit dem Button "Create ON" in das zweite Fenster "Create Widgets" wechselt, dann wird beim zweiten Fenster meist schon beim ersten Mal nicht die Größe angepaßt.

Wenn doch und man geht im zweiten Fenster wieder auf das erste mit dem Button "Back", dann geschieht eben beim zweiten Mal. Kleinere Fenster sind kein Ptroblem, aber bei größeren geschieht es.

Ich habe einen Workaround gemacht mit after und dann einen Anwendungsfenster Refresh durch withdraw, geometry(nur position) und deiconify aber schön ist dieses kurze Flackern nicht.

Beispielcode:

Code: Alles auswählen

import tkinter as tk

def content_1(master):

    tk.Grid.rowconfigure( master, 0,minsize=12)
    tk.Grid.rowconfigure( master, 1,minsize=23)
    tk.Grid.rowconfigure( master, 2,minsize=25)
    tk.Grid.rowconfigure( master, 3,minsize=25)
    tk.Grid.rowconfigure( master, 4,minsize=25)
    tk.Grid.rowconfigure( master, 5,minsize=25)
    tk.Grid.rowconfigure( master, 6,minsize=25)
    tk.Grid.rowconfigure( master, 7,minsize=25)
    tk.Grid.rowconfigure( master, 8,minsize=25)
    tk.Grid.rowconfigure( master, 9,minsize=11)
    tk.Grid.rowconfigure( master, 10,minsize=21)
    tk.Grid.rowconfigure( master, 11,minsize=16)
    tk.Grid.rowconfigure( master, 12,minsize=12)

    tk.Grid.columnconfigure( master, 0,minsize=16)
    tk.Grid.columnconfigure( master, 1,minsize=75)
    tk.Grid.columnconfigure( master, 2,minsize=75)
    tk.Grid.columnconfigure( master, 3,minsize=75)
    tk.Grid.columnconfigure( master, 4,minsize=75)
    tk.Grid.columnconfigure( master, 5,minsize=75)
    tk.Grid.columnconfigure( master, 6,minsize=75)
    tk.Grid.columnconfigure( master, 7,minsize=75)
    tk.Grid.columnconfigure( master, 8,minsize=12)

    master.Label = tk.Label(master,**{'text': 'GuiDesigner after Start', 'font': 'TkDefaultFont 12 bold', 'fg': 'blue'})
    master.Label.grid(**{'columnspan': 3, 'column': 1, 'row': 1, 'sticky': 'w'})
    master.Label_1 = tk.Label(master,**{'text': 'But here:', 'bg': 'white','anchor':'w', 'padx' : 7})
    master.Label_1.grid(**{'column': 1, 'row': 11, 'sticky': 'nswe'})
    master.LinkButton = tk.Button(master,**{'command' : master.master.call_content_2, 'text': 'Create ON', 'bd': '3', 'bg': 'green'})
    master.LinkButton.grid(**{'column': 2, 'row': 11, 'sticky': 'nesw'})
    master.Message = tk.Message(master,**{'width': 550, 'text': "After you have started the GuiDesigner, it looks as you see above.\n\nThere is the Menu, the Path and the Selection Module. The path shows the Application and the Selection Module shows, it's empty.\n\nLet's change this.\n\nIn the Menu you see the entry 'Create ON'. So let's press it. Of course not in the photo image.\n", 'bg': 'white'})
    master.Message.grid(**{'columnspan': 7, 'column': 1, 'row': 10})
    master.designer_image = tk.Label(master,text="Hier soll ein PhotoImage sein")
    master.designer_image.grid(**{'columnspan': 7, 'column': 1, 'row': 3, 'rowspan': 6, 'sticky': 'nw'})

def content_2(master):


    def main_content(master):

        tk.Grid.rowconfigure( master, 0,minsize=11)
        tk.Grid.rowconfigure( master, 1,minsize=24)
        tk.Grid.rowconfigure( master, 2,minsize=13)
        tk.Grid.rowconfigure( master, 3,minsize=25)
        tk.Grid.rowconfigure( master, 4,minsize=11)
        tk.Grid.rowconfigure( master, 5,minsize=25)
        tk.Grid.rowconfigure( master, 6,minsize=13)
        tk.Grid.rowconfigure( master, 7,minsize=25)
        tk.Grid.rowconfigure( master, 8,minsize=10)
        tk.Grid.rowconfigure( master, 9,minsize=25)
        tk.Grid.rowconfigure( master, 10,minsize=8)
        tk.Grid.rowconfigure( master, 11,minsize=0)
        tk.Grid.rowconfigure( master, 12,minsize=0)

        tk.Grid.columnconfigure( master, 0,minsize=19)
        tk.Grid.columnconfigure( master, 1,minsize=300)
        tk.Grid.columnconfigure( master, 2,minsize=300)
        tk.Grid.columnconfigure( master, 3,minsize=19)
        tk.Grid.columnconfigure( master, 4,minsize=0)
        tk.Grid.columnconfigure( master, 5,minsize=0)
        tk.Grid.columnconfigure( master, 6,minsize=0)
        tk.Grid.columnconfigure( master, 7,minsize=0)
        tk.Grid.columnconfigure( master, 8,minsize=0)

        master.Back = tk.Button(master,**{'command': master.master.call_content_1, 'text': 'Back', 'bd': '3'})
        master.Back.grid(**{'row': 9, 'column': 1, 'sticky': 'w'})
        master.CreateFrame = Createframe(master)
        master.CreateFrame.grid(**{'row': 3, 'column': 1, 'columnspan': 2})
        master.Label = tk.Label(master,**{'font': 'TkDefaultFont 12 bold', 'text': 'Create Widgets', 'fg': 'blue'})
        master.Label.grid(**{'row': 1, 'column': 1, 'columnspan': 2, 'sticky': 'w'})
        master.Message = tk.Message(master,**{'width': 600, 'bg': 'white', 'text': "The Create Widget module lets you create widgets.\n\nThe buttons in the section 'Select Widget Type' let you select the class of the tkinter widget.\n\nIn the last line there are two special widgets, which don't exist in tkinter: LinkButton and LinkLabel. You just had pressed the button 'Create ON'. This was a LinkButton, which can be used as Next or Back button. The LinkLabel is just the same, but looks different.\n\nThe entry 'Name' shows the selected class type as default for the name. You should change this name. If you like to export the designed GUI as a python tkinter file, the name should be fitting for a variable name. But if you access the GUI via interface, then there are no restrictions for the name, besides, that it has to be a string. But you only can enter a string."})
        master.Message.grid(**{'row': 5, 'column': 1, 'columnspan': 2, 'sticky': 'ew'})
        master.Message_1 = tk.Message(master,**{'width': 600, 'anchor': 'w', 'font': 'TkDefaultFont 9 bold', 'bg': 'white', 'text': 'The module above is the original GuiDesigner module, so just try it.'})
        master.Message_1.grid(**{'row': 6, 'column': 1, 'columnspan': 2, 'sticky': 'nesw'})
        master.Message_2 = tk.Message(master,**{'width': 600, 'anchor': 'w', 'bg': 'white', 'text': "Do you think, it doesn't work, because it doesn't create a widget? But it works, it doesn't create a widget, but informs another module to create the widget."})
        master.Message_2.grid(**{'row': 7, 'column': 1, 'columnspan': 2, 'sticky': 'ew'})
        master.Next = tk.Button(master,**{'text': 'Next', 'bd': '3', 'state' : 'disabled'})
        master.Next.grid(**{'row': 9, 'column': 2, 'sticky': 'e'})


    class Createframe(tk.Frame):

        def __init__(self,master,**kwargs):
            tk.Frame.__init__(self,master,**kwargs)
            self.CreateWidget = Createwidget(self,**{'text': 'Create Widget'})
            self.MenuEntryTypes = Menuentrytypes(self,**{'text': 'Select Widget Type'})
            self.SelectType = Selecttype(self,**{'text': 'Select Widget Type'})
            self.CreateWidget.pack(**{'fill': 'x', 'anchor': 'n', 'ipady': 4})
            self.SelectType.pack()

    class Createwidget(tk.LabelFrame):

        def __init__(self,master,**kwargs):
            tk.LabelFrame.__init__(self,master,**kwargs)
            self.Create = tk.Button(self,**{'pady': '1', 'padx': '1', 'bg': 'green', 'text': 'Create', 'bd': '3'})
            self.Create.grid(**{'row': 0, 'column': 3, 'sticky': 'nes'})
            self.Label = tk.Label(self,**{'text': 'Class'})
            self.Label.grid(**{'row': 0})
            self.Label_1 = tk.Label(self,**{'text': 'Name'})
            self.Label_1.grid(**{'row': 1})
            self.Name = tk.Entry(self)
            self.Name.grid(**{'row': 1, 'column': 1, 'columnspan': 3, 'sticky': 'nesw'})
            self.Type = tk.Label(self,**{'font': 'TkDefaultFont 9 bold', 'bg': 'yellow', 'text': 'Button', 'fg': 'blue', 'relief': 'ridge'})
            self.Type.grid(**{'row': 0, 'column': 1, 'sticky': 'ew'})

    class Menuentrytypes(tk.LabelFrame):

        def __init__(self,master,**kwargs):
            tk.LabelFrame.__init__(self,master,**kwargs)
            self.cascade = tk.Button(self,**{'width': 9, 'text': 'cascade'})
            self.cascade.grid(**{'row': 1})
            self.checkbutton = tk.Button(self,**{'width': 11, 'text': 'checkbutton'})
            self.checkbutton.grid(**{'row': 0, 'column': 1})
            self.command = tk.Button(self,**{'width': 9, 'text': 'command'})
            self.command.grid(**{'row': 0})
            self.delimiter = tk.Button(self,**{'width': 11, 'text': 'delimiter'})
            self.delimiter.grid(**{'row': 2, 'column': 1})
            self.radiobutton = tk.Button(self,**{'width': 11, 'text': 'radiobutton'})
            self.radiobutton.grid(**{'row': 1, 'column': 1})
            self.separator = tk.Button(self,**{'width': 9, 'text': 'separator'})
            self.separator.grid(**{'row': 2})

    class Selecttype(tk.LabelFrame):

        def __init__(self,master,**kwargs):
            tk.LabelFrame.__init__(self,master,**kwargs)
            self.Button = tk.Button(self,**{'width': 10, 'text': 'Button'})
            self.Button.grid(**{'row': 0, 'column': 2})
            self.Canvas = tk.Button(self,**{'width': 10, 'text': 'Canvas'})
            self.Canvas.grid(**{'row': 4, 'column': 2})
            self.Checkbutton = tk.Button(self,**{'width': 10, 'text': 'Checkbutton'})
            self.Checkbutton.grid(**{'row': 1})
            self.Entry = tk.Button(self,**{'width': 10, 'text': 'Entry'})
            self.Entry.grid(**{'row': 1, 'column': 2})
            self.Frame = tk.Button(self,**{'width': 10, 'text': 'Frame'})
            self.Frame.grid(**{'row': 3, 'column': 2})
            self.Label = tk.Button(self,**{'width': 10, 'text': 'Label'})
            self.Label.grid(**{'row': 0, 'column': 1})
            self.LabelFrame = tk.Button(self,**{'width': 10, 'text': 'LabelFrame'})
            self.LabelFrame.grid(**{'row': 4})
            self.LinkButton = tk.Button(self,**{'width': 10, 'text': 'LinkButton'})
            self.LinkButton.grid(**{'row': 6})
            self.LinkLabel = tk.Button(self,**{'width': 10, 'text': 'LinkLabel'})
            self.LinkLabel.grid(**{'row': 6, 'column': 1})
            self.Listbox = tk.Button(self,**{'width': 10, 'text': 'Listbox'})
            self.Listbox.grid(**{'row': 3})
            self.Menu = tk.Button(self,**{'width': 10, 'text': 'Menu'})
            self.Menu.grid(**{'row': 5})
            self.Menubutton = tk.Button(self,**{'width': 10, 'text': 'Menubutton'})
            self.Menubutton.grid(**{'row': 5, 'column': 1})
            self.Message = tk.Button(self,**{'width': 10, 'text': 'Message'})
            self.Message.grid(**{'row': 0})
            self.PaintCanvas = tk.Button(self,**{'width': 10, 'font': 'TkDefaultFont 9 bold', 'activeforeground': 'blue', 'text': 'Paint Canvas', 'fg': 'blue'})
            self.PanedWindow = tk.Button(self,**{'width': 10, 'text': 'PanedWindow'})
            self.PanedWindow.grid(**{'row': 4, 'column': 1})
            self.Radiobutton = tk.Button(self,**{'width': 10, 'text': 'Radiobutton'})
            self.Radiobutton.grid(**{'row': 1, 'column': 1})
            self.Scale = tk.Button(self,**{'width': 10, 'text': 'Scale'})
            self.Scale.grid(**{'row': 2, 'column': 2})
            self.Scrollbar = tk.Button(self,**{'width': 10, 'text': 'Scrollbar'})
            self.Scrollbar.grid(**{'row': 3, 'column': 1})
            self.Spinbox = tk.Button(self,**{'width': 10, 'text': 'Spinbox'})
            self.Spinbox.grid(**{'row': 2, 'column': 1})
            self.Text = tk.Button(self,**{'width': 10, 'text': 'Text'})
            self.Text.grid(**{'row': 2})
            self.Toplevel = tk.Button(self,**{'width': 10, 'text': 'Toplevel'})
            self.Toplevel.grid(**{'row': 5, 'column': 2})

    main_content(master)

def destroy_children(master):
    for child in master.winfo_children():
        child.destroy()

class Application(tk.Tk):

    def __init__(self,**kwargs):
        tk.Tk.__init__(self,**kwargs)
        self.title('Application Window')

        self.inside = tk.Frame(self)
        self.inside.pack()
        content_1(self.inside)

    def call_content_1(self):
        destroy_children(self.inside)
        content_1(self.inside)

    def call_content_2(self):
        destroy_children(self.inside)
        content_2(self.inside)


Application().mainloop()
PS: könnte auch ein Timingproblem sein, daß columnconfigure und rowconfigure oft erst völlig wirksam werden - Größe des Anwendungsfensters, wenn das Fenster schon dargestellt wurde - bei der Verwendung innerhalb mainloop
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Hab eine Lösung gefunden.

bei call_content_1 und call_content_2 noch anfügen:

Code: Alles auswählen

        self.inside.pack_forget()
        self.after(100,self.inside.pack)
Benutzeravatar
pillmuncher
User
Beiträge: 1482
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@Alfons Mittelmeyer: Wozu die ganzen ** ?
In specifications, Murphy's Law supersedes Ohm's.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@pillmuncher: das ist Alfons' ganz spezieller GUI-Editor, der kann nur so.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

pillmuncher hat geschrieben:@Alfons Mittelmeyer: Wozu die ganzen ** ?
Das sind die Dictionarys, die ich mit config() oder grid_info() bekomme, wobei die Daten mit Defaultwerten herausgelöscht sind. Ich habe noch nicht implementiert, daß daraus noch die gewohnte Schreibweise generiert wird. Es handelt sich um generierte Daten aus meinem GuiDesigner.

Könnte ich ja noch implementieren, ist ja nicht schwierig: **{ vorne weglassen, vom key die String limiter entfernen, das : durch = ersetzen und hinten die geweifte Klammer auch weglassen.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Habe endlich eine stabile Lösung gefunden, nämlich grid_remove für enen Container mit grid Layout, gefolgt von after mit grid.
Schön ist dieses Flackern nicht, besonders nicht für Systeme die dieses Problem nicht haben und bei denen es das nicht bräuchte.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Sirius3 hat geschrieben:@pillmuncher: das ist Alfons' ganz spezieller GUI-Editor, der kann nur so.
Naja, läßt sich ja ändern:

Code: Alles auswählen

a = {'columnspan': 3, 'column': 1, 'row': 1, 'sticky': 'w'}

def convert_save(dictionary):
    b=""
    for key,value in dictionary.items():
        b+=key + "="+repr(value)+","
    return b[0:-1]
        
print(convert_save(a))
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@Alfons Mittelmeyer: das läßt sich leicht einfacher schreiben, mit sinnvolleren Namen:

Code: Alles auswählen

def generate_keyvalues(dictionary):
    result = []
    for key, value in dictionary.items():
        result.append("{}={!r}".format(key, value))
    return ", ".join(result)

a = {'columnspan': 3, 'column': 1, 'row': 1, 'sticky': 'w'}
print(generate_keyvalues(a))
Antworten