Tkinter custom window

前端 未结 2 604
醉梦人生
醉梦人生 2020-12-12 02:15

I want to make a window in Tk that has a custom titlebar and frame. I have seen many questions on this website dealing with this, but what I\'m looking for is to actually re

相关标签:
2条回答
  • 2020-12-12 02:38

    Here is a rough example where the frame, titlebar and close button are made with canvas rectangles:

    import Tkinter as tk
    
    class Application(tk.Tk):
    
        def __init__(self):
            tk.Tk.__init__(self)
            # Get rid of the os' titlebar and frame
            self.overrideredirect(True)
    
            self.mCan = tk.Canvas(self, height=768, width=768)
            self.mCan.pack()
    
            # Frame and close button
            self.lFrame = self.mCan.create_rectangle(0,0,9,769,
                                        outline='lightgrey', fill='lightgrey')
            self.rFrame = self.mCan.create_rectangle(760,0,769,769,
                                        outline='lightgrey', fill='lightgrey')
            self.bFrame = self.mCan.create_rectangle(0,760,769,769,
                                        outline='lightgrey', fill='lightgrey')
            self.titleBar = self.mCan.create_rectangle(0,0,769,20,
                                        outline='lightgrey', fill='lightgrey')
            self.closeButton = self.mCan.create_rectangle(750,4,760, 18,
                                                activefill='red', fill='darkgrey')
    
            # Binds
            self.bind('<1>', self.left_mouse)
            self.bind('<Escape>', self.close_win)
    
            # Center the window
            self.update_idletasks()
            xp = (self.winfo_screenwidth() / 2) - (self.winfo_width() / 2)
            yp = (self.winfo_screenheight() / 2) - (self.winfo_height() / 2)
            self.geometry('{0}x{1}+{2}+{3}'.format(self.winfo_width(),
                                                    self.winfo_height(),
                                                                xp, yp))
    
        def left_mouse(self, event=None):
            obj = self.mCan.find_closest(event.x,event.y)
            if obj[0] == self.closeButton:
                self.destroy()
    
        def close_win(self, event=None):
            self.destroy()
    
    app = Application()
    app.mainloop()
    

    If I were going to make a custom GUI frame I would consider creating it with images,
    made with a program like Photoshop, instead of rendering canvas objects.
    Images can be placed on a canvas like this:

    self.ti = tk.PhotoImage(file='test.gif')
    self.aImage = mCanvas.create_image(0,0, image=self.ti,anchor='nw')
    

    More info →here←

    0 讨论(0)
  • 2020-12-12 02:49

    You can use the canvas as if it were a frame in order to draw your own window borders. Like you said, however, you cannot draw canvas items on top of widgets embedded in a canvas; widgets always have the highest stacking order. There is no way around that, though it's not clear if you really need to do that or not.

    Here's a quick and dirty example to show how to create a window with a gradient for a custom border. To keep the example short I didn't add any code to allow you to move or resize the window. Also, it uses a fixed color for the gradient.

    import Tkinter as tk
    
    class GradientFrame(tk.Canvas):
        '''A gradient frame which uses a canvas to draw the background'''
        def __init__(self, parent, borderwidth=1, relief="sunken"):
            tk.Canvas.__init__(self, parent, borderwidth=borderwidth, relief=relief)
            self._color1 = "red"
            self._color2 = "black"
            self.bind("<Configure>", self._draw_gradient)
    
        def _draw_gradient(self, event=None):
            '''Draw the gradient'''
            self.delete("gradient")
            width = self.winfo_width()
            height = self.winfo_height()
            limit = width
            (r1,g1,b1) = self.winfo_rgb(self._color1)
            (r2,g2,b2) = self.winfo_rgb(self._color2)
            r_ratio = float(r2-r1) / limit
            g_ratio = float(g2-g1) / limit
            b_ratio = float(b2-b1) / limit
    
            for i in range(limit):
                nr = int(r1 + (r_ratio * i))
                ng = int(g1 + (g_ratio * i))
                nb = int(b1 + (b_ratio * i))
                color = "#%4.4x%4.4x%4.4x" % (nr,ng,nb)
                self.create_line(i,0,i,height, tags=("gradient",), fill=color)
            self.lower("gradient")
    
    class SampleApp(tk.Tk):
        def __init__(self):
            tk.Tk.__init__(self)
            self.wm_overrideredirect(True)
            gradient_frame = GradientFrame(self)
            gradient_frame.pack(side="top", fill="both", expand=True)
            inner_frame = tk.Frame(gradient_frame)
            inner_frame.pack(side="top", fill="both", expand=True, padx=8, pady=(16,8))
    
            b1 = tk.Button(inner_frame, text="Close",command=self.destroy)
            t1 = tk.Text(inner_frame, width=40, height=10)
            b1.pack(side="top")
            t1.pack(side="top", fill="both", expand=True)
    
    if __name__ == "__main__":
        app = SampleApp()
        app.mainloop()
    
    0 讨论(0)
提交回复
热议问题