#StackBounty: #python #tkinter How to stop window jitter

Bounty: 50

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):
        self.offset = kwargs.pop('offset', (0, 0, 0, 0))
        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()

        font = tkfont.nametofont('TkDefaultFont')
        self.linespace = font.metrics('linespace')+2

    def select(self, _):
        widget = self.focus_get()
        master = self.nametowidget(widget.winfo_toplevel())
        if widget == master:
            if not isinstance(widget, ttk.Treeview) and not isinstance(widget, tk.Listbox):
                return

        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
        wdg_width = widget.winfo_width()
        wdg_height = widget.winfo_height()-linespace

        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.columnconfigure(0, weight=1)
        self.columnconfigure(1, weight=1)
        self.title('Selector Demo')
        self.selector = Selector(self)

        var = tk.StringVar()
        var.set((1, 2, 3, 4))
        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.update_idletasks()

        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()
        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, _):
        self.selector.geometry('0x0+0+0')
        self.unbind('<Motion>')


def main():
    app = App()
    app.mainloop()


if __name__ == '__main__':
    main()


Get this bounty!!!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.