Skip to content Skip to sidebar Skip to footer

Tkinter: Windows Without Title Bar But Resizable

What I know is if I want to create a window without title bar, I can write root = Tk() ........ root.overrideredirect(1) But I would also like the window to be resizab

Solution 1:

The problem is, the window is resizable, but when you turn on overrideredirect you lose any sort of header or edge that you can grab in order to resize the window. The only solution is to implement resizing yourself. You can add your own borders, or add mouse bindings that work when the mouse is near an edge.

This answer shows how to move such a window: Python/Tkinter: Mouse drag a window without borders, eg. overridedirect(1)

Here's a short example that illustrates resizing. It has only barely been tested on OSX but should work on any platform. It uses python2, though it should work with python3 just by changing the import statements.

import Tkinter as tk
import ttk

classExample(tk.Tk):
    def__init__(self):
        tk.Tk.__init__(self)
        self.floater = FloatingWindow(self)

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


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

Solution 2:

An extended working example of @Bryan's solution can be found here:

import tkinter as tk


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

    defOnMotion(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 >0and abs_y >0:
                self.geometry("%sx%s" % (abs_x,abs_y)
                              )
                
        if mode == 'e':
            if height >0and 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 >0and 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 >0and 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 >0and 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 >0and width >0:
                self.geometry("%dx%d+%d+%d" % (width,height,
                                               x,y))
        if mode == 's':
            height=height-(height-abs_y)
            if height >0and width >0:
                self.geometry("%dx%d+%d+%d" % (width,height,
                                               x,y))
            
        
    defcenter(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()

Output:

enter image description here

If someone know how to get rid of the performance issues, please answer this question.

Post a Comment for "Tkinter: Windows Without Title Bar But Resizable"