Wie kann man hier Zeilen und Spalten einfügen und löschen?

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

Zeilen und Spalten einfügen und löschen soll hier über Mausklick und Tastatur (Einfg, Entf) möglich sein. Wie lässt sich das realisieren?

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_row(self,event = None):
        print("We don't want this now")

    def tableline_startmove_col(self,event = None):
        print("We don't want this now")

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

ZUm Einfügen und Löschen brauche ich die Spalten und Reihen Markierungslinien links und oben statt rechts und unten wie beim Ziehen, das muss ich dort noch entsprechend ändern. Außerdem brauche ich noch eine zusätzliche Reihe und Spalte rechts und unten, damit man auch weitere Reihen und Spalten hinten anhängen kann.

Das Spalten und Reihen schiebel soll dann mit <B1-Motion> gehehen. Die Linie Markieren für Einfügen oder Löschen soll mit <ButtonRelease-1> gemacht werden. Dabei soll dann die Linie blau werden.

Das habe ich so gemacht:

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+1):
            frame = LineFrame(self,width = self.line_size, bg = 'black',is_col = True)
            frame.grid(column = col,row = 0, rowspan = self.rows+1, sticky = 'nsw')
            if col:
                frame.bind('<Enter>',frame.tableline_enter_col)
                frame.bind('<B1-Motion>',frame.tableline_startmove_col)
            else:
                frame.bind('<Enter>',frame.tableline_enter_insert_col)
                
            frame.bind('<ButtonRelease-1>',frame.tableline_mark_col)
            self.table_frames.append(frame)

        for row in range(self.rows+1):
            frame = LineFrame(self,height = self.line_size, bg = 'black',is_col = False)
            frame.grid(row = row, column = 0, columnspan = self.cols+1, sticky = 'wen')
            if row:
                frame.bind('<Enter>',frame.tableline_enter_row)
                frame.bind('<B1-Motion>',frame.tableline_startmove_row)
            else:
                frame.bind('<Enter>',frame.tableline_enter_insert_row)

            frame.bind('<ButtonRelease-1>',frame.tableline_mark_row)
            self.table_frames.append(frame)


class LineFrame(tk.Frame):

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

        self.is_col = kwargs.pop('is_col',None)

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

    def bind_enter(self):
        if self.is_col:
            if int(self.grid_info()['column']):
                self.bind('<Enter>',self.tableline_enter_col)
            else:
                self.bind('<Enter>',self.tableline_enter_insert_col)
        else:
            if int(self.grid_info()['row']):
                self.bind('<Enter>',self.tableline_enter_row)
            else:
                self.bind('<Enter>',self.tableline_enter_insert_row)

    # these are double defined, but nearly identical may be we not only a single definition
    def tableline_enter_col(self,event=None):
        for element in self.master.table_frames:
            element.config( bg = 'black')
            element.bind_enter()

        self.bind('<Leave>',self.tableline_leave)
        self.lift()
        self.config( cursor = 'sb_h_double_arrow', bg = 'lightgreen')

    def tableline_enter_row(self,event=None):
        for element in self.master.table_frames:
            element.config( bg = 'black')
            element.bind_enter()

        self.bind('<Leave>',self.tableline_leave)
        self.lift()
        self.config( cursor = 'sb_v_double_arrow', bg = 'lightgreen')

    def tableline_enter_insert_col(self,event=None):
        for element in self.master.table_frames:
            element.config( bg = 'black')
        self.bind('<Leave>',self.tableline_leave)
        self.lift()
        self.config( cursor = 'plus', bg = 'lightgreen')

    def tableline_enter_insert_row(self,event=None):
        for element in self.master.table_frames:
            element.config( bg = 'black')
        self.bind('<Leave>',self.tableline_leave)
        self.lift()
        self.config( cursor = 'plus', bg = 'lightgreen')

    # ========================================================        

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

    def tableline_startmove_row(self,event = None):
        print('is moving')
        self.move_started = True
        self.button_release = self.tableline_mark_row
        self.enter = self.tableline_enter_row
        self.startmove = self.tableline_startmove_row
        self.unbind('<Enter>')
        self.unbind('<Leave>')
        self.bind('<ButtonRelease-1>',self.move_release)

    def tableline_startmove_col(self,event = None):
        print('is moving')
        self.move_started = True
        self.button_release = self.tableline_mark_col
        self.enter = self.tableline_enter_col
        self.startmove = self.tableline_startmove_col
        self.unbind('<Enter>')
        self.unbind('<Leave>')
        self.bind('<ButtonRelease-1>',self.move_release)

    def tableline_mark_col(self,event = None):
        if not self.move_started:
            self.unbind('<Leave>')
            self.unbind('<Enter>')
            for element in self.master.table_frames:
                element.config( bg = 'black')
            self.lift()
            self.config( cursor = '', bg = 'blue')
        
    def tableline_mark_row(self,event = None):
        if not self.move_started:
            self.unbind('<Leave>')
            self.unbind('<Enter>')
            for element in self.master.table_frames:
                element.config( bg = 'black')
            self.lift()
            self.config( cursor = '', bg = 'blue')
        

    def move_release(self,event = None):
        self.bind('<B1-Motion>',self.startmove)
        self.bind('<Enter>',self.enter)
        self.bind('<ButtonRelease-1>',self.button_release)
        self.tableline_leave()
        self.move_started = False

if __name__ == '__main__':
    Application().mainloop()
Wäre das so in Ordnung?
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Na, das geht so:

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.minsize(200, 200)
        # widget definitions ===================================
        self.frame = tk.Frame(self,takefocus='1', bg='#ffffd8')
        self.frame.pack(expand=1, fill='both')

        # code ================================================
        self.frame.focus()
        self.frame.bind('<Insert>',self.insert)
        self.frame.bind('<Delete>',self.delete)

    def insert(self,event = None):
        print('Insert pressed')
                        
    def delete(self,event = None):
        print('Delete pressed')


if __name__ == '__main__':
    Application().mainloop()
Dann kann man das ja mal machen
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Es geht auch ohne takefocus:

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.minsize(200, 200)
        # widget definitions ===================================
        self.frame = tk.Frame(self,bg='#ffffd8')
        self.frame.pack(expand=1, fill='both')

        # code ================================================
        self.frame.focus()
        self.frame.bind('<Insert>',self.insert)
        self.frame.bind('<Delete>',self.delete)

    def insert(self,event = None):
        print('Insert pressed')
                        
    def delete(self,event = None):
        print('Delete pressed')


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

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.col_default={ 'minsize' : 75, 'pad' : 0, 'weight' : 0 }
        self.row_default={ 'minsize' : 25, 'pad' : 0, 'weight' : 1 }

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


    def insert_col(self,col):
        frame = LineFrame(self,width = self.line_size, bg = 'black',is_col = True)
        frame.grid(column = col,row = 0, rowspan = self.rows+1, sticky = 'nsw')
        if col:
            frame.bind('<Enter>',frame.tableline_enter_col)
            frame.bind('<B1-Motion>',frame.tableline_startmove_col)
        else:
            frame.bind('<Enter>',frame.tableline_enter_insert_col)
            
        frame.bind('<ButtonRelease-1>',frame.tableline_mark_col)
        self.table_frames.append(frame)
        self.col_frames.append(frame)
        return frame


    def insert_row(self,row):        
        frame = LineFrame(self,height = self.line_size, bg = 'black',is_col = False)
        frame.grid(row = row, column = 0, columnspan = self.cols+1, sticky = 'wen')
        if row:
            frame.bind('<Enter>',frame.tableline_enter_row)
            frame.bind('<B1-Motion>',frame.tableline_startmove_row)
        else:
            frame.bind('<Enter>',frame.tableline_enter_insert_row)

        frame.bind('<ButtonRelease-1>',frame.tableline_mark_row)
        self.table_frames.append(frame)
        self.row_frames.append(frame)
        return frame

    def insert_table(self,event = None):
        for col in range(self.cols+1):
            self.insert_col(col)
        configure = self.columnconfigure(self.cols-1)
        configure['minsize'] = 0
        self.columnconfigure(self.cols,**configure)

        for row in range(self.rows+1):
            self.insert_row(row)

class LineFrame(tk.Frame):

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

        self.is_col = kwargs.pop('is_col',None)

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

    def bind_enter(self):
        if self.is_col:
            if int(self.grid_info()['column']):
                self.bind('<Enter>',self.tableline_enter_col)
            else:
                self.bind('<Enter>',self.tableline_enter_insert_col)
        else:
            if int(self.grid_info()['row']):
                self.bind('<Enter>',self.tableline_enter_row)
            else:
                self.bind('<Enter>',self.tableline_enter_insert_row)

    # these are double defined, but nearly identical may be we not only a single definition
    def tableline_enter_col(self,event=None):
        for element in self.master.table_frames:
            element.config( bg = 'black')
            element.bind_enter()

        self.master.focus()
        self.bind('<Leave>',self.tableline_leave)
        self.lift()
        self.config( cursor = 'sb_h_double_arrow', bg = 'lightgreen')

    def tableline_enter_row(self,event=None):
        for element in self.master.table_frames:
            element.config( bg = 'black')
            element.bind_enter()

        self.master.focus()
        self.bind('<Leave>',self.tableline_leave)
        self.lift()
        self.config( cursor = 'sb_v_double_arrow', bg = 'lightgreen')

    def tableline_enter_insert_col(self,event=None):
        for element in self.master.table_frames:
            element.config( bg = 'black')
        self.master.focus()
        self.bind('<Leave>',self.tableline_leave)
        self.lift()
        self.config( cursor = 'plus', bg = 'lightgreen')

    def tableline_enter_insert_row(self,event=None):
        for element in self.master.table_frames:
            element.config( bg = 'black')
        self.master.focus()
        self.bind('<Leave>',self.tableline_leave)
        self.lift()
        self.config( cursor = 'plus', bg = 'lightgreen')

    # ========================================================        

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

    def tableline_startmove_row(self,event = None):
        print('is moving')
        self.move_started = True
        self.button_release = self.tableline_mark_row
        self.enter = self.tableline_enter_row
        self.startmove = self.tableline_startmove_row
        self.unbind('<Enter>')
        self.unbind('<Leave>')
        self.bind('<ButtonRelease-1>',self.move_release)

    def tableline_startmove_col(self,event = None):
        print('is moving')
        self.move_started = True
        self.button_release = self.tableline_mark_col
        self.enter = self.tableline_enter_col
        self.startmove = self.tableline_startmove_col
        self.unbind('<Enter>')
        self.unbind('<Leave>')
        self.bind('<ButtonRelease-1>',self.move_release)

    def tableline_mark_col(self,event = None):
        if not self.move_started:
            self.unbind('<Leave>')
            self.unbind('<Enter>')
            for element in self.master.table_frames:
                element.config( bg = 'black')
            self.lift()
            self.config( cursor = '', bg = 'blue')
            self.focus()
            self.bind('<Insert>',self.insert)
            self.bind('<Delete>',self.delete)
            self.row_col = int(self.grid_info()['column'])
            self.grid_key = 'column'
            self.grid_configure = self.master.columnconfigure
            self.row_col_default = self.master.col_default
            self.insert_row_col = self.master.insert_col
            
        
    def tableline_mark_row(self,event = None):
        if not self.move_started:
            self.unbind('<Leave>')
            self.unbind('<Enter>')
            for element in self.master.table_frames:
                element.config( bg = 'black')
            self.lift()
            self.config( cursor = '', bg = 'blue')
            self.focus()
            self.bind('<Insert>',self.insert)
            self.bind('<Delete>',self.delete)
            self.row_col = int(self.grid_info()['row'])
            self.grid_key = 'row'
            self.grid_configure = self.master.rowconfigure
            self.row_col_default = self.master.row_default
            self.insert_row_col = self.master.insert_row
            

    def insert(self,event = None):
        endpos = self.master.cols if self.is_col else self.master.rows
        children = self.master.winfo_children()
        for pos in range(endpos,self.row_col-1,-1):
            for child in children:
                grid_info = child.grid_info()
                if int(grid_info[self.grid_key]) == pos:
                    child.grid_forget()
                    grid_info[self.grid_key] = pos + 1
                    child.grid(**grid_info)
            self.grid_configure(pos+1,**self.grid_configure(pos))
        self.grid_configure(self.row_col,self.row_col_default)
        insert_frame = self.insert_row_col(self.row_col)

        for element in self.master.table_frames:
            element.config( bg = 'black')
            element.bind_enter()

        if self.is_col:
            self.master.cols += 1

            for frame in self.master.row_frames:
                frame.grid(column = 0, columnspan = self.master.cols +1)
            insert_frame.tableline_mark_col()
        else:
            self.master.rows += 1
            for frame in self.master.col_frames:
                frame.grid(row = 0,rowspan = self.master.rows+1)
            insert_frame.tableline_mark_row()
            

    def delete(self,event = None):
        pass


    def move_release(self,event = None):
        self.bind('<B1-Motion>',self.startmove)
        self.bind('<Enter>',self.enter)
        self.bind('<ButtonRelease-1>',self.button_release)
        self.tableline_leave()
        self.move_started = False



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

Und zwar beim Gui Builder SpecTcl.

Also es ist so, man kann nur leere Zeilen und Spalten löschen und die erste kann man nicht löschen. Das ist dort logisch, den SpecTcl arbeitet nur mit Grid Layout und zwar nur mit einem, das columnspan und rowspan für alle Zeilen und Spalten definiert. Eine Zeile und Spalte hat man dort immer.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Bitte testen:

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.col_default={ 'minsize' : 75, 'pad' : 0, 'weight' : 0 }
        self.row_default={ 'minsize' : 25, 'pad' : 0, 'weight' : 1 }

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


    def insert_col(self,col):
        frame = LineFrame(self,width = self.line_size, bg = 'black',is_col = True)
        frame.grid(column = col,row = 0, rowspan = self.rows+1, sticky = 'nsw')
        if col:
            frame.bind('<Enter>',frame.tableline_enter_col)
            frame.bind('<B1-Motion>',frame.tableline_startmove_col)
        else:
            frame.bind('<Enter>',frame.tableline_enter_insert_col)
            
        frame.bind('<ButtonRelease-1>',frame.tableline_mark_col)
        self.table_frames.append(frame)
        self.col_frames.append(frame)
        return frame


    def insert_row(self,row):        
        frame = LineFrame(self,height = self.line_size, bg = 'black',is_col = False)
        frame.grid(row = row, column = 0, columnspan = self.cols+1, sticky = 'wen')
        if row:
            frame.bind('<Enter>',frame.tableline_enter_row)
            frame.bind('<B1-Motion>',frame.tableline_startmove_row)
        else:
            frame.bind('<Enter>',frame.tableline_enter_insert_row)

        frame.bind('<ButtonRelease-1>',frame.tableline_mark_row)
        self.table_frames.append(frame)
        self.row_frames.append(frame)
        return frame

    def insert_table(self,event = None):
        for col in range(self.cols+1):
            self.insert_col(col)
        configure = self.columnconfigure(self.cols-1)
        configure['minsize'] = 0
        self.columnconfigure(self.cols,**configure)

        for row in range(self.rows+1):
            self.insert_row(row)

class LineFrame(tk.Frame):

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

        self.is_col = kwargs.pop('is_col',None)

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

    def bind_enter(self):
        if self.is_col:
            if int(self.grid_info()['column']):
                self.bind('<Enter>',self.tableline_enter_col)
            else:
                self.bind('<Enter>',self.tableline_enter_insert_col)
        else:
            if int(self.grid_info()['row']):
                self.bind('<Enter>',self.tableline_enter_row)
            else:
                self.bind('<Enter>',self.tableline_enter_insert_row)



    # these are double defined, but nearly identical may be we not only a single definition
    def tableline_enter_col(self,event=None):
        for element in self.master.table_frames:
            element.config( bg = 'black')
            element.bind_enter()

        self.master.focus()
        self.bind('<Leave>',self.tableline_leave)
        self.lift()
        self.config( cursor = 'sb_h_double_arrow', bg = 'lightgreen')

    def tableline_enter_row(self,event=None):
        for element in self.master.table_frames:
            element.config( bg = 'black')
            element.bind_enter()

        self.master.focus()
        self.bind('<Leave>',self.tableline_leave)
        self.lift()
        self.config( cursor = 'sb_v_double_arrow', bg = 'lightgreen')

    def tableline_enter_insert_col(self,event=None):
        for element in self.master.table_frames:
            element.config( bg = 'black')
            element.bind_enter()
        self.master.focus()
        self.bind('<Leave>',self.tableline_leave)
        self.lift()
        self.config( cursor = 'plus', bg = 'lightgreen')

    def tableline_enter_insert_row(self,event=None):
        for element in self.master.table_frames:
            element.config( bg = 'black')
            element.bind_enter()
        self.master.focus()
        self.bind('<Leave>',self.tableline_leave)
        self.lift()
        self.config( cursor = 'plus', bg = 'lightgreen')

    # ========================================================        

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

    def tableline_startmove_row(self,event = None):
        print('is moving')
        self.move_started = True
        self.button_release = self.tableline_mark_row
        self.enter = self.tableline_enter_row
        self.startmove = self.tableline_startmove_row
        self.unbind('<Enter>')
        self.unbind('<Leave>')
        self.bind('<ButtonRelease-1>',self.move_release)

    def tableline_startmove_col(self,event = None):
        print('is moving')
        self.move_started = True
        self.button_release = self.tableline_mark_col
        self.enter = self.tableline_enter_col
        self.startmove = self.tableline_startmove_col
        self.unbind('<Enter>')
        self.unbind('<Leave>')
        self.bind('<ButtonRelease-1>',self.move_release)

    def tableline_mark_col(self,event = None):
        if not self.move_started:
            self.unbind('<Leave>')
            self.unbind('<Enter>')
            for element in self.master.table_frames:
                element.config( bg = 'black')
            self.lift()
            self.config( cursor = '', bg = 'blue')
            self.focus()
            self.bind('<Insert>',self.insert)
            self.bind('<Delete>',self.delete)
            self.row_col = int(self.grid_info()['column'])
            self.grid_key = 'column'
            self.grid_configure = self.master.columnconfigure
            self.row_col_default = self.master.col_default
            self.insert_row_col = self.master.insert_col
            
        
    def tableline_mark_row(self,event = None):
        if not self.move_started:
            self.unbind('<Leave>')
            self.unbind('<Enter>')
            for element in self.master.table_frames:
                element.config( bg = 'black')
            self.lift()
            self.config( cursor = '', bg = 'blue')
            self.focus()
            self.bind('<Insert>',self.insert)
            self.bind('<Delete>',self.delete)
            self.row_col = int(self.grid_info()['row'])
            self.grid_key = 'row'
            self.grid_configure = self.master.rowconfigure
            self.row_col_default = self.master.row_default
            self.insert_row_col = self.master.insert_row
            

    def insert(self,event = None):
        endpos = self.master.cols if self.is_col else self.master.rows
        # if our line is the last one, we don't insert anything
        
        
        children = self.master.winfo_children()
        for pos in range(endpos,self.row_col-1,-1):
            for child in children:
                if int(child.grid_info()[self.grid_key]) == pos:
                    child.grid(**{ self.grid_key : pos+1})
            self.grid_configure(pos+1,**self.grid_configure(pos))

        self.grid_configure(self.row_col,self.row_col_default)
        insert_frame = self.insert_row_col(self.row_col)


        self['bg'] = 'black'
        self.bind_enter()

        if self.is_col:

            self.master.cols += 1
            # increase columnspan for row lines
            for frame in self.master.row_frames:
                frame.grid(column = 0, columnspan = self.master.cols)
            insert_frame.tableline_mark_col()
        else:
            self.master.rows += 1
            # increase rowspan for column lines
            for frame in self.master.col_frames:
                frame.grid(row = 0,rowspan = self.master.rows)
            insert_frame.tableline_mark_row()
            

    def delete(self,event = None):
        endpos = self.master.cols if self.is_col else self.master.rows

        # don't delete anything, if it's the last line
        if self.row_col == endpos:
            return

        # check whether it's the first line or column and whether there is only one line or column
        if self.row_col == 0 and endpos == 1:
            return
        # check whether the current row or column is empty
        children = self.master.winfo_children()
        elements = [ element for element in children if int(element.grid_info()[self.grid_key]) == self.row_col]
        elements.pop(elements.index(self))
        if elements: 
            return

        # ok we have an empty row or column, which isn't the first one, so we first destroy the line frame of this column or line
        if self.is_col:
            for frame in self.master.col_frames:
                if int(frame.grid_info()[self.grid_key]) == self.row_col + 1:
                    self.master.col_frames.pop(self.master.col_frames.index(frame)).destroy()
                    self.master.table_frames.pop(self.master.table_frames.index(frame)).destroy()
                    break

            self.master.cols -= 1
            # decrease columnspan for row lines
            for frame in self.master.row_frames:
                frame.grid(column = 0, columnspan = self.master.cols)

        else:
            for frame in self.master.row_frames:
                if int(frame.grid_info()[self.grid_key]) == self.row_col + 1:
                    self.master.row_frames.pop(self.master.row_frames.index(frame)).destroy()
                    self.master.table_frames.pop(self.master.table_frames.index(frame)).destroy()
                    break

            self.master.rows -= 1
            # increase rowspan for column lines
            for frame in self.master.col_frames:
                frame.grid(row = 0,rowspan = self.master.rows)


        #so we move the widgets one row or colum down
        children = self.master.winfo_children()
        for pos in range(self.row_col,endpos):
            for child in children:
                if int(child.grid_info()[self.grid_key]) == pos+1:
                    child.grid(**{ self.grid_key : pos })
            self.grid_configure(pos,**self.grid_configure(pos+1))
        self.grid_configure(endpos,minsize = 0, pad = 0, weight = 0)


    def move_release(self,event = None):
        self.bind('<B1-Motion>',self.startmove)
        self.bind('<Enter>',self.enter)
        self.bind('<ButtonRelease-1>',self.button_release)
        self.tableline_leave()
        self.move_started = False



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

Die schwarze Linie war nicht gut, es könnten ja Widgets schwarzen Hintergrund haben. Aber mit relief = 'raised' sieht es doch gut aus, oder?

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.col_default={ 'minsize' : 75, 'pad' : 0, 'weight' : 0 }
        self.row_default={ 'minsize' : 25, 'pad' : 0, 'weight' : 1 }

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

        self.green = '#50d090'
        self.gray = '#d9d9d9'
        self.blue = 'blue'


    def insert_col(self,col):
        frame = LineFrame(self,is_col = True)
        frame.grid(column = col,row = 0, rowspan = self.rows+1, sticky = 'nsw')
        if col:
            frame.bind('<Enter>',frame.tableline_enter_col)
            frame.bind('<B1-Motion>',frame.tableline_startmove_col)
        else:
            frame.bind('<Enter>',frame.tableline_enter_insert_col)
            
        frame.bind('<ButtonRelease-1>',frame.tableline_mark_col)
        self.table_frames.append(frame)
        self.col_frames.append(frame)
        return frame


    def insert_row(self,row):        
        frame = LineFrame(self,is_col = False)
        frame.grid(row = row, column = 0, columnspan = self.cols+1, sticky = 'wen')
        if row:
            frame.bind('<Enter>',frame.tableline_enter_row)
            frame.bind('<B1-Motion>',frame.tableline_startmove_row)
        else:
            frame.bind('<Enter>',frame.tableline_enter_insert_row)

        frame.bind('<ButtonRelease-1>',frame.tableline_mark_row)
        self.table_frames.append(frame)
        self.row_frames.append(frame)
        return frame

    def insert_table(self,event = None):
        for col in range(self.cols+1):
            self.insert_col(col)
        configure = self.columnconfigure(self.cols-1)
        configure['minsize'] = 0
        self.columnconfigure(self.cols,**configure)

        for row in range(self.rows+1):
            self.insert_row(row)

class LineFrame(tk.Frame):

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

        self.green = '#50d090'
        self.gray = '#d9d9d9'
        self.blue = 'blue'

        self.is_col = kwargs.pop('is_col',None)
        
        kwargs['bg'] = self.gray
        kwargs['bd'] = 2
        kwargs['relief'] = 'raised'
        if self.is_col:
            kwargs['width'] = 6
        else:
            kwargs['height'] = 6
        
        tk.Frame.__init__(self,master,**kwargs)
        self.master = master
        self.move_started = False

    def bind_enter(self):
        if self.is_col:
            if int(self.grid_info()['column']):
                self.bind('<Enter>',self.tableline_enter_col)
            else:
                self.bind('<Enter>',self.tableline_enter_insert_col)
        else:
            if int(self.grid_info()['row']):
                self.bind('<Enter>',self.tableline_enter_row)
            else:
                self.bind('<Enter>',self.tableline_enter_insert_row)



    # these are double defined, but nearly identical may be we not only a single definition
    def tableline_enter_col(self,event=None):
        for element in self.master.table_frames:
            element.config( bg = self.gray)
            element.bind_enter()

        self.master.focus()
        self.bind('<Leave>',self.tableline_leave)
        self.lift()
        self.config( cursor = 'sb_h_double_arrow', bg = self.green)

    def tableline_enter_row(self,event=None):
        for element in self.master.table_frames:
            element.config( bg = self.gray)
            element.bind_enter()

        self.master.focus()
        self.bind('<Leave>',self.tableline_leave)
        self.lift()
        self.config( cursor = 'sb_v_double_arrow', bg = self.green)

    def tableline_enter_insert_col(self,event=None):
        for element in self.master.table_frames:
            element.config( bg = self.gray)
            element.bind_enter()
        self.master.focus()
        self.bind('<Leave>',self.tableline_leave)
        self.lift()
        self.config( cursor = 'plus', bg = self.green)

    def tableline_enter_insert_row(self,event=None):
        for element in self.master.table_frames:
            element.config( bg = self.gray)
            element.bind_enter()
        self.master.focus()
        self.bind('<Leave>',self.tableline_leave)
        self.lift()
        self.config( cursor = 'plus', bg = self.green)

    # ========================================================        

    def tableline_leave(self,event=None):
        self.config( cursor = '', bg = self.gray)

    def tableline_startmove_row(self,event = None):
        self.move_started = True
        self.button_release = self.tableline_mark_row
        self.enter = self.tableline_enter_row
        self.startmove = self.tableline_startmove_row
        self.unbind('<Enter>')
        self.unbind('<Leave>')
        self.unbind('<B1-Motion>')
        self.bind('<ButtonRelease-1>',self.move_release)
        # from gridproject
        self.mouse_startpos = self.master.winfo_pointery()
        self.row_col = int(self.grid_info()['row']) - 1
        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.is_endline = self.row_col + 1 == 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.startmove = self.tableline_startmove_row
        self.enter = self.tableline_enter_row
        self.pointer = self.master.winfo_pointery
        self.move()

    def tableline_startmove_col(self,event = None):
        self.move_started = True
        self.button_release = self.tableline_mark_col
        self.enter = self.tableline_enter_col
        self.startmove = self.tableline_startmove_col
        self.unbind('<Enter>')
        self.unbind('<Leave>')
        self.bind('<ButtonRelease-1>',self.move_release)
        self.unbind('<B1-Motion>')

        # from gridproject
        self.mouse_startpos = self.master.winfo_pointerx()
        self.row_col = int(self.grid_info()['column']) -1
        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.is_endline = self.row_col + 1 == 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.startmove = self.tableline_startmove_col
        self.enter = self.tableline_enter_col
        self.pointer = self.master.winfo_pointerx
        self.move()

    def measure_colwidth(self):
        self.begin,top,self.cellsize,height = self.master.grid_bbox(row = 0, column = self.row_col)

    def measure_rowheight(self):
        left,self.begin,width,self.cellsize = self.master.grid_bbox(row = self.row_col, column = 0)

    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 move(self):

        if not self.is_moving:
            self.bind('<B1-Motion>',self.startmove)
            self.bind('<Enter>',self.enter)
            self.bind('<ButtonRelease-1>',self.button_release)
            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.is_endline:
            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)

    def tableline_mark_col(self,event = None):
        if not self.move_started:
            self.unbind('<Leave>')
            self.unbind('<Enter>')
            for element in self.master.table_frames:
                element.config( bg = self.gray)
            self.lift()
            self.config( cursor = '', bg = self.blue)
            self.focus()
            self.bind('<Insert>',self.insert)
            self.bind('<Delete>',self.delete)
            self.row_col = int(self.grid_info()['column'])
            self.grid_key = 'column'
            self.grid_configure = self.master.columnconfigure
            self.row_col_default = self.master.col_default
            self.insert_row_col = self.master.insert_col
            
        
    def tableline_mark_row(self,event = None):
        if not self.move_started:
            self.unbind('<Leave>')
            self.unbind('<Enter>')
            for element in self.master.table_frames:
                element.config( bg = self.gray)
            self.lift()
            self.config( cursor = '', bg = self.blue)
            self.focus()
            self.bind('<Insert>',self.insert)
            self.bind('<Delete>',self.delete)
            self.row_col = int(self.grid_info()['row'])
            self.grid_key = 'row'
            self.grid_configure = self.master.rowconfigure
            self.row_col_default = self.master.row_default
            self.insert_row_col = self.master.insert_row
            

    def insert(self,event = None):
        endpos = self.master.cols if self.is_col else self.master.rows
        # if our line is the last one, we don't insert anything
        
        
        children = self.master.winfo_children()
        for pos in range(endpos,self.row_col-1,-1):
            for child in children:
                if int(child.grid_info()[self.grid_key]) == pos:
                    child.grid(**{ self.grid_key : pos+1})
            self.grid_configure(pos+1,**self.grid_configure(pos))

        self.grid_configure(self.row_col,self.row_col_default)
        insert_frame = self.insert_row_col(self.row_col)


        self['bg'] = self.gray
        self.bind_enter()

        if self.is_col:

            self.master.cols += 1
            # increase columnspan for row lines
            for frame in self.master.row_frames:
                frame.grid(column = 0, columnspan = self.master.cols)
            insert_frame.tableline_mark_col()
        else:
            self.master.rows += 1
            # increase rowspan for column lines
            for frame in self.master.col_frames:
                frame.grid(row = 0,rowspan = self.master.rows)
            insert_frame.tableline_mark_row()
            

    def delete(self,event = None):
        endpos = self.master.cols if self.is_col else self.master.rows

        # don't delete anything, if it's the last line
        if self.row_col == endpos:
            return

        # check whether it's the first line or column and whether there is only one line or column
        if self.row_col == 0 and endpos == 1:
            return
        # check whether the current row or column is empty
        children = self.master.winfo_children()
        elements = [ element for element in children if int(element.grid_info()[self.grid_key]) == self.row_col]
        elements.pop(elements.index(self))
        if elements: 
            return

        # ok we have an empty row or column, which isn't the first one, so we first destroy the line frame of this column or line
        if self.is_col:
            for frame in self.master.col_frames:
                if int(frame.grid_info()[self.grid_key]) == self.row_col + 1:
                    self.master.col_frames.pop(self.master.col_frames.index(frame)).destroy()
                    self.master.table_frames.pop(self.master.table_frames.index(frame)).destroy()
                    break

            self.master.cols -= 1
            # decrease columnspan for row lines
            for frame in self.master.row_frames:
                frame.grid(column = 0, columnspan = self.master.cols)

        else:
            for frame in self.master.row_frames:
                if int(frame.grid_info()[self.grid_key]) == self.row_col + 1:
                    self.master.row_frames.pop(self.master.row_frames.index(frame)).destroy()
                    self.master.table_frames.pop(self.master.table_frames.index(frame)).destroy()
                    break

            self.master.rows -= 1
            # increase rowspan for column lines
            for frame in self.master.col_frames:
                frame.grid(row = 0,rowspan = self.master.rows)


        #so we move the widgets one row or colum down
        children = self.master.winfo_children()
        for pos in range(self.row_col,endpos):
            for child in children:
                if int(child.grid_info()[self.grid_key]) == pos+1:
                    child.grid(**{ self.grid_key : pos })
            self.grid_configure(pos,**self.grid_configure(pos+1))
        self.grid_configure(endpos,minsize = 0, pad = 0, weight = 0)


    def move_release(self,event = None):
        self.is_moving = False
        self.tableline_leave()
        self.move_started = False


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

Zeile 351 genügt nicht für die erste Spalte oder Zeile:

Code: Alles auswählen

        # diese Zeile 351 fliegt raus
        elements.pop(elements.index(self))

        # stattdessen wird Zeile 350 ergänzt zu:
        elements = [ element for element in children if int(element.grid_info()[self.grid_key]) == self.row_col and element not in self.master.table_frames]
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Damit es jemand ausprobieren kann. Ich überlege mir das Grid Konzept für meinen GuiDesigner.

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.col_default={ 'minsize' : 75, 'pad' : 0, 'weight' : 0 }
        self.row_default={ 'minsize' : 25, 'pad' : 0, 'weight' : 1 }

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


    def insert_col(self,col):
        frame = LineFrame(self,is_col = True)
        frame.grid(column = col,row = 0, rowspan = self.rows+1, sticky = 'nsw')
        if col:
            frame.bind('<Enter>',frame.tableline_enter_col)
            frame.bind('<B1-Motion>',frame.tableline_startmove_col)
        else:
            frame.bind('<Enter>',frame.tableline_enter_insert_col)
            
        frame.bind('<ButtonRelease-1>',frame.tableline_mark_col)
        self.table_frames.append(frame)
        self.col_frames.append(frame)
        return frame


    def insert_row(self,row):        
        frame = LineFrame(self,is_col = False)
        frame.grid(row = row, column = 0, columnspan = self.cols+1, sticky = 'wen')
        if row:
            frame.bind('<Enter>',frame.tableline_enter_row)
            frame.bind('<B1-Motion>',frame.tableline_startmove_row)
        else:
            frame.bind('<Enter>',frame.tableline_enter_insert_row)

        frame.bind('<ButtonRelease-1>',frame.tableline_mark_row)
        self.table_frames.append(frame)
        self.row_frames.append(frame)
        return frame

    def insert_table(self,event = None):
        for col in range(self.cols+1):
            self.insert_col(col)
        configure = self.columnconfigure(self.cols-1)
        configure['minsize'] = 0
        self.columnconfigure(self.cols,**configure)

        for row in range(self.rows+1):
            self.insert_row(row)

class LineFrame(tk.Frame):

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

        self.green = '#50d090'
        self.gray = '#d9d9d9'
        self.blue = 'blue'

        self.is_col = kwargs.pop('is_col',None)
        
        kwargs['bg'] = self.gray
        kwargs['bd'] = 2
        kwargs['relief'] = 'raised'
        if self.is_col:
            kwargs['width'] = 6
        else:
            kwargs['height'] = 6
        
        tk.Frame.__init__(self,master,**kwargs)
        self.master = master
        self.move_started = False

    def bind_enter(self):
        if self.is_col:
            if int(self.grid_info()['column']):
                self.bind('<Enter>',self.tableline_enter_col)
            else:
                self.bind('<Enter>',self.tableline_enter_insert_col)
        else:
            if int(self.grid_info()['row']):
                self.bind('<Enter>',self.tableline_enter_row)
            else:
                self.bind('<Enter>',self.tableline_enter_insert_row)



    # these are double defined, but nearly identical may be we not only a single definition
    def tableline_enter_col(self,event=None):
        for element in self.master.table_frames:
            element.config( bg = self.gray)
            element.bind_enter()

        self.master.focus()
        self.bind('<Leave>',self.tableline_leave)
        self.lift()
        self.config( cursor = 'sb_h_double_arrow', bg = self.green)

    def tableline_enter_row(self,event=None):
        for element in self.master.table_frames:
            element.config( bg = self.gray)
            element.bind_enter()

        self.master.focus()
        self.bind('<Leave>',self.tableline_leave)
        self.lift()
        self.config( cursor = 'sb_v_double_arrow', bg = self.green)

    def tableline_enter_insert_col(self,event=None):
        for element in self.master.table_frames:
            element.config( bg = self.gray)
            element.bind_enter()
        self.master.focus()
        self.bind('<Leave>',self.tableline_leave)
        self.lift()
        self.config( cursor = 'plus', bg = self.green)

    def tableline_enter_insert_row(self,event=None):
        for element in self.master.table_frames:
            element.config( bg = self.gray)
            element.bind_enter()
        self.master.focus()
        self.bind('<Leave>',self.tableline_leave)
        self.lift()
        self.config( cursor = 'plus', bg = self.green)

    # ========================================================        

    def tableline_leave(self,event=None):
        self.config( cursor = '', bg = self.gray)

    def tableline_startmove_row(self,event = None):
        self.move_started = True
        self.button_release = self.tableline_mark_row
        self.enter = self.tableline_enter_row
        self.startmove = self.tableline_startmove_row
        self.unbind('<Enter>')
        self.unbind('<Leave>')
        self.unbind('<B1-Motion>')
        self.bind('<ButtonRelease-1>',self.move_release)
        # from gridproject
        self.mouse_startpos = self.master.winfo_pointery()
        self.row_col = int(self.grid_info()['row']) - 1
        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.is_endline = self.row_col + 1 == 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.startmove = self.tableline_startmove_row
        self.enter = self.tableline_enter_row
        self.pointer = self.master.winfo_pointery
        self.move()

    def tableline_startmove_col(self,event = None):
        self.move_started = True
        self.button_release = self.tableline_mark_col
        self.enter = self.tableline_enter_col
        self.startmove = self.tableline_startmove_col
        self.unbind('<Enter>')
        self.unbind('<Leave>')
        self.bind('<ButtonRelease-1>',self.move_release)
        self.unbind('<B1-Motion>')

        # from gridproject
        self.mouse_startpos = self.master.winfo_pointerx()
        self.row_col = int(self.grid_info()['column']) -1
        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.is_endline = self.row_col + 1 == 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.startmove = self.tableline_startmove_col
        self.enter = self.tableline_enter_col
        self.pointer = self.master.winfo_pointerx
        self.move()

    def measure_colwidth(self):
        self.begin,top,self.cellsize,height = self.master.grid_bbox(row = 0, column = self.row_col)

    def measure_rowheight(self):
        left,self.begin,width,self.cellsize = self.master.grid_bbox(row = self.row_col, column = 0)

    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 move(self):

        if not self.is_moving:
            self.bind('<B1-Motion>',self.startmove)
            self.bind('<Enter>',self.enter)
            self.bind('<ButtonRelease-1>',self.button_release)
            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.is_endline:
            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)

    def tableline_mark_col(self,event = None):
        if not self.move_started:
            self.unbind('<Leave>')
            self.unbind('<Enter>')
            for element in self.master.table_frames:
                element.config( bg = self.gray)
            self.lift()
            self.config( cursor = '', bg = self.blue)
            self.focus()
            self.bind('<Insert>',self.insert)
            self.bind('<Delete>',self.delete)
            self.row_col = int(self.grid_info()['column'])
            self.grid_key = 'column'
            self.grid_configure = self.master.columnconfigure
            self.row_col_default = self.master.col_default
            self.insert_row_col = self.master.insert_col
            
        
    def tableline_mark_row(self,event = None):
        if not self.move_started:
            self.unbind('<Leave>')
            self.unbind('<Enter>')
            for element in self.master.table_frames:
                element.config( bg = self.gray)
            self.lift()
            self.config( cursor = '', bg = self.blue)
            self.focus()
            self.bind('<Insert>',self.insert)
            self.bind('<Delete>',self.delete)
            self.row_col = int(self.grid_info()['row'])
            self.grid_key = 'row'
            self.grid_configure = self.master.rowconfigure
            self.row_col_default = self.master.row_default
            self.insert_row_col = self.master.insert_row
            

    def insert(self,event = None):
        endpos = self.master.cols if self.is_col else self.master.rows
        # if our line is the last one, we don't insert anything
        
        
        children = self.master.winfo_children()
        for pos in range(endpos,self.row_col-1,-1):
            for child in children:
                if int(child.grid_info()[self.grid_key]) == pos:
                    child.grid(**{ self.grid_key : pos+1})
            self.grid_configure(pos+1,**self.grid_configure(pos))

        self.grid_configure(self.row_col,self.row_col_default)
        insert_frame = self.insert_row_col(self.row_col)


        self['bg'] = self.gray
        self.bind_enter()

        if self.is_col:

            self.master.cols += 1
            # increase columnspan for row lines
            for frame in self.master.row_frames:
                frame.grid(column = 0, columnspan = self.master.cols)
            insert_frame.tableline_mark_col()
        else:
            self.master.rows += 1
            # increase rowspan for column lines
            for frame in self.master.col_frames:
                frame.grid(row = 0,rowspan = self.master.rows)
            insert_frame.tableline_mark_row()
            

    def delete(self,event = None):
        endpos = self.master.cols if self.is_col else self.master.rows

        # don't delete anything, if it's the last line
        if self.row_col == endpos:
            return

        # check whether it's the first line or column and whether there is only one line or column
        if self.row_col == 0 and endpos == 1:
            return

        # check whether the current row or column is empty
        children = self.master.winfo_children()
        elements = [ element for element in children if int(element.grid_info()[self.grid_key]) == self.row_col and element not in self.master.table_frames]

        if elements: 
            return

        # ok we have an empty row or column, which isn't the first one, so we first destroy the line frame of this column or line
        if self.is_col:
            for frame in self.master.col_frames:
                if int(frame.grid_info()[self.grid_key]) == self.row_col + 1:
                    self.master.col_frames.pop(self.master.col_frames.index(frame)).destroy()
                    self.master.table_frames.pop(self.master.table_frames.index(frame)).destroy()
                    break

            self.master.cols -= 1
            # decrease columnspan for row lines
            for frame in self.master.row_frames:
                frame.grid(column = 0, columnspan = self.master.cols)

        else:
            for frame in self.master.row_frames:
                if int(frame.grid_info()[self.grid_key]) == self.row_col + 1:
                    self.master.row_frames.pop(self.master.row_frames.index(frame)).destroy()
                    self.master.table_frames.pop(self.master.table_frames.index(frame)).destroy()
                    break

            self.master.rows -= 1
            # increase rowspan for column lines
            for frame in self.master.col_frames:
                frame.grid(row = 0,rowspan = self.master.rows)


        #so we move the widgets one row or colum down
        children = self.master.winfo_children()
        for pos in range(self.row_col,endpos):
            for child in children:
                if int(child.grid_info()[self.grid_key]) == pos+1:
                    child.grid(**{ self.grid_key : pos })
            self.grid_configure(pos,**self.grid_configure(pos+1))
        self.grid_configure(endpos,minsize = 0, pad = 0, weight = 0)


    def move_release(self,event = None):
        self.is_moving = False
        self.tableline_leave()
        self.move_started = False


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