受this问题的启发,我想为我的根窗口编写自己的调整大小函数。但我注意到我的代码存在一些性能问题。如果你快速调整大小,你会发现窗口不能像我希望的那样迅速找到它的高度,它会“卡顿”。(更像是摆动)
有人知道这是为什么吗?我最好的猜测是
我尝试在不同位置和多次使用
以下是示例代码:
tkinter
事件处理程序太慢了,或者我做的数学运算不是最快的方式。我尝试在不同位置和多次使用
update_idletasks()
。我尝试的另一种方法是使用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()
更新
看起来性能问题与微软有关,这是一个众所周知的问题,让大多数微软开发人员感到疯狂。
更新2
由于这个问题似乎与MS-Windows有关,我尝试找到一个MS特定的解决方案并进行了大量研究。我试图拦截消息,如wm_pain
,wm_nccalcsize
等等。在某个地方,我认为已经有一个大小框,因此利用它是有意义的。但是,这种解决方案还存在另一个问题。
顶部有一条细白线。我花了很长时间才找到答案,它只是sizebox本身。不幸的是,我还没有找到通过win32 api或Dwmapi来配置 sizebox的方法。
简而言之
这个问题的最好答案是带有蓝色和绿色标签的平滑调整大小事件。但如果您找到一种方法来消除细白线并仍然具有调整大小能力,(仅缩小窗口矩形到客户端矩形不起作用或您只有1像素可以调整大小)也是一种解决方案。
更新后的代码如下:
import tkinter as tk
import win32gui
import win32api
import win32con
class FloatingWindow(tk.Tk):
def __init__(self):
super().__init__()
#self.overrideredirect(True)
self.hWnd = int(self.wm_frame(), 16)
self.label = tk.Label(self, text="Grab one of the blue")
self.label.pack(side="top", fill="both", expand=True)
blues = {'se' : (1,1),'ne' : (1,0),'nw' : (0,0),'sw' : (0,1)}
grens = {'e' : (1,0.5), 'n' : (0.5,0), 'w' : (0,0.5), 's' : (0.5,1)}
for k,v in blues.items():
ref = tk.Label(self, bg='blue')
ref.place(relx=v[0],rely=v[1],anchor=k)
ref.bind("<B1-Motion>", lambda e, mode=k:self.OnMotion(e,mode))
for k,v in grens.items():
ref = tk.Label(self, bg='green')
ref.place(relx=v[0],rely=v[1],anchor=k)
ref.bind("<B1-Motion>", lambda e, mode=k:self.OnMotion(e,mode))
self.bind('<ButtonPress-1>', self.start_drag)
self.bind('<ButtonRelease-1>', self.stop_drag)
return
def stop_drag(self,event):
self.start_abs_x = None
self.start_abs_y = None
self.start_width = None
self.start_height= None
self.start_x = None
self.start_y = None
def start_drag(self,event):
self.update_idletasks()
self.start_abs_x = self.winfo_pointerx() - self.winfo_rootx()
self.start_abs_y = self.winfo_pointery() - self.winfo_rooty()
self.start_width = self.winfo_width()
self.start_height= self.winfo_height()
self.start_x = self.winfo_x()
self.start_y = self.winfo_y()
def OnMotion(self, event, mode):
self.update_idletasks()
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_x()
y = self.winfo_y()
x_motion = self.start_abs_x - abs_x
y_motion = self.start_abs_y - abs_y
self.calc_x = x;self.calc_y=y;self.calc_w=width;
self.calc_h=self.start_height
if 'e' in mode:
self.calc_w = self.start_width-x_motion
if 's' in mode:
self.calc_h -= y_motion
if 'n' in mode:
self.calc_y = y-y_motion
self.calc_h = height+y_motion
if 'w' in mode:
self.calc_w = width+x_motion
self.calc_x = x-x_motion
self.geometry("%dx%d+%d+%d" % (self.calc_w,self.calc_h,
self.calc_x,self.calc_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.update_idletasks()
hwnd = win32gui.GetParent(app.hWnd)
style= win32api.GetWindowLong(hwnd, win32con.GWL_STYLE)
style&= ~win32con.WS_CAPTION
#style&= ~win32con.WS_SIZEBOX
valid= win32api.SetWindowLong(hwnd, win32con.GWL_STYLE, style)
app.mainloop()
系统信息:
Windows 10 Home;x64-基础,Intel(R) Core(TM) i3-2120 @ 3.30GHz,3300 MHz,2个核心
使用:
Python 3.7.2 和 tkinter 8.6
osx10.12.5 MacBook Air 2核i5 2011年4GB RAM,2个浏览器,一个大型PDF,系统监视器,Textedit打开和两个屏幕
使用Jupyter笔记本
中的python 3.8
- 您的代码存在错误:在双监视器上,通过边界调整大小会使y
朝两个方向扩展。 - Reblochon Masque