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()