停止窗口抖动

问题描述 投票:0回答:1

当您单击并拖动鼠标时,窗口会自行调整大小。问题是从右向左拖动时窗口的右侧会跳动。此问题仅发生在 Windows 中,而不是 Linux 中。我不确定 MacOS,因为我无法访问运行它的计算机。不过如果知道的话那就太好了!

更新:

我已经根据下面建议的

jizhihaoSAMA
更新了代码,现在它在Windows和Linux中运行良好,但不确定MacOS!

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

使用Python

3

python python-3.x tkinter
1个回答
0
投票

使用 platform.startswith('linux') 调整了 Linux 的平台检查

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.startswith('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

        # Constrain x and y within widget boundaries
        if x < root_x:
            x = root_x
        elif x > root_x + wdg_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}')

        # Debugging output
        print(f"Pointer (x, y): ({x}, {y}), Origin (ox, oy): ({widget.origin_x}, {widget.origin_y}), Geometry: {self.geometry()}")

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)
        
        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"))
        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()
© www.soinside.com 2019 - 2024. All rights reserved.