I have a window that sizes itself when you click and drag the mouse. The problem is the right side of the window jumps around when dragging from right to left. This issue only happens in Windows not Linux I'm not sure about MaxOS because I don't have access to a machine that runs it.It would be good to know though! Does anyone know how to fix this?
UPDATE: I have updated the code according to what "jizhihaoSAMA" suggested below and now it works fine in Windows and Linux not sure about MacOS still!
import tkinter as tk
import tkinter.ttk as ttk
import tkinter.font as tkfont
from sys import platform
class Selector(tk.Toplevel):
def __init__(self, parent, **kwargs):
super().__init__(parent, **kwargs)
self.geometry('0x0+0+0')
self.overrideredirect(True)
if platform == 'linux':
self.wait_visibility(self)
self.wm_attributes('-alpha', 0.2)
self.wm_attributes("-topmost", True)
self.config(bg='#00aaff')
self.update()
self.lift()
self.linespace = self.master.linespace
self.heading_padding = parent.style.lookup('Treeview.Heading', 'padding')
self.theme = parent.style.theme_use()
self.style = parent.style
def select(self, _):
widget = self.focus_get()
master = widget.winfo_toplevel()
if widget == master:
return
padding = 0 if not isinstance(widget, ttk.Treeview) else \
int(str(self.style.lookup('Treeview.Heading', 'padding')[0]))
tv_padding = padding*2 if isinstance(widget, ttk.Treeview) else 0
border_width = 3 if self.theme == 'default' else 6
linespace = self.linespace if isinstance(widget, ttk.Treeview) else 0
x, y = master.winfo_pointerxy()
root_x = widget.winfo_rootx()
root_y = widget.winfo_rooty()+linespace+tv_padding+border_width
wdg_width = widget.winfo_width()
wdg_height = widget.winfo_height()-linespace-tv_padding-border_width
if x < root_x:
x = root_x
elif x > root_x + widget.winfo_width():
x = root_x + wdg_width
if y < root_y:
y = root_y
elif y > root_y + wdg_height:
y = root_y + wdg_height
origin_x = widget.origin_x if x > widget.origin_x else x
origin_y = widget.origin_y if y > widget.origin_y else y
self.geometry(f'{abs(x-widget.origin_x)}x{abs(y-widget.origin_y)}+{origin_x}+{origin_y}')
class App(tk.Tk):
def __init__(self):
super().__init__()
self.rowconfigure(0, weight=1)
self.rowconfigure(1, weight=1)
self.columnconfigure(0, weight=1)
self.columnconfigure(1, weight=1)
self.title('Selector Demo')
font = tkfont.nametofont('TkDefaultFont')
self.linespace = font.metrics('linespace')
self.style = ttk.Style()
self.style.theme_use('clam')
self.style.configure('Treeview.Heading', padding=5)
self.style.configure('Treeview', rowheight=self.linespace+7)
self.selector = Selector(self)
var = tk.StringVar()
var.set(('List Item 1', 'List Item 2', 'List Item 3', 'List Item 4', 'List Item 5'))
self.lb = tk.Listbox(self, listvariable=var, selectmode=tk.EXTENDED, width=50, height=15)
self.lb.grid(padx=20, pady=20, row=0, column=0)
tree = ttk.Treeview(self)
tree["columns"] = ("one", "two", "three")
tree.column("#0", width=120, minwidth=3, stretch=tk.NO)
tree.column("one", width=150, minwidth=3, stretch=tk.NO)
tree.column("two", width=80, minwidth=3)
tree.column("three", width=80, minwidth=50, stretch=tk.NO)
tree.heading("#0", text="Name", anchor=tk.W)
tree.heading("one", text="Date modified", anchor=tk.W)
tree.heading("two", text="Type", anchor=tk.W)
tree.heading("three", text="Size", anchor=tk.W)
# Level 1
folder1 = tree.insert("", 1, text="Folder 1", open=1, values=("23-Jun-17 11:05", "File folder", ""))
tree.insert("", 2, text="text_file.txt", values=("23-Jun-17 11:25", "TXT file", "1 KB"))
# # Level 2
tree.insert(folder1, "end", text="photo1.png", values=("23-Jun-17 11:28", "PNG file", "2.6 KB"))
tree.insert(folder1, "end", text="photo2.png", values=("23-Jun-17 11:29", "PNG file", "3.2 KB"))
tree.insert(folder1, "end", text="photo3.png", values=("23-Jun-17 11:30", "PNG file", "3.1 KB"))
tree.grid(padx=20, pady=20, row=0, column=1)
self.tb = tk.Text(self, height=10)
self.tb.grid(pady=(0, 20), columnspan=2)
self.tb.insert(tk.END, "Just a text Widget\nin two lines\n")
self.tb.cursor = self.tb.cget('cursor')
self.bind('<Button-1>', self.button_press)
self.bind('<ButtonRelease-1>', self.button_release)
def button_press(self, event):
wdg = event.widget
wdg.focus_set()
if isinstance(wdg, tk.Text):
wdg.config(cursor='arrow')
self.selector.geometry('0x0+0+0')
wdg.origin_x, wdg.origin_y = wdg.winfo_pointerxy()
self.bind('<Motion>', self.selector.select)
def button_release(self, event):
wdg = event.widget
if isinstance(wdg, tk.Text) and hasattr(wdg, 'cursor'):
wdg.config(cursor=wdg.cursor)
self.selector.geometry('0x0+0+0')
self.unbind('<Motion>')
def main():
app = App()
app.mainloop()
if __name__ == '__main__':
main()