Tkinter:无标题栏但可调整大小的窗口。

10

我知道如果我想创建一个没有标题栏的窗口,可以这样写:

    root = Tk()
    ........
    root.overrideredirect(1)

但我也希望窗口可以调整大小。有什么解决方案吗?

(FYI:我正在Windows电脑上工作,虽然我不确定这是否真的重要。如果有一个独立于操作系统的解决方案,那将是完美的,但如果至少有一个Windows的解决方案,我也很高兴。)

2个回答

14

问题是,窗口可以被调整大小,但当您打开overrideredirect时,您将失去任何可以用于调整窗口大小的标题栏或边缘。唯一的解决方法是自己实现调整大小。您可以添加自己的边框,或者添加当鼠标靠近边缘时起作用的鼠标绑定。

这个答案展示了如何移动这样的窗口:Python/Tkinter: Mouse drag a window without borders, eg. overridedirect(1)

这里有一个简短的例子,说明如何调整大小。它只在OSX上进行了基本测试,但应该适用于任何平台。它使用python2,但通过更改导入语句,应该可以与python3一起使用。

import Tkinter as tk
import ttk

class Example(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.floater = FloatingWindow(self)

class FloatingWindow(tk.Toplevel):
    def __init__(self, *args, **kwargs):
        tk.Toplevel.__init__(self, *args, **kwargs)
        self.overrideredirect(True)
        self.wm_geometry("400x400")

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

        self.grip = ttk.Sizegrip(self)
        self.grip.place(relx=1.0, rely=1.0, anchor="se")
        self.grip.lift(self.label)
        self.grip.bind("<B1-Motion>", self.OnMotion)


    def OnMotion(self, event):
        x1 = self.winfo_pointerx()
        y1 = self.winfo_pointery()
        x0 = self.winfo_rootx()
        y0 = self.winfo_rooty()
        self.geometry("%sx%s" % ((x1-x0),(y1-y0)))
        return

app=Example()
app.mainloop()

这正是我想要的。谢谢。 - Dick Wong
简单的修改可以让 Mac 上的窗口只能在一个方向上调整大小,由于某些 Tk 的 bug,win.resizable(False,True)win.resizable(True, False) 会创建可在两个方向上调整大小的窗口。 - saulspatz

1

这里可以找到@Bryan解决方案的扩展工作示例:

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 one of the blue")
        self.label.pack(side="top", fill="both", expand=True)

        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 OnMotion(self, event, mode):
        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':
            if height >0 and abs_x >0:
                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))
            
        
    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()

输出:

enter image description here

如果有人知道如何解决性能问题,请回答这个问题

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接