Wie bekomme ich grid_rowconfigure wieder weg?

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

Wuf, danke, das mit geometry('') hatte ich nicht gewusst. Das ist besser als alles neu laden und dann die urprüngliche Position nicht haben.

Die Lösung in TopMenu.py:

Code: Alles auswählen

#statt in Zeile 27
widget("Refresh").do_command(lambda: send('SELECTION_CHANGED',this()))

# das dafür nehmen:
def do_refresh():
    selection_before = Selection()
    gotoTop() # go into the TopRoot
    widget('DynTkInterGuiDesigner').geometry('') # refresh the geometry of the GUI Designer
    setSelection(selection_before)
    send('SELECTION_CHANGED') # refresh display of the current selection

widget("Refresh").do_command(do_refresh)
Sollte mal eine neue Funktion einführen, damit man nur eine Zeile schreiben braucht statt vier, etwa: widget('//DynTkInterGuiDesigner').geometry('')
Zuletzt geändert von Alfons Mittelmeyer am Freitag 2. Oktober 2015, 14:28, insgesamt 1-mal geändert.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi Alfons

Habe festgestellt, wenn das Fenster im Fullscreen-Modus ist klappt es nicht immer. Hier eine strengere Geometry-Refresh Massnahme:

Code: Alles auswählen

    def refresh(self, event):
        print('Refresh')
        self.master.geometry('')
        self.master.withdraw()
        #self.master.update_idletasks()
        self.master.geometry("+100+100")
        self.master.deiconify()
Gruss wuf :wink:
Take it easy Mates!
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Hi wuf, eine feste Größe von +100 würde ich aber nicht nehmen. Am Besten so, wie es zuvor war. Aber das Fenster hat ja oben eine Leiste. Deshalb klappt es so nicht ganz:

Code: Alles auswählen

def do_refresh():
    selection_before = Selection()

    gotoTop() # go into the TopRoot
    goto('DynTkInterGuiDesigner')
    x_location = this().winfo_rootx()
    y_location = this().winfo_rooty()
    this().geometry('') # refresh the geometry of the GUI Designer
    this().withdraw()
    this().geometry('+'+str(x_location)+'+'+str(y_location))
    this().deiconify()

    setSelection(selection_before)
    send('SELECTION_CHANGED') # refresh display of the current selection

widget("Refresh").do_command(do_refresh)
Da müsste man dann diese + aus der Geometry rauslesen und wieder setzen.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi Alfons

Code: Alles auswählen

master.geometry("+100+100")
Ist nicht die Grösse sondern nur die Position der oberen linken Fensterecke des Hauptfensters.

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

@wuf Das weiß ich doch, dass das die Position des Fenters ist, aber geometry und winfo unterscheiden sich, weil das eine links oben im Fenster und das andere links oben des Rahmens ist. Richtig ist daher:

Code: Alles auswählen

def do_refresh():
    selection_before = Selection()

    gotoTop() # go into the TopRoot
    goto('DynTkInterGuiDesigner')

    my_geo = this().geometry()
    find_plus = my_geo.find("+")
    find_minus = my_geo.find("-")
    if find_plus < 0: find_plus = 100000
    if find_minus < 0: find_minus = 100000
    my_geo = my_geo[min(find_plus,find_minus):]
    
    this().geometry('') # refresh the geometry of the GUI Designer
    this().withdraw()
    this().geometry(my_geo)
    this().deiconify()

    setSelection(selection_before)
    send('SELECTION_CHANGED') # refresh display of the current selection

widget("Refresh").do_command(do_refresh)
Oder statt mit 100000 besser so:

Code: Alles auswählen

def do_refresh():
    selection_before = Selection()

    gotoTop() # go into the TopRoot
    goto('DynTkInterGuiDesigner')

    my_geo = this().geometry()
    find_plus = my_geo.find("+")
    find_minus = my_geo.find("-")
    if find_plus < 0: begin = find_minus
    elif find_minus < 0: begin = find_plus
    else: begin = min(find_plus,find_minus)
    my_geo = my_geo[begin:]
    
    this().geometry('') # refresh the geometry of the GUI Designer
    this().withdraw()
    this().geometry(my_geo)
    this().deiconify()

    setSelection(selection_before)
    send('SELECTION_CHANGED') # refresh display of the current selection

widget("Refresh").do_command(do_refresh)
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi Alfons
Alfons Mittelmeyer hat geschrieben:Hi wuf, eine feste Größe von +100 würde ich aber nicht nehmen. Am Besten so, wie es zuvor war. Aber das Fenster hat ja oben eine Leiste. Deshalb klappt es so nicht ganz:
Alfons Mittelmeyer hat geschrieben:@wuf Das weiß ich doch, dass das die Position des Fenters ist, aber geometry und winfo unterscheiden sich, weil das eine links oben im Fenster und das andere links oben des Rahmens ist. Richtig ist daher:
Sorry da habe ich dich falsch verstanden. Hast du das neueste mit der Geometry in deiner GitHub Version schon integriert?

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

Nö wuf, hab es noch nicht integriert, aber kannst den Code ja selber in TopMenu.py statt Zeile 27 reintun.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi Alfons
Alfons Mittelmeyer hat geschrieben:Nö wuf, hab es noch nicht integriert, aber kannst den Code ja selber in TopMenu.py statt Zeile 27 reintun.
Danke! Bereits erledigt. Funktioniert bestens.

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

Aber nach wie vor ist mein Problem nicht gelöst.

Hier sieht man links oben einen Frame mit grid in einem grid des Main Windows. Es war eingestellt, 8 Zeilen 5 Spalten:

Bild

Nach Umstellung auf 4 Zeilen 4 Spalten bekomme ich:

Bild

Der graue Bereich war mit grid_rowconfigure und grid_columnconfigure definiert. Auch beim Mainwindow geht es nicht mehr weg.

Gibt es so etwas, wie ein grid_rowunconfigure und grid_columnunconfigure?
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Eine Möglichkeit ist natürlich: speichern und neu laden

Bild
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Hat sich erledigt. Brauch nur min width und min heigt wieder auf 0 setzen
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Hab die Änderungen wieder auf Github gepusht
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi Alfons

Welche Widgets verwendest du für die Tabellen-Elemente die du mit 'show' einblendest um weiter Widgets darauf zu platzieren? Sorry bin zu faul in deinen Skripten herumzustöbern.

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

Hi wuf, neugierig?

Ich benutze nur einen einfachen Label mit relief solid: {'height': '0', 'width': '0', 'relief': 'solid','bg':'#b3d9d9','padx':0,'pady':0}
Und mach dann ein grid mit sticky = 'news'

Ich schreibe 'news' statt so etwas wie 'nesw', denn das kann ich mir prima merken.

Einfach, aber wirkungsvoll, oder?
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi Alfons

Ich machte einen Versuch mit einem kleinen Skript, welches eine Tabelle mit Frames als Tabellen-Elemente erzeugte. Ich kann bei dieser Tabelle auch Reihen und Spalten mit Änderung deren Optionen width & height=0 zum verschwinde bringen. Die so unsichtbar gemachten Element bleiben aber bestehen. Man müsste eigendlich die Tabellen-Elemente (bei mir die Frame-Elemente) destroy'en. Ausser es stört in deinem Fall nicht.

N.B. Dein Tipp mit sticky='news' (genial!)

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

HI wuf, Du hast es erfaßt. Die Tabellenelemente muss man destroyen. In meinem Script geschieht das durch: deleteWidgetsForName(container(),NONAME)
Das macht ein destroy für alle Widgets im betreffenden Container, die den Namen NONAME haben. Und die zeige ich auch nicht im Selektions Teil an.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi Alfons

Hier noch mein erwähntes Testskript mit der Tabelle:

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 = "Testtabelle mit Frames"
APP_XPOS = 100
APP_YPOS = 100
APP_WIDTH = 300
APP_HEIGHT = 200

BUTTON_01 = 'Letzte horizontale\nReihe entfernen'
BUTTON_02 = 'Letzte vertikale\nKolonne entfernen'
BUTTONS = [BUTTON_01, BUTTON_02]
HORIZONTAL = 'horz'
VERTICAL = 'vert'

class SimpleTable(tk.Frame):
    def __init__(self, parent, rows, columns):
        self.parent = parent
        self.rows = rows
        self.columns = columns
        tk.Frame.__init__(self, parent, background="black")
        self.cells = []
        for row in range(rows):
            current_row = []
            for column in range(columns):
                frame = tk.Frame(self, borderwidth=1, width=200, height=30,
                   relief='raised')
                frame.grid(row=row, column=column, sticky="nsew")

                current_row.append(frame)
            self.cells.append(current_row)

        for column in range(columns):
            self.grid_columnconfigure(column, weight=1)
        
    def set(self, row, column, value):
        widget = self.cells[row][column]
        widget.configure(height=0)

    
    def remove_row(self, row=6):
        for label in self.cells[row]:
            label.config(height=0)
            label.update_idletasks()
 
    def remove_cells(self, direction):
        if direction == VERTICAL:
            # Remove last column on the right side of the table
            last_column = len(self.cells[0])
            last_row = len(self.cells)
            #print('Rows:', last_row)
            for row in range(last_row):
                print(row)
                self.cells[row][last_column-1].destroy()
                del self.cells[row][last_column-1:]
            #print(len(self.cells[0]))
                
        if direction == HORIZONTAL:
            # Remove last row on the botton side of the table
            last_column = len(self.cells[0])
            last_row = len(self.cells)
            #print('Columns:', last_column)
            for column in range(last_column):
                print(column)
                self.cells[last_row-1][column].destroy() #config(height=0)
            del self.cells[last_row-1:]
            #print(self.cells)
                
class Application(tk.Frame):

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

        self.table = SimpleTable(self, rows=7, columns=6)
        self.table.pack(side="top", fill="x")
        #table.set(0,0,"Hello, world")
        self.master.geometry('')

        button_frame = tk.Frame(self)
        button_frame.pack()
    
        [tk.Button(button_frame, text=button_text,
            command=partial(self.on_button_press, button_text)).pack(
                side='left', pady=5)
                    for button_text in BUTTONS]
    
    def on_button_press(self, button):
        if button == BUTTON_01:
            self.remove_cells(HORIZONTAL)
        if button == BUTTON_02:
            self.remove_cells(VERTICAL)
              
    def remove_cells(self, direction):
        self.table.remove_cells(direction)
        
    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)
    app.pack(fill='both', expand=True, padx=0, pady=0)
    
    app_win.mainloop()
 
 
if __name__ == '__main__':
    main()
Gruss wuf :wink:
Take it easy Mates!
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Hi wuf, noch ein Tipp: das lower nicht vergessen:

Code: Alles auswählen

        for row in range(rows):
            fill_cell = {'height': '0', 'width': '0', 'relief': 'solid','bg':'#b3d9d9','padx':0,'pady':0}
            for col in range(cols):
                Label(NONAME,**fill_cell).rcgrid(row,col,sticky='news')
                this().lower()
Wenn Du ein Widget drüberziehst, soll es ja darüber erscheinen und nicht dahinter versteckt sein.

Hab mir Deinen Code jetzt angeschaut. Wolltest ja gar nichts drüberziehen.
Zuletzt geändert von Alfons Mittelmeyer am Sonntag 4. Oktober 2015, 19:46, insgesamt 1-mal geändert.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Ok

Danke für den Tipp.

Gruss wuf :wink:
Take it easy Mates!
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi Alfons
Alfons Mittelmeyer hat geschrieben:Hab mir Deinen Code jetzt angeschaut. Wolltest ja gar nichts drüberziehen.
Aber hier ziehe ich etwas darüber:

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 = "Testtabelle mit Frames"
APP_XPOS = 100
APP_YPOS = 100
APP_WIDTH = 300
APP_HEIGHT = 200

BUTTON_01 = 'Letzte horizontale\nReihe entfernen'
BUTTON_02 = 'Letzte vertikale\nKolonne entfernen'
BUTTON_03 = 'Platziere 3x3-Element\n Frame'
BUTTONS = [BUTTON_01, BUTTON_02, BUTTON_03]
HORIZONTAL = 'horz'
VERTICAL = 'vert'

class SimpleTable(tk.Frame):
    def __init__(self, parent, rows, columns):
        self.parent = parent
        self.rows = rows
        self.columns = columns
        tk.Frame.__init__(self, parent, background="black")
        self.cells = []
        for row in range(rows):
            current_row = []
            for column in range(columns):
                frame = tk.Frame(self, borderwidth=1, width=200, height=30,
                   relief='raised')
                frame.grid(row=row, column=column, sticky="nsew")

                current_row.append(frame)
            self.cells.append(current_row)

        for column in range(columns):
            self.grid_columnconfigure(column, weight=1)
        
    def set(self, row, column, value):
        widget = self.cells[row][column]
        widget.configure(height=0)

    
    def remove_row(self, row=6):
        for label in self.cells[row]:
            label.config(height=0)
            label.update_idletasks()
 
    def remove_cells(self, direction):
        if direction == VERTICAL:
            # Remove last column on the right side of the table
            last_column = len(self.cells[0])
            last_row = len(self.cells)
            #print('Rows:', last_row)
            for row in range(last_row):
                print(row)
                self.cells[row][last_column-1].destroy()
                del self.cells[row][last_column-1:]
            #print(len(self.cells[0]))
                
        if direction == HORIZONTAL:
            # Remove last row on the bottom side of the table
            last_column = len(self.cells[0])
            last_row = len(self.cells)
            #print('Columns:', last_column)
            for column in range(last_column):
                print(column)
                self.cells[last_row-1][column].destroy() #config(height=0)
            del self.cells[last_row-1:]
            #print(self.cells)

    def add_big_frame(self):
        self.big_frame = tk.Frame(self, bg='red', bd=1, relief='raised')
        self.big_frame.grid(row=0, column=0, rowspan=3, columnspan=3,
            sticky='news')
        
        self.button = tk.Button(self.big_frame, text='Hello!', bd=1,
            highlightthickness=0)
        self.button.pack(expand=True)
             
class Application(tk.Frame):

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

        self.table = SimpleTable(self, rows=7, columns=6)
        self.table.pack(side="top", fill="x")
        #table.set(0,0,"Hello, world")
        self.master.geometry('')

        button_frame = tk.Frame(self)
        button_frame.pack()
    
        [tk.Button(button_frame, text=button_text,
            command=partial(self.on_button_press, button_text)).pack(
                side='left', pady=5)
                    for button_text in BUTTONS]
    
    def on_button_press(self, button):
        if button == BUTTON_01:
            self.remove_cells(HORIZONTAL)
        if button == BUTTON_02:
            self.remove_cells(VERTICAL)
        if button == BUTTON_03:
            self.table.add_big_frame() 
               
    def remove_cells(self, direction):
        self.table.remove_cells(direction)
        
    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)
    app.pack(fill='both', expand=True, padx=0, pady=0)
    
    app_win.mainloop()
 
 
if __name__ == '__main__':
    main()
Warum braucht es dein vorgeschlagenes lower nicht?

Gruss wuf :wink:
Take it easy Mates!
Antworten