Grid: Zeilen und Spaltenabstände ändern

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

Bei diesem 2 zeiligen und 2 spaltigen Grid Layout sind mir die Zeilen und Spaltenabstände zu gering:

Code: Alles auswählen

# -*- coding: utf-8 -*-

try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk


class Application(tk.Tk):

    def __init__(self,**kwargs):
        tk.Tk.__init__(self,**kwargs)
        self.config(height=160, width=300)
        self.minsize(300, 200)
        # widget definitions ===================================
        self.Button = tk.Button(self,padx=1, text='Button', width=10)
        self.Button.grid(column=1, row=0)
        self.Entry = tk.Button(self,padx=1, text='Entry', width=10)
        self.Entry.grid(column=1, row=1)
        self.Label = tk.Button(self,padx=1, text='Label', width=10)
        self.Label.grid(row=0)
        self.Listbox = tk.Button(self,padx=1, text='Listbox', width=10)
        self.Listbox.grid(row=1)

if __name__ == '__main__':
    Application().mainloop()
Ich möchte nun durch Ziehen mit der Maus, diese Abstände ändern können.

Wie mache ich das?
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Ich habe mir gedacht, ich ziehe mal Linien rein. Aber wenn man mit der Maus draufgeht, fangen die verrückt zu flackern an.

Code: Alles auswählen

# -*- coding: utf-8 -*-

try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk


class Application(tk.Tk):

    def __init__(self,**kwargs):
        tk.Tk.__init__(self,**kwargs)
        self.config(height=160, width=300)
        self.minsize(300, 200)
        # widget definitions ===================================
        self.Button = tk.Button(self,padx=1, text='Button', width=10)
        self.Button.grid(column=1, row=0)
        self.Entry = tk.Button(self,padx=1, text='Entry', width=10)
        self.Entry.grid(column=1, row=1)
        self.Label = tk.Button(self,padx=1, text='Label', width=10)
        self.Label.grid(row=0)
        self.Listbox = tk.Button(self,padx=1, text='Listbox', width=10)
        self.Listbox.grid(row=1)

        self.rows = 2
        self.cols = 2
        self.bind('<Enter>',self.insert_table,'+')
        self.bind('<Leave>',self.remove_table,'+')
        self.table_frames = []

    def insert_table(self,event):
        for col in range(self.cols):
            frame = tk.Frame(self,width = 4, bg = 'black')
            frame.grid(column = col,row = 0, rowspan = self.cols, sticky = 'nse')
            frame.lift()
            self.table_frames.append(frame)

        for row in range(self.rows):
            frame = tk.Frame(self,height = 4, bg = 'black')
            frame.grid(row = row, column = 0, columnspan = self.rows, sticky = 'wes')
            #frame.lift()
            self.table_frames.append(frame)
        
            
    def remove_table(self,event):
        for frame in self.table_frames:
            frame.destroy()
        self.table_frames.clear()
            
        
if __name__ == '__main__':
    Application().mainloop()
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Das mit den Bindings on leave und on enter war doch keine gute Idee. Leave ist ja nicht nur, wenn man das Anwendungsfenster nach außen verläßt, sondern auch nach innen, wenn man mit der Maus auf ein Widget fährt. Lassen wir das also weg, dann flackert auch nichts mehr:

Code: Alles auswählen

# -*- coding: utf-8 -*-

try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk


class Application(tk.Tk):

    def __init__(self,**kwargs):
        tk.Tk.__init__(self,**kwargs)
        self.config(height=160, width=300)
        self.minsize(300, 200)
        # widget definitions ===================================
        self.Button = tk.Button(self,padx=1, text='Button', width=10)
        self.Button.grid(column=1, row=0)
        self.Entry = tk.Button(self,padx=1, text='Entry', width=10)
        self.Entry.grid(column=1, row=1)
        self.Label = tk.Button(self,padx=1, text='Label', width=10)
        self.Label.grid(row=0)
        self.Listbox = tk.Button(self,padx=1, text='Listbox', width=10)
        self.Listbox.grid(row=1)

        self.rows = 2
        self.cols = 2
        self.table_frames = []
        self.line_size = 4
        self.insert_table()

    def insert_table(self,event = None):
        for col in range(self.cols):
            frame = tk.Frame(self,width = self.line_size, bg = 'black')
            frame.grid(column = col,row = 0, rowspan = self.cols, sticky = 'nse')
            self.table_frames.append(frame)

        for row in range(self.rows):
            frame = tk.Frame(self,height = self.line_size, bg = 'black')
            frame.grid(row = row, column = 0, columnspan = self.rows, sticky = 'wes')
            self.table_frames.append(frame)
        
if __name__ == '__main__':
    Application().mainloop()
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Als nächstes sollte man wohl signalisieren, dass man ziehen kann - naja wenn das jetzt schon ginge.

Code: Alles auswählen

# -*- coding: utf-8 -*-

try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk


class Application(tk.Tk):

    def __init__(self,**kwargs):
        tk.Tk.__init__(self,**kwargs)
        self.config(height=160, width=300)
        self.minsize(300, 200)
        # widget definitions ===================================
        self.Button = tk.Button(self,padx=1, text='Button', width=10)
        self.Button.grid(column=1, row=0)
        self.Entry = tk.Button(self,padx=1, text='Entry', width=10)
        self.Entry.grid(column=1, row=1)
        self.Label = tk.Button(self,padx=1, text='Label', width=10)
        self.Label.grid(row=0)
        self.Listbox = tk.Button(self,padx=1, text='Listbox', width=10)
        self.Listbox.grid(row=1)

        self.rows = 2
        self.cols = 2
        self.table_frames = []
        self.line_size = 4
        self.insert_table()

    def insert_table(self,event = None):
        for col in range(self.cols):
            frame = LineFrame(self,width = self.line_size, bg = 'black')
            frame.grid(column = col,row = 0, rowspan = self.cols, sticky = 'nse')
            frame.bind('<Enter>',frame.tableline_enter_col,'+')
            frame.bind('<Leave>',frame.tableline_leave,'+')
            self.table_frames.append(frame) # evtl. brauchen wir es noch

        for row in range(self.rows):
            frame = LineFrame(self,height = self.line_size, bg = 'black')
            frame.grid(row = row, column = 0, columnspan = self.rows, sticky = 'wes')
            frame.bind('<Enter>',frame.tableline_enter_row,'+')
            frame.bind('<Leave>',frame.tableline_leave,'+')
            self.table_frames.append(frame) # evtl. brauchen wir es noch


class LineFrame(tk.Frame):

    def __init__(self,master,**kwargs):
        tk.Frame.__init__(self,master,**kwargs)

    def tableline_enter_col(self,event=None):
        self.lift()
        self.config( cursor = 'sb_h_double_arrow', bg = 'lightgreen')


    def tableline_enter_row(self,event=None):
        self.lift()
        self.config( cursor = 'sb_v_double_arrow', bg = 'lightgreen')
        
    def tableline_leave(self,event=None):
        self.config( cursor = '', bg = 'black')


if __name__ == '__main__':
    Application().mainloop()
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Für weight =0 habe ich schon die Lösung - naja ist noch nicht ganz aufgeräumt. Für weight = 1 muss ich noch überlegen.

Code: Alles auswählen

# -*- coding: utf-8 -*-

try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk


class Application(tk.Tk):

    def __init__(self,**kwargs):
        tk.Tk.__init__(self,**kwargs)
        self.config(height=160, width=300)
        self.minsize(300, 200)
        # widget definitions ===================================
        self.Button = tk.Button(self,padx=1, text='Button', width=10)
        self.Button.grid(column=1, row=0)
        self.Entry = tk.Button(self,padx=1, text='Entry', width=10)
        self.Entry.grid(column=1, row=1)
        self.Label = tk.Button(self,padx=1, text='Label', width=10)
        self.Label.grid(row=0)
        self.Listbox = tk.Button(self,padx=1, text='Listbox', width=10)
        self.Listbox.grid(row=1)

        self.rows = 2
        self.cols = 2
        self.table_frames = []
        self.line_size = 4
        self.insert_table()

    def insert_table(self,event = None):
        for col in range(self.cols):
            left_frame = tk.Frame(self)
            left_frame.grid(column = col,row = 0, rowspan = self.cols, sticky = 'nsw')

            frame = LineFrame(self,width = self.line_size, bg = 'black',left_frame = left_frame)
            frame.grid(column = col,row = 0, rowspan = self.cols, sticky = 'nse')
            frame.bind('<Enter>',frame.tableline_enter_col)
            frame.bind('<Leave>',frame.tableline_leave)
            frame.bind('<Button-1>',frame.tableline_startmove_col)
                       

            self.table_frames.append(frame)

        for row in range(self.rows):

            top_frame = tk.Frame(self)
            top_frame.grid(column = 0,row = row, columnspan = self.rows, sticky = 'wen')
            frame = LineFrame(self,height = self.line_size, bg = 'black',top_frame = top_frame)
            frame.grid(row = row, column = 0, columnspan = self.rows, sticky = 'wes')
            frame.bind('<Enter>',frame.tableline_enter_row)
            frame.bind('<Leave>',frame.tableline_leave)
            frame.bind('<Button-1>',frame.tableline_startmove_row)
            self.table_frames.append(frame)


class LineFrame(tk.Frame):

    def __init__(self,master,**kwargs):

        # for measuring column or row size
        self.left_frame = kwargs.pop('left_frame',None)
        self.top_frame = kwargs.pop('top_frame',None)

        tk.Frame.__init__(self,master,**kwargs)
        self.master = master

    def tableline_enter_col(self,event=None):
        self.lift()
        self.config( cursor = 'sb_h_double_arrow', bg = 'lightgreen')


    def tableline_enter_row(self,event=None):
        self.lift()
        self.config( cursor = 'sb_v_double_arrow', bg = 'lightgreen')
        
    def tableline_leave(self,event=None):
        self.config( cursor = '', bg = 'black')

    def tableline_startmove_col(self,event = None):
        self.x_mouse = self.master.winfo_pointerx()
        x_line = self.winfo_rootx()
        self.dx = x_line - self.x_mouse
        self.col = int(self.grid_info()['column'])
        self.colconfig = self.master.grid_columnconfigure(self.col)
        self.weight = int(self.colconfig['weight'])

        if not self.weight:
            self.measure_colwidth()
            self.set_colwidth()

            self.is_moving = True
            self.unbind('<Enter>')
            self.unbind('<Leave>')
            self.bind('<ButtonRelease-1>',self.button_release_col)
            self.move_column()

    def tableline_startmove_row(self,event = None):

        self.y_mouse = self.master.winfo_pointery()
        y_line = self.winfo_rooty()
        self.dy = y_line - self.y_mouse
        self.row = int(self.grid_info()['row'])
        self.rowconfig = self.master.grid_rowconfigure(self.row)
        self.weight = int(self.rowconfig['weight'])
        if not self.weight:
            self.measure_rowheight()
            self.set_rowheight()
            self.is_moving = True
            self.unbind('<Enter>')
            self.unbind('<Leave>')
            self.bind('<ButtonRelease-1>',self.button_release_row)
            self.move_row()

                       
    def measure_colwidth(self):
        left_x = self.left_frame.winfo_rootx()
        right_x = self.winfo_rootx() + self.winfo_width()
        self.colwidth = right_x - left_x

    def set_colwidth(self):
        self.colconfig['minsize'] = self.colwidth - 2 * int(self.colconfig['pad'])
        self.master.columnconfigure(self.col,**self.colconfig)

    def measure_rowheight(self):
        top_y = self.top_frame.winfo_rooty()
        bottom_y = self.winfo_rooty() + self.winfo_height()
        self.rowheight =  bottom_y - top_y

    def set_rowheight(self):
        self.rowconfig['minsize'] = self.rowheight - 2 * int(self.rowconfig['pad'])
        self.master.rowconfigure(self.row,**self.rowconfig)


    def button_release_col(self,event = None):
        self.unbind('<ButtonRelease-1>')
        self.is_moving = False

        self.bind('<Enter>',self.tableline_enter_col)
        self.bind('<Leave>',self.tableline_leave)
        

    def button_release_row(self,event = None):
        self.unbind('<ButtonRelease-1>')
        self.is_moving = False

        self.bind('<Enter>',self.tableline_enter_row)
        self.bind('<Leave>',self.tableline_leave)
        

    def move_column(self):
        if not self.weight:
            x_mouse = self.master.winfo_pointerx()
            if x_mouse != self.x_mouse:
                dx = x_mouse - self.x_mouse
                self.x_mouse = x_mouse
                self.measure_colwidth()
                self.colwidth += dx
                self.set_colwidth()
        if self.is_moving:
            self.after(20,self.move_column)
                

    def move_row(self):
        if not self.weight:
            y_mouse = self.master.winfo_pointery()
            if y_mouse != self.y_mouse:
                dy = y_mouse - self.y_mouse
                self.y_mouse = y_mouse
                self.measure_rowheight()
                self.rowheight += dy
                self.set_rowheight()
        if self.is_moving:
            self.after(20,self.move_row)


if __name__ == '__main__':
    Application().mainloop()
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Jetzt habe ich es auch mit weight gemacht. Aber bei weight sollte man das Ziehen mit der Maus besser lassen. Denn dabei hat man dann keine Kontrolle mehr, welcher minsizte dann drin ist.

Hier sind die Spalten ohne weight und die Zeilen mit weight:

Code: Alles auswählen

# -*- coding: utf-8 -*-

try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk


class Application(tk.Tk):

    def __init__(self,**kwargs):
        tk.Tk.__init__(self,**kwargs)
        #self.config(height=160, width=300)
        self.minsize(300, 200)
        # widget definitions ===================================
        self.Button = tk.Button(self,padx=1, width=10, text='Button')
        self.Button.grid(column=1, row=0)
        self.Entry = tk.Button(self,padx=1, width=10, text='Entry')
        self.Entry.grid(column=1, row=1)
        self.Frame = tk.Button(self,padx='1', width=10, text='Frame')
        self.Frame.grid(column=1, row=2)
        self.Label = tk.Button(self,padx=1, width=10, text='Label')
        self.Label.grid(row=0)
        self.Listbox = tk.Button(self,padx=1, width=10, text='Listbox')
        self.Listbox.grid(row=1)
        self.Text = tk.Button(self,padx='1', width=10, text='Text')
        self.Text.grid(row=2)

        self.rowconfigure(0,weight=1,minsize = 30)
        self.rowconfigure(1,weight=1,minsize = 30)
        self.rowconfigure(2,weight=1,minsize = 30)

        self.rows = 3
        self.cols = 2
        self.table_frames = []
        self.line_size = 4
        self.insert_table()

    def insert_table(self,event = None):
        for col in range(self.cols):
            compare_frame = tk.Frame(self)
            compare_frame.grid(column = col,row = 0, rowspan = self.rows, sticky = 'nsw')

            frame = LineFrame(self,width = self.line_size, bg = 'black',compare_frame = compare_frame)
            frame.grid(column = col,row = 0, rowspan = self.rows, sticky = 'nse')
            frame.bind('<Enter>',frame.tableline_enter_col)
            frame.bind('<Leave>',frame.tableline_leave)
            frame.bind('<Button-1>',frame.tableline_startmove_col)
                       

            self.table_frames.append(frame)

        for row in range(self.rows):

            compare_frame = tk.Frame(self)
            compare_frame.grid(column = 0,row = row, columnspan = self.cols, sticky = 'wen')


            frame = LineFrame(self,height = self.line_size, bg = 'black',compare_frame = compare_frame)
            frame.grid(row = row, column = 0, columnspan = self.cols, sticky = 'wes')
            frame.bind('<Enter>',frame.tableline_enter_row)
            frame.bind('<Leave>',frame.tableline_leave)
            frame.bind('<Button-1>',frame.tableline_startmove_row)
            self.table_frames.append(frame)


class LineFrame(tk.Frame):

    def __init__(self,master,**kwargs):

        # for measuring column or row size
        self.compare_frame = kwargs.pop('compare_frame',None)

        tk.Frame.__init__(self,master,**kwargs)
        self.master = master

    def tableline_enter_col(self,event=None):
        self.lift()
        self.config( cursor = 'sb_h_double_arrow', bg = 'lightgreen')


    def tableline_enter_row(self,event=None):
        self.lift()
        self.config( cursor = 'sb_v_double_arrow', bg = 'lightgreen')
        
    def tableline_leave(self,event=None):
        self.config( cursor = '', bg = 'black')

    def tableline_startmove_col(self,event = None):
        self.mouse_startpos = self.master.winfo_pointerx()
        self.mouse_before = self.mouse_startpos 

        x_line = self.winfo_rootx()
        self.dx = x_line - self.mouse_startpos
        self.row_col = int(self.grid_info()['column'])
        self.line_configure = self.master.grid_columnconfigure
        self.row_col_config = self.line_configure(self.row_col)
        self.weight = int(self.row_col_config['weight'])

        self.measure_size = self.measure_colwidth
        self.measure_size()
        self.start_size = self.cellsize
        self.start_begin = self.begin

        self.is_moving = True
        self.unbind('<Enter>')
        self.unbind('<Leave>')
        self.bind('<ButtonRelease-1>',self.button_release_col)
        self.startmove = self.tableline_startmove_col
        self.enter = self.tableline_enter_col
        self.pointer = self.master.winfo_pointerx
        self.move()
       

    def tableline_startmove_row(self,event = None):

        self.mouse_startpos = self.master.winfo_pointery()
        self.mouse_before = self.mouse_startpos 

        y_line = self.winfo_rooty()
        self.dy = y_line - self.mouse_startpos
        self.row_col = int(self.grid_info()['row'])
        self.line_configure = self.master.grid_rowconfigure
        self.row_col_config = self.line_configure(self.row_col)
        self.weight = int(self.row_col_config['weight'])

        self.measure_size = self.measure_rowheight
        self.measure_size()
        self.start_size = self.cellsize
        self.start_begin = self.begin
        self.is_moving = True
        self.unbind('<Enter>')
        self.unbind('<Leave>')
        self.bind('<ButtonRelease-1>',self.button_release_row)
        self.startmove = self.tableline_startmove_row
        self.enter = self.tableline_enter_row
        self.pointer = self.master.winfo_pointery
        self.move()

                       
    def measure_colwidth(self):
        left_x = self.compare_frame.winfo_rootx()
        right_x = self.winfo_rootx() + self.winfo_width()
        self.cellsize = right_x - left_x
        self.begin = left_x
        self.end = right_x


    def set_size(self):
        self.row_col_config['minsize'] = self.cellsize - 2 * int(self.row_col_config['pad'])
        self.line_configure(self.row_col,**self.row_col_config)

    def measure_rowheight(self):
        top_y = self.compare_frame.winfo_rooty()
        bottom_y = self.winfo_rooty() + self.winfo_height()
        self.cellsize =  bottom_y - top_y
        self.begin = top_y
        self.end = bottom_y


    def update_weight_release(self):
        #pos_mouse = self.pointer()
        #dpos = pos_mouse - self.mouse_startpos
        self.measure_size()
        self.new_cellsize = self.start_size + self.start_begin - self.begin + self.dpos
        if self.cellsize != self.new_cellsize:
            self.increase = 1 if self.new_cellsize > self.cellsize else -1
            self.update_minsize()
            self.after(1,self.update_minsize)
        else:
            self.bind('<Button-1>',self.startmove)
            self.bind('<Enter>',self.enter)
            self.bind('<Leave>',self.tableline_leave)



    def button_release_col(self,event = None):
        self.unbind('<ButtonRelease-1>')
        self.is_moving = False
        if self.weight:
            self.unbind('<Button-1>')
            self.new_cellsize = self.cellsize
            self.row_col_config['weight'] = self.weight
            self.line_configure(self.row_col,weight = self.weight)
            self.tableline_leave()
            self.after(100,self.update_weight_release)
            return

        self.bind('<Enter>',self.tableline_enter_col)
        self.bind('<Leave>',self.tableline_leave)
        


    def button_release_row(self,event = None):
        self.unbind('<ButtonRelease-1>')
        self.is_moving = False
        if self.weight:
            self.unbind('<Button-1>')
            self.new_cellsize = self.cellsize
            self.row_col_config['weight'] = self.weight
            self.line_configure(self.row_col,**self.row_col_config)
            self.tableline_leave()
            self.after(100,self.update_weight_release)
            return

        self.bind('<Enter>',self.tableline_enter_row)
        self.bind('<Leave>',self.tableline_leave)
        

    def update_minsize(self):

        if self.increase > 0 and self.cellsize < self.new_cellsize or self.increase < 0 and self.cellsize > self.new_cellsize:

            minsize = self.row_col_config['minsize']
            if self.increase > 0 and minsize < self.new_cellsize or self.increase < 0 and minsize > 0:
                #print('tit')
                      

                self.row_col_config['minsize'] = minsize + self.increase
                self.line_configure(self.row_col,**self.row_col_config)
                self.measure_size()
                self.after(1,self.update_minsize)
                    
            elif self.is_moving:
                self.after(20,self.move)
            else:
                #self.after(1,self.update_weight_release())
                self.bind('<Button-1>',self.startmove)
                self.bind('<Enter>',self.enter)
                self.bind('<Leave>',self.tableline_leave)

        elif self.is_moving:
            self.after(20,self.move)
        else:
            self.bind('<Button-1>',self.startmove)
            self.bind('<Enter>',self.enter)
            self.bind('<Leave>',self.tableline_leave)


    def move(self):
        pos_mouse = self.pointer()
        dpos = pos_mouse - self.mouse_startpos
        self.dpos = dpos
        self.measure_size()
        self.new_cellsize = self.start_size + self.start_begin - self.begin + dpos

        if self.new_cellsize != self.cellsize:
    
            if not self.weight:
                self.cellsize = self.new_cellsize
                self.set_size()
                if self.is_moving:
                    self.after(20,self.move)
            else:
                self.increase = 1 if self.new_cellsize > self.cellsize else -1
                self.update_minsize()
                
        elif self.is_moving:
            self.after(20,self.move)
                


if __name__ == '__main__':
    Application().mainloop()
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Das mit der letzten Zeile oder Spalte sollte man bei weight wohl anders handhaben, da die von der Endposition her nicht verstellbar ist und da dann alles zum rennen anfängt, wenn man die Zeile soweit vergrößern will, bis die durch den Cursor bestimmte Endposition erreicht wird. Das geht schließlich nicht.

Da wäre sinnvoll, sie nur soweit zu vergrößern oder zu verkleinern., wie das durch die Mauskursordifferenz bestimmt wird.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Aber so sollte es dann wohl passen:

Code: Alles auswählen

# -*- coding: utf-8 -*-

try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk


class Application(tk.Tk):

    def __init__(self,**kwargs):
        tk.Tk.__init__(self,**kwargs)
        #self.config(height=160, width=300)
        self.minsize(300, 200)
        # widget definitions ===================================
        self.Button = tk.Button(self,padx=1, width=10, text='Button')
        self.Button.grid(column=1, row=0)
        self.Entry = tk.Button(self,padx=1, width=10, text='Entry')
        self.Entry.grid(column=1, row=1)
        self.Frame = tk.Button(self,padx='1', width=10, text='Frame')
        self.Frame.grid(column=1, row=2)
        self.Label = tk.Button(self,padx=1, width=10, text='Label')
        self.Label.grid(row=0)
        self.Listbox = tk.Button(self,padx=1, width=10, text='Listbox')
        self.Listbox.grid(row=1)
        self.Text = tk.Button(self,padx='1', width=10, text='Text')
        self.Text.grid(row=2)

        self.rowconfigure(0,weight=1,minsize = 30)
        self.rowconfigure(1,weight=1,minsize = 30)
        self.rowconfigure(2,weight=1,minsize = 30)

        self.rows = 3
        self.cols = 2
        self.table_frames = []
        self.line_size = 4
        self.insert_table()

    def insert_table(self,event = None):
        for col in range(self.cols):
            compare_frame = tk.Frame(self)
            compare_frame.grid(column = col,row = 0, rowspan = self.rows, sticky = 'nsw')

            frame = LineFrame(self,width = self.line_size, bg = 'black',compare_frame = compare_frame)
            frame.grid(column = col,row = 0, rowspan = self.rows, sticky = 'nse')
            frame.bind('<Enter>',frame.tableline_enter_col)
            frame.bind('<Leave>',frame.tableline_leave)
            frame.bind('<Button-1>',frame.tableline_startmove_col)
                       

            self.table_frames.append(frame)

        for row in range(self.rows):

            compare_frame = tk.Frame(self)
            compare_frame.grid(column = 0,row = row, columnspan = self.cols, sticky = 'wen')


            frame = LineFrame(self,height = self.line_size, bg = 'black',compare_frame = compare_frame)
            frame.grid(row = row, column = 0, columnspan = self.cols, sticky = 'wes')
            frame.bind('<Enter>',frame.tableline_enter_row)
            frame.bind('<Leave>',frame.tableline_leave)
            frame.bind('<Button-1>',frame.tableline_startmove_row)
            self.table_frames.append(frame)


class LineFrame(tk.Frame):

    def __init__(self,master,**kwargs):

        # for measuring column or row size
        self.compare_frame = kwargs.pop('compare_frame',None)

        tk.Frame.__init__(self,master,**kwargs)
        self.master = master

    def tableline_enter_col(self,event=None):
        self.lift()
        self.config( cursor = 'sb_h_double_arrow', bg = 'lightgreen')


    def tableline_enter_row(self,event=None):
        self.lift()
        self.config( cursor = 'sb_v_double_arrow', bg = 'lightgreen')
        
    def tableline_leave(self,event=None):
        self.config( cursor = '', bg = 'black')

    def tableline_startmove_col(self,event = None):
        self.mouse_startpos = self.master.winfo_pointerx()
        self.mouse_before = self.mouse_startpos 

        x_line = self.winfo_rootx()
        self.dx = x_line - self.mouse_startpos
        self.row_col = int(self.grid_info()['column'])
        self.line_configure = self.master.grid_columnconfigure
        self.row_col_config = self.line_configure(self.row_col)
        self.weight = int(self.row_col_config['weight'])
        self.line_count = self.master.cols

        self.measure_size = self.measure_colwidth
        self.measure_size()
        self.start_size = self.cellsize
        self.start_begin = self.begin

        self.is_moving = True
        self.unbind('<Enter>')
        self.unbind('<Leave>')
        self.bind('<ButtonRelease-1>',self.button_release_col)
        self.startmove = self.tableline_startmove_col
        self.enter = self.tableline_enter_col
        self.pointer = self.master.winfo_pointerx
        self.move()
       

    def tableline_startmove_row(self,event = None):

        self.mouse_startpos = self.master.winfo_pointery()
        self.mouse_before = self.mouse_startpos 

        y_line = self.winfo_rooty()
        self.dy = y_line - self.mouse_startpos
        self.row_col = int(self.grid_info()['row'])
        self.line_configure = self.master.grid_rowconfigure
        self.row_col_config = self.line_configure(self.row_col)
        self.weight = int(self.row_col_config['weight'])
        self.line_count = self.master.rows


        self.measure_size = self.measure_rowheight
        self.measure_size()
        self.start_size = self.cellsize
        self.start_begin = self.begin
        self.is_moving = True
        self.unbind('<Enter>')
        self.unbind('<Leave>')
        self.bind('<ButtonRelease-1>',self.button_release_row)
        self.startmove = self.tableline_startmove_row
        self.enter = self.tableline_enter_row
        self.pointer = self.master.winfo_pointery
        self.move()

                       
    def measure_colwidth(self):
        left_x = self.compare_frame.winfo_rootx()
        right_x = self.winfo_rootx() + self.winfo_width()
        self.cellsize = right_x - left_x
        self.begin = left_x
        self.end = right_x


    def set_size(self):
        self.row_col_config['minsize'] = self.cellsize - 2 * int(self.row_col_config['pad'])
        self.line_configure(self.row_col,**self.row_col_config)

    def measure_rowheight(self):
        top_y = self.compare_frame.winfo_rooty()
        bottom_y = self.winfo_rooty() + self.winfo_height()
        self.cellsize =  bottom_y - top_y
        self.begin = top_y
        self.end = bottom_y


    def update_weight_release(self):
        self.measure_size()

        if self.row_col + 1 ==  self.line_count:
            self.new_cellsize = self.start_size + self.dpos
        else:
            self.new_cellsize = self.start_size + self.start_begin - self.begin + self.dpos

        if self.cellsize != self.new_cellsize:
            self.increase = 1 if self.new_cellsize > self.cellsize else -1
            self.update_minsize()
            self.after(1,self.update_minsize)
        else:
            self.bind('<Button-1>',self.startmove)
            self.bind('<Enter>',self.enter)
            self.bind('<Leave>',self.tableline_leave)



    def button_release_col(self,event = None):
        self.unbind('<ButtonRelease-1>')
        self.is_moving = False
        if self.weight:
            self.unbind('<Button-1>')
            self.new_cellsize = self.cellsize
            self.row_col_config['weight'] = self.weight
            self.line_configure(self.row_col,weight = self.weight)
            self.tableline_leave()
            self.after(100,self.update_weight_release)
            return

        self.bind('<Enter>',self.tableline_enter_col)
        self.bind('<Leave>',self.tableline_leave)
        


    def button_release_row(self,event = None):
        self.unbind('<ButtonRelease-1>')
        self.is_moving = False
        if self.weight:
            self.unbind('<Button-1>')
            self.new_cellsize = self.cellsize
            self.row_col_config['weight'] = self.weight
            self.line_configure(self.row_col,**self.row_col_config)
            self.tableline_leave()
            self.after(100,self.update_weight_release)
            return

        self.bind('<Enter>',self.tableline_enter_row)
        self.bind('<Leave>',self.tableline_leave)
        

    def update_minsize(self):

        if self.increase > 0 and self.cellsize < self.new_cellsize or self.increase < 0 and self.cellsize > self.new_cellsize:

            minsize = self.row_col_config['minsize']
            if self.increase > 0 and minsize < self.new_cellsize or self.increase < 0 and minsize > 0:

                self.row_col_config['minsize'] = minsize + self.increase
                self.line_configure(self.row_col,**self.row_col_config)
                self.measure_size()
                self.after(1,self.update_minsize)
                    
            elif self.is_moving:
                self.after(20,self.move)
            else:
                self.bind('<Button-1>',self.startmove)
                self.bind('<Enter>',self.enter)
                self.bind('<Leave>',self.tableline_leave)

        elif self.is_moving:
            self.after(20,self.move)
        else:
            self.bind('<Button-1>',self.startmove)
            self.bind('<Enter>',self.enter)
            self.bind('<Leave>',self.tableline_leave)


    def move(self):
        pos_mouse = self.pointer()
        dpos = pos_mouse - self.mouse_startpos
        self.dpos = dpos
        self.measure_size()

        if self.row_col + 1 ==  self.line_count:
            self.new_cellsize = self.start_size + dpos
        else:
            self.new_cellsize = self.start_size + self.start_begin - self.begin + dpos

        if self.new_cellsize != self.cellsize:
    
            if not self.weight:
                self.cellsize = self.new_cellsize
                self.set_size()
                if self.is_moving:
                    self.after(20,self.move)
            else:
                self.increase = 1 if self.new_cellsize > self.cellsize else -1
                self.update_minsize()
                
        elif self.is_moving:
            self.after(20,self.move)
                


if __name__ == '__main__':
    Application().mainloop()
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Jetzt tut es ziemlich perfekt:

Code: Alles auswählen

# -*- coding: utf-8 -*-

try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk


class Application(tk.Tk):

    def __init__(self,**kwargs):
        tk.Tk.__init__(self,**kwargs)
        #self.config(height=160, width=300)
        self.minsize(300, 200)
        self.geometry("+0+0")
        # widget definitions ===================================
        self.Button = tk.Button(self,padx=1, width=10, text='Button')
        self.Button.grid(column=1, row=0)
        self.Entry = tk.Button(self,padx=1, width=10, text='Entry')
        self.Entry.grid(column=1, row=1)
        self.Frame = tk.Button(self,padx='1', width=10, text='Frame')
        self.Frame.grid(column=1, row=2)
        self.Label = tk.Button(self,padx=1, width=10, text='Label')
        self.Label.grid(row=0)
        self.Listbox = tk.Button(self,padx=1, width=10, text='Listbox')
        self.Listbox.grid(row=1)
        self.Text = tk.Button(self,padx='1', width=10, text='Text')
        self.Text.grid(row=2)

        self.rowconfigure(0,weight=1,minsize = 30)
        self.rowconfigure(1,weight=1,minsize = 30)
        self.rowconfigure(2,weight=1,minsize = 30)

        self.rows = 3
        self.cols = 2
        self.table_frames = []
        self.line_size = 4
        self.insert_table()

    def insert_table(self,event = None):
        for col in range(self.cols):
            compare_frame = tk.Frame(self)
            compare_frame.grid(column = col,row = 0, rowspan = self.rows, sticky = 'nsw')

            frame = LineFrame(self,width = self.line_size, bg = 'black',compare_frame = compare_frame)
            frame.grid(column = col,row = 0, rowspan = self.rows, sticky = 'nse')
            frame.bind('<Enter>',frame.tableline_enter_col)
            frame.bind('<Leave>',frame.tableline_leave)
            frame.bind('<Button-1>',frame.tableline_startmove_col)
                       

            self.table_frames.append(frame)

        for row in range(self.rows):

            compare_frame = tk.Frame(self)
            compare_frame.grid(column = 0,row = row, columnspan = self.cols, sticky = 'wen')


            frame = LineFrame(self,height = self.line_size, bg = 'black',compare_frame = compare_frame)
            frame.grid(row = row, column = 0, columnspan = self.cols, sticky = 'wes')
            frame.bind('<Enter>',frame.tableline_enter_row)
            frame.bind('<Leave>',frame.tableline_leave)
            frame.bind('<Button-1>',frame.tableline_startmove_row)
            self.table_frames.append(frame)


class LineFrame(tk.Frame):

    def __init__(self,master,**kwargs):

        # for measuring column or row size
        self.compare_frame = kwargs.pop('compare_frame',None)

        tk.Frame.__init__(self,master,**kwargs)
        self.master = master

    def tableline_enter_col(self,event=None):
        self.lift()
        self.config( cursor = 'sb_h_double_arrow', bg = 'lightgreen')


    def tableline_enter_row(self,event=None):
        self.lift()
        self.config( cursor = 'sb_v_double_arrow', bg = 'lightgreen')
        
    def tableline_leave(self,event=None):
        self.config( cursor = '', bg = 'black')

    def tableline_startmove_col(self,event = None):
        self.mouse_startpos = self.master.winfo_pointerx()
        self.mouse_before = self.mouse_startpos 

        x_line = self.winfo_rootx()
        self.dx = x_line - self.mouse_startpos
        self.row_col = int(self.grid_info()['column'])
        self.line_configure = self.master.grid_columnconfigure
        self.row_col_config = self.line_configure(self.row_col)
        self.weight = int(self.row_col_config['weight'])
        self.line_count = self.master.cols

        self.measure_size = self.measure_colwidth
        self.measure_size()
        self.start_size = self.cellsize
        self.start_begin = self.begin

        self.is_moving = True
        self.unbind('<Enter>')
        self.unbind('<Leave>')
        self.bind('<ButtonRelease-1>',self.button_release)
        self.startmove = self.tableline_startmove_col
        self.enter = self.tableline_enter_col
        self.pointer = self.master.winfo_pointerx
        self.move()
       

    def tableline_startmove_row(self,event = None):

        self.mouse_startpos = self.master.winfo_pointery()
        self.mouse_before = self.mouse_startpos 

        y_line = self.winfo_rooty()
        self.dy = y_line - self.mouse_startpos
        self.row_col = int(self.grid_info()['row'])
        self.line_configure = self.master.grid_rowconfigure
        self.row_col_config = self.line_configure(self.row_col)
        self.weight = int(self.row_col_config['weight'])
        self.line_count = self.master.rows


        self.measure_size = self.measure_rowheight
        self.measure_size()
        self.start_size = self.cellsize
        self.start_begin = self.begin
        self.is_moving = True
        self.unbind('<Enter>')
        self.unbind('<Leave>')
        self.bind('<ButtonRelease-1>',self.button_release)
        self.startmove = self.tableline_startmove_row
        self.enter = self.tableline_enter_row
        self.pointer = self.master.winfo_pointery
        self.move()

                       
    def measure_colwidth(self):
        left_x = self.compare_frame.winfo_rootx()
        right_x = self.winfo_rootx() + self.winfo_width()
        self.cellsize = right_x - left_x + 1
        self.begin = left_x
        self.end = right_x


    def set_size(self):
        self.row_col_config['minsize'] = self.cellsize - 2 * int(self.row_col_config['pad'])
        self.line_configure(self.row_col,**self.row_col_config)

    def measure_rowheight(self):
        top_y = self.compare_frame.winfo_rooty()
        bottom_y = self.winfo_rooty() + self.winfo_height()
        self.cellsize =  bottom_y - top_y + 1
        self.begin = top_y
        self.end = bottom_y


    def button_release(self,event = None):
        self.is_moving = False
        self.unbind('<Button-1>')
        self.unbind('<ButtonRelease-1>')
        self.tableline_leave()
        #self.after(20,self.update_minsize)
        return


    def update_minsize(self):

        self.measure_size()
        if self.row_col + 1 ==  self.line_count:
            self.new_cellsize = self.start_size + self.dpos
        else:
            self.new_cellsize = self.start_size + self.start_begin - self.begin + self.dpos

        self.new_cellsize = max(self.new_cellsize,0)

        self.increase =  self.new_cellsize - self.cellsize

        if self.weight:
            if self.increase < 0:
                self.increase = min(self.increase//2,-1)
        
        
            
        if self.increase > 0 and self.cellsize < self.new_cellsize or self.increase < 0 and self.cellsize > self.new_cellsize:

            minsize = self.row_col_config['minsize']
            if self.increase > 0 and minsize + self.increase <= self.new_cellsize or self.increase < 0 and minsize + self.increase >=0:
                      

                self.row_col_config['minsize'] = minsize + self.increase
                self.line_configure(self.row_col,**self.row_col_config)
                #self.measure_size()
                self.after(10,self.update_minsize)
                    
            elif self.is_moving:
                self.after(10,self.move)
            else:
                self.bind('<Button-1>',self.startmove)
                self.bind('<Enter>',self.enter)
                self.bind('<Leave>',self.tableline_leave)

        elif self.is_moving:
            self.after(10,self.move)
        else:
            self.bind('<Button-1>',self.startmove)
            self.bind('<Enter>',self.enter)
            self.bind('<Leave>',self.tableline_leave)


    def move(self):
        pos_mouse = self.pointer()
        dpos = pos_mouse - self.mouse_startpos
        self.dpos = dpos
        if not self.weight:
            self.measure_size()
            self.row_col_config['minsize'] = self.cellsize
            self.line_configure(self.row_col,**self.row_col_config)
        self.update_minsize()
 
if __name__ == '__main__':
    Application().mainloop()
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Wenn nicht, bitte Fehler melden:

Code: Alles auswählen

# -*- coding: utf-8 -*-

try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk


class Application(tk.Tk):

    def __init__(self,**kwargs):
        tk.Tk.__init__(self,**kwargs)
        #self.config(height=160, width=300)
        self.minsize(300, 200)
        self.geometry("+0+0")
        # widget definitions ===================================
        self.Button = tk.Button(self,padx=1, width=10, text='Button')
        self.Button.grid(column=1, row=0)
        self.Entry = tk.Button(self,padx=1, width=10, text='Entry')
        self.Entry.grid(column=1, row=1)
        self.Frame = tk.Button(self,padx='1', width=10, text='Frame')
        self.Frame.grid(column=1, row=2)
        self.Label = tk.Button(self,padx=1, width=10, text='Label')
        self.Label.grid(row=0)
        self.Listbox = tk.Button(self,padx=1, width=10, text='Listbox')
        self.Listbox.grid(row=1)
        self.Text = tk.Button(self,padx='1', width=10, text='Text')
        self.Text.grid(row=2)

        self.rowconfigure(0,weight=1,minsize = 30)
        self.rowconfigure(1,weight=1,minsize = 30)
        self.rowconfigure(2,weight=1,minsize = 30)

        self.rows = 3
        self.cols = 2
        self.table_frames = []
        self.line_size = 4
        self.insert_table()

    def insert_table(self,event = None):
        for col in range(self.cols):
            compare_frame = tk.Frame(self)
            compare_frame.grid(column = col,row = 0, rowspan = self.rows, sticky = 'nsw')

            frame = LineFrame(self,width = self.line_size, bg = 'black',compare_frame = compare_frame)
            frame.grid(column = col,row = 0, rowspan = self.rows, sticky = 'nse')
            frame.bind('<Enter>',frame.tableline_enter_col)
            frame.bind('<Leave>',frame.tableline_leave)
            frame.bind('<Button-1>',frame.tableline_startmove_col)
                       

            self.table_frames.append(frame)

        for row in range(self.rows):

            compare_frame = tk.Frame(self)
            compare_frame.grid(column = 0,row = row, columnspan = self.cols, sticky = 'wen')


            frame = LineFrame(self,height = self.line_size, bg = 'black',compare_frame = compare_frame)
            frame.grid(row = row, column = 0, columnspan = self.cols, sticky = 'wes')
            frame.bind('<Enter>',frame.tableline_enter_row)
            frame.bind('<Leave>',frame.tableline_leave)
            frame.bind('<Button-1>',frame.tableline_startmove_row)
            self.table_frames.append(frame)


class LineFrame(tk.Frame):

    def __init__(self,master,**kwargs):

        # for measuring column or row size
        self.compare_frame = kwargs.pop('compare_frame',None)

        tk.Frame.__init__(self,master,**kwargs)
        self.master = master

    def tableline_enter_col(self,event=None):
        self.lift()
        self.config( cursor = 'sb_h_double_arrow', bg = 'lightgreen')

    def tableline_enter_row(self,event=None):
        self.lift()
        self.config( cursor = 'sb_v_double_arrow', bg = 'lightgreen')
        
    def tableline_leave(self,event=None):
        self.config( cursor = '', bg = 'black')

    def tableline_startmove_col(self,event = None):
        self.mouse_startpos = self.master.winfo_pointerx()
        self.mouse_before = self.mouse_startpos 
        x_line = self.winfo_rootx()
        self.dx = x_line - self.mouse_startpos
        self.row_col = int(self.grid_info()['column'])
        self.line_configure = self.master.grid_columnconfigure
        self.row_col_config = self.line_configure(self.row_col)
        self.weight = int(self.row_col_config['weight'])
        self.line_count = self.master.cols
        self.measure_size = self.measure_colwidth
        self.measure_size()
        self.start_size = self.cellsize
        self.start_begin = self.begin

        self.is_moving = True
        self.unbind('<Enter>')
        self.unbind('<Leave>')
        self.bind('<ButtonRelease-1>',self.button_release)
        self.startmove = self.tableline_startmove_col
        self.enter = self.tableline_enter_col
        self.pointer = self.master.winfo_pointerx
        self.move()
       

    def tableline_startmove_row(self,event = None):

        self.mouse_startpos = self.master.winfo_pointery()
        self.mouse_before = self.mouse_startpos 

        y_line = self.winfo_rooty()
        self.dy = y_line - self.mouse_startpos
        self.row_col = int(self.grid_info()['row'])
        self.line_configure = self.master.grid_rowconfigure
        self.row_col_config = self.line_configure(self.row_col)
        self.weight = int(self.row_col_config['weight'])
        self.line_count = self.master.rows
        self.measure_size = self.measure_rowheight
        self.measure_size()
        self.start_size = self.cellsize
        self.start_begin = self.begin
        self.is_moving = True
        self.unbind('<Enter>')
        self.unbind('<Leave>')
        self.bind('<ButtonRelease-1>',self.button_release)
        self.startmove = self.tableline_startmove_row
        self.enter = self.tableline_enter_row
        self.pointer = self.master.winfo_pointery
        self.move()

                       
    def measure_colwidth(self):
        left_x = self.compare_frame.winfo_rootx()
        right_x = self.winfo_rootx() + self.winfo_width()
        self.cellsize = right_x - left_x + 1
        self.begin = left_x
        self.end = right_x


    def set_size(self):
        self.row_col_config['minsize'] = self.cellsize - 2 * int(self.row_col_config['pad'])
        self.line_configure(self.row_col,**self.row_col_config)

    def measure_rowheight(self):
        top_y = self.compare_frame.winfo_rooty()
        bottom_y = self.winfo_rooty() + self.winfo_height()
        self.cellsize =  bottom_y - top_y + 1
        self.begin = top_y
        self.end = bottom_y


    def button_release(self,event = None):
        self.is_moving = False
        self.unbind('<Button-1>')
        self.unbind('<ButtonRelease-1>')
        self.tableline_leave()


    def move(self):

        if not self.is_moving:
            self.bind('<Button-1>',self.startmove)
            self.bind('<Enter>',self.enter)
            self.bind('<Leave>',self.tableline_leave)
            return
        
        pos_mouse = self.pointer()
        dpos = pos_mouse - self.mouse_startpos
        self.dpos = dpos
        if not self.weight:
            self.measure_size()
            self.row_col_config['minsize'] = self.cellsize
            self.line_configure(self.row_col,**self.row_col_config)

        self.measure_size()
        if self.row_col + 1 ==  self.line_count:
            self.new_cellsize = self.start_size + self.dpos
        else:
            self.new_cellsize = self.start_size + self.start_begin - self.begin + self.dpos

        self.new_cellsize = max(self.new_cellsize,0)
        self.increase =  self.new_cellsize - self.cellsize

        if self.weight:
            if self.increase < 0:
                self.increase = min(self.increase//2,-1)
            
        if self.increase > 0 and self.cellsize < self.new_cellsize or self.increase < 0 and self.cellsize > self.new_cellsize:
            minsize = self.row_col_config['minsize']
            if self.increase > 0 and minsize + self.increase <= self.new_cellsize or self.increase < 0 and minsize + self.increase >=0:
                self.row_col_config['minsize'] = minsize + self.increase
                self.line_configure(self.row_col,**self.row_col_config)
                  
        self.after(10,self.move)



if __name__ == '__main__':
    Application().mainloop()
Antworten