通过在MSWindows下调整大小来解决性能问题

2024-09-28 19:05:09 发布

您现在位置:Python中文网/ 问答频道 /正文

受这个question的启发,我想为我的根窗口编写我自己的大小调整函数。 但是我注意到我的代码显示了一些性能问题。如果您快速调整它的大小,您可以看到窗口没有如我所愿找到其高度提示,它会“结巴”。(更像是一个摆动)

有人知道为什么会这样吗?我最好的猜测是tkinter事件处理程序对它来说太慢了。 也许我做的数学不是最快的方法

也许我应该说我在不同的地方试过几次。我尝试过的另一种方法是使用after方法,但它使情况变得更糟

下面是一个示例代码:

import tkinter as tk


class FloatingWindow(tk.Tk):
    def __init__(self):
        super().__init__()
        self.overrideredirect(True)
        self.center()

        self.label = tk.Label(self, text="Grab the upper-right corner to resize")
        self.label.pack(side="top", fill="both", expand=True)

        self.grip2 = tk.Label(self,bg='blue')
        self.grip2.place(relx=1.0, rely=0, anchor="ne")
        self.grip2.bind("<B1-Motion>",self.OnMotion)

    def OnMotion(self, event):
        abs_x = self.winfo_pointerx() - self.winfo_rootx()
        abs_y = self.winfo_pointery() - self.winfo_rooty()
        if abs_x >0:
            x = self.winfo_rootx()
            y = self.winfo_rooty()+abs_y
            height = self.winfo_height()-abs_y
            if height >0:
                self.geometry("%dx%d+%d+%d" % (abs_x,height,
                                               x,y))
            
        
    def center(self):
        width = 300
        height = 300
        screen_width = self.winfo_screenwidth()
        screen_height = self.winfo_screenheight()
        x_coordinate = (screen_width/2) - (width/2)
        y_coordinate = (screen_height/2) - (height/2)

        self.geometry("%dx%d+%d+%d" % (width, height,
                                       x_coordinate, y_coordinate))

app=FloatingWindow()
app.mainloop()

full example

更新

似乎性能问题与微软有关,而且是一个well known issue让大多数微软开发人员疯狂的问题

抖动/闪烁/跳跃

enter image description here

黑色边框

enter image description here

双图像/快速闪烁\跳转

enter image description here

我的mashine是:

Windows 10 Home; x64-base,Intel(R) Core(TM) i3-2120 @ 3.30GHz, 3300 MHz, 2Cores

Python 3.7.2 and tkinter 8.6


Tags: 方法代码selfcoordinatetkinterdefabs性能
2条回答

我能够通过在OnMotion方法的开头添加update()函数来解决这个问题

我已经快速添加了一些小部件和一些事件,以便每个人都能注意到性能问题,如果注释行(在OnMotion方法的开头)被停用self.update()。我已经玩了代码,没有得到任何错误。希望这能解决你的问题

import tkinter as tk

class FloatingWindow(tk.Tk):
    def __init__(self):
        super().__init__()
        self.overrideredirect(True)
        self.geometry("800x400+300+100")
        self.minsize(200, 200)
        self.config(bg="green")
        self.grid_columnconfigure(0, weight=3)
        self.grid_rowconfigure(1, weight=3)

        self.menu()
        self.textbox()        

        self.grip_se = tk.Label(self,bg='blue')
        self.grip_se.place(relx=1.0, rely=1.0, anchor="se")
        self.grip_se.bind("<B1-Motion>",lambda e, mode='se':self.OnMotion(e,mode))

        self.grip_e = tk.Label(self,bg='green')
        self.grip_e.place(relx=1.0, rely=0.5, anchor="e")
        self.grip_e.bind("<B1-Motion>",lambda e, mode='e':self.OnMotion(e,mode))
        
        self.grip_ne = tk.Label(self,bg='blue')
        self.grip_ne.place(relx=1.0, rely=0, anchor="ne")
        self.grip_ne.bind("<B1-Motion>",lambda e, mode='ne':self.OnMotion(e,mode))

        self.grip_n = tk.Label(self,bg='green')
        self.grip_n.place(relx=0.5, rely=0, anchor="n")
        self.grip_n.bind("<B1-Motion>",lambda e, mode='n':self.OnMotion(e,mode))

        self.grip_nw = tk.Label(self,bg='blue')
        self.grip_nw.place(relx=0, rely=0, anchor="nw")
        self.grip_nw.bind("<B1-Motion>",lambda e, mode='nw':self.OnMotion(e,mode))

        self.grip_w = tk.Label(self,bg='green')
        self.grip_w.place(relx=0, rely=0.5, anchor="w")
        self.grip_w.bind("<B1-Motion>",lambda e, mode='w':self.OnMotion(e,mode))

        self.grip_sw = tk.Label(self,bg='blue')
        self.grip_sw.place(relx=0, rely=1, anchor="sw")
        self.grip_sw.bind("<B1-Motion>",lambda e, mode='sw':self.OnMotion(e,mode))

        self.grip_s = tk.Label(self,bg='green')
        self.grip_s.place(relx=0.5, rely=1, anchor="s")
        self.grip_s.bind("<B1-Motion>",lambda e, mode='s':self.OnMotion(e,mode))

    def menu(self):
        self.frame = tk.Frame(self, height=25, bg='black')
        self.frame.grid(row=0, column=0, sticky="new")
        color = ['#FEF3B3','#FFF9DC', "#341C09"]

        for i in range(3):
            self.button = tk.Button(self.frame, text="Can you see", font=('calibri',12), bg=color[i-1], fg="red", relief="flat", bd=0)
            self.button.pack(side="left", fill="both", padx=3)
            self.lbl_space  = tk.Label(self.frame ,text="",bd=0,bg="black")
            self.lbl_space.pack(side="left", padx=5)

            self.button = tk.Button(self.frame, text="Can you see", font=('calibri',12), bg=color[i-1], fg="red", relief="flat", bd=0)
            self.button.pack(side="right", fill="both", padx=3)

            
    def textbox(self):
        self.frame2 = tk.Frame(self, bg='white')
        self.frame2.grid(row=1, column=0, sticky="wens")
        self.text_editor = tk.Text(self.frame2, wrap='word', font='calibri 12',undo = True, relief=tk.FLAT,bg="white")
        self.yscrollbar = tk.Scrollbar(self.frame2, command=self.text_editor.yview)
        self.yscrollbar.grid(row=0, column=1, sticky="ns")#ns

        self.text_editor.config(yscrollcommand=self.yscrollbar.set)
        self.text_editor.grid(row=0, column=0, sticky="wens", padx=3)

        self.frame2.grid_columnconfigure(0, weight=3)
        self.frame2.grid_rowconfigure(0, weight=3)
        self.text_editor.insert("1.0", 'Bed sincerity yet therefore forfeited his certainty neglected questions. Pursuit chamber as elderly amongst on. Distant however warrant farther to of. My justice wishing prudent waiting in be. Comparison age not pianoforte increasing delightful now. Insipidity sufficient dispatched any reasonably led ask. Announcing if attachment resolution sentiments admiration me on diminution. ')

        # insert a widget inside the text box
        options = ["choice 1","choice 2"]
        clicked = tk.StringVar()
        clicked.set(options[0])
        self.drop = tk.OptionMenu(self.text_editor, clicked, *options)
        self.text_editor.window_create("1.0", window=self.drop)
        self.drop.config(bg="#474747", relief='flat', font=('calibri',11, 'bold'))

    def OnMotion(self, event, mode):
        self.update() # <==== if you deactivate this line you can see the performance issues
        
        abs_x = self.winfo_pointerx() - self.winfo_rootx()
        abs_y = self.winfo_pointery() - self.winfo_rooty()
        width = self.winfo_width()
        height= self.winfo_height()
        x = self.winfo_rootx()
        y = self.winfo_rooty()
        
        if mode == 'se' and abs_x >0 and abs_y >0:
                self.geometry("%sx%s" % (abs_x,abs_y)
                              )
                
        if mode == 'e':
            self.geometry("%sx%s" % (abs_x,height)
                          )
        if mode == 'ne' and abs_x >0:
                y = y+abs_y
                height = height-abs_y
                if height >0:
                    self.geometry("%dx%d+%d+%d" % (abs_x,height,
                                                   x,y))
        if mode == 'n':
            height=height-abs_y
            y = y+abs_y
            if height >0 and width >0:
                self.geometry("%dx%d+%d+%d" % (width,height,
                                               x,y))
            
        if mode == 'nw':
            width = width-abs_x
            height=height-abs_y
            x = x+abs_x
            y = y+abs_y
            if height >0 and width >0:
                self.geometry("%dx%d+%d+%d" % (width,height,
                                               x,y))
        if mode == 'w':
            width = width-abs_x
            x = x+abs_x
            if height >0 and width >0:
                self.geometry("%dx%d+%d+%d" % (width,height,
                                               x,y))
        if mode == 'sw':
            width = width-abs_x
            height=height-(height-abs_y)
            x = x+abs_x
            if height >0 and width >0:
                self.geometry("%dx%d+%d+%d" % (width,height,
                                               x,y))
        if mode == 's':
            height=height-(height-abs_y)
            if height >0 and width >0:
                self.geometry("%dx%d+%d+%d" % (width,height,
                                               x,y))
            


app=FloatingWindow()
app.mainloop()

相关问题 更多 >