The default handler of pannedwindow is replaced by a rectangle with the color and size that the user wants.
It's similar to jquery Layout plugin: http://layout.jquery-dev.com/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | # Author: Miguel Martinez Lopez
#
# Uncomment the next line to see my email
# print("Author's email: %s"%"61706c69636163696f6e616d656469646140676d61696c2e636f6d".decode("hex"))
try:
from Tkinter import Frame, PanedWindow as Tk_PanedWindow
from ttk import Label
from Tkconstants import HORIZONTAL, VERTICAL
except ImportError:
from tkinter import Frame, PanedWindow as Tk_PanedWindow
from tkinter.ttk import Label
from tkinter.constants import HORIZONTAL, VERTICAL
class Handle(Frame):
def __init__(self, panedwindow, sash_index, disallow_dragging=False, on_click=None, **kw):
image = kw.pop("image", None)
Frame.__init__(self, panedwindow, class_="Handle", **kw)
self._sash_index = sash_index
if image:
self._event_area = Label(self, image=image)
self._event_area.pack()
else:
self._event_area = self
self._center = int(self._event_area.winfo_reqwidth()/2), int(self._event_area.winfo_reqheight()/2)
if disallow_dragging:
if on_click:
self._event_area.bind('<Button-1>', lambda event: on_click())
else:
self._event_area.bind('<Button-1>', self._initiate_motion)
self._event_area.bind('<B1-Motion>', self._on_dragging)
self._event_area.bind('<ButtonRelease-1>', self.master._on_release)
def _initiate_motion(self, event) :
self.master._active_sash = self._sash_index
self._dx = event.x
self._dy = event.y
@property
def sash_index(self):
return self._sash_index
def _on_dragging(self):
raise NotImplementedError
class Vertical_Handle(Handle):
def _on_dragging(self, event):
y = event.y_root - self.master.winfo_rooty() - self._dy
self.master.sash_place(self._sash_index, 1, y)
self.master._update_position_all_handles()
class Horizontal_Handle(Handle):
def _on_dragging(self, event):
x = event.x_root - self.master.winfo_rootx() - self._dx
self.master.sash_place(self._sash_index, x, 1)
self.master._update_position_all_handles()
class PanedWindow(Tk_PanedWindow):
def __init__(self, master, color="gray", size=60, sashpad=2, disallow_dragging=False, on_click=None, image=None, cursor=None, opaqueresize=True):
Tk_PanedWindow.__init__(self, master, showhandle = False, orient=self.ORIENT, sashpad=sashpad, opaqueresize=opaqueresize)
self._active_sash = None
self._on_click = on_click
self._image = image
self._color = color
self._cursor = cursor
self._configure_callbacks = []
if not opaqueresize:
disallow_dragging = True
self._disallow_dragging = disallow_dragging
self._handle_list = []
self._list_of_panes = []
if self.ORIENT == VERTICAL:
self._width= size
self._height = 2*sashpad
else:
self._width = 2*sashpad
self._height= size
if opaqueresize:
self.bind('<Button-1>', self._on_mark_sash)
self.bind('<B1-Motion>', self._on_drag_sash)
self.bind('<ButtonRelease-1>', self._on_release)
def _on_release(self, event):
handle_index = self._active_sash
callback_id1 = self._list_of_panes[handle_index+1].bind("<Configure>", lambda event, handle_index=handle_index: self._on_configure_pane(handle_index), "+")
callback_id2 = self._list_of_panes[handle_index].bind("<Configure>", lambda event, handle_index=handle_index: self._on_configure_pane(handle_index), "+")
self._configure_callbacks[handle_index] = (callback_id1,callback_id2)
self._active_sash = None
def _on_drag_sash(self, event):
coord_x = event.x
coord_y = event.y
Tk_PanedWindow.sash_place(self, self._active_sash, coord_x, coord_y)
self._update_position_all_handles()
return "break"
def add(self, pane, **kwargs):
Tk_PanedWindow.add(self, pane, **kwargs)
self._list_of_panes.append(pane)
quantity_of_panes = len(self._list_of_panes)
if quantity_of_panes >= 2:
handle_index = quantity_of_panes-2
handle = self.HANDLE_CLASS(self, handle_index, bg=self._color, height=self._height, width=self._width, cursor = self._cursor, disallow_dragging=self._disallow_dragging, on_click=self._on_click, image=self._image)
if self.ORIENT == VERTICAL:
handle.place(relx=0.5, anchor="c")
else:
handle.place(rely=0.5, anchor="c")
self._handle_list.append(handle)
callback_id1 = pane.bind("<Configure>", lambda event, handle_index=handle_index: self._on_configure_pane(handle_index), "+")
callback_id2 = self._list_of_panes[handle_index].bind("<Configure>", lambda event, handle_index=handle_index: self._on_configure_pane(handle_index), "+")
self._configure_callbacks.append((callback_id1,callback_id2))
def _on_mark_sash(self, event):
identity = self.identify(event.x, event.y)
if len(identity) ==2:
self._active_sash= handle_index = identity[0]
callback_id1,callback_id2 = self._configure_callbacks[handle_index]
self._list_of_panes[handle_index+1].unbind(callback_id1)
self._list_of_panes[handle_index].unbind(callback_id2)
else:
self._active_sash = None
class Vertical_PanedWindow(PanedWindow):
ORIENT = VERTICAL
HANDLE_CLASS = Vertical_Handle
def _on_configure_pane(self, sash_index):
x,y = Tk_PanedWindow.sash_coord(self, sash_index)
self._handle_list[sash_index].place(y=y)
def _update_position_all_handles(self):
for sash_index, handle in enumerate(self._handle_list):
x,y = Tk_PanedWindow.sash_coord(self, sash_index)
handle.place(y=y)
class Horizontal_PanedWindow(PanedWindow):
ORIENT = HORIZONTAL
HANDLE_CLASS = Horizontal_Handle
def _update_position_all_handles(self):
for sash_index, handle in enumerate(self._handle_list):
x,y = Tk_PanedWindow.sash_coord(self, sash_index)
handle.place(x=x)
def _on_configure_pane(self, sash_index):
x,y = Tk_PanedWindow.sash_coord(self, sash_index)
self._handle_list[sash_index].place(x=x)
if __name__ == "__main__":
try:
from Tkinter import Tk, PhotoImage
except ImportError:
from tkinter import Tk
root = Tk()
# Use for example this image for horizontal panedwindow
# image = PhotoImage(data="R0lGODlhAwAYAPIAAEBAQGBgYICAgLu7u8zMzAAAAAAAAAAAACH5BAEAAAUALAAAAAADABgAAAMXCCFRI4OUSRVzUNJp24sbt3hZWHQYOCUAOw==")
image = PhotoImage(data="R0lGODlhGAADAPIFAEBAQGBgYICAgLu7u8zMzAAAAAAAAAAAACH5BAEAAAUALAAAAAAYAAMAAAMaWBJQym61N2UZJTisb96fpxGD4JBmgZ4lKyQAOw==")
panedwindow = Vertical_PanedWindow(root, sashpad = 3, image=image)
panedwindow.pack(fill="both", expand=True)
for color in ("red", "blue","green"):
frame = Frame(panedwindow, width=200, height=200, bg=color)
panedwindow.add(frame, stretch="always")
root.mainloop()
|