我想在Tk中创建一个具有自定义标题栏和框架的窗口。我在这个网站上看到很多关于此问题的问题,但我正在寻找的是使用画布实际渲染帧,然后将内容添加到画布。我不能用框架来做这个,因为边框是渐变的。
根据这个网站:http://effbot.org/tkinterbook/canvas.htm#Tkinter.Canvas.create_window-method,我不能在窗口小部件上放置任何其他画布项(使用create_window
方法),但我需要这样做,因为我的一些小部件是使用画布渲染。
有关如何执行此操作的任何建议?我在这里很傻。
编辑:布莱恩奥克利证实用帆布渲染是不可能的。那么是否可以使用具有自定义边框颜色的框架?如果是这样,有人会举一个简单的例子吗?我是python的新手。答案 0 :(得分:3)
您可以像使用画布一样使用画布来绘制自己的窗口边框。但是,就像你说的那样,你不能在画布中嵌入的小部件上绘制画布项;窗口小部件始终具有最高的堆叠顺序。没有办法解决这个问题,但目前尚不清楚你是否确实需要这样做。
这是一个快速而肮脏的示例,展示如何使用自定义边框的渐变创建窗口。为了保持示例简短,我没有添加任何代码来允许您移动窗口或调整窗口大小。此外,它使用固定颜色作为渐变。
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()
答案 1 :(得分:1)
这是一个粗略的例子,其中框架,标题栏和关闭按钮是用画布矩形制作的:
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()
如果我要制作一个自定义GUI框架,我会考虑用图像创建它,
使用像Photoshop这样的程序,而不是渲染画布对象
图像可以放在这样的画布上:
self.ti = tk.PhotoImage(file='test.gif')
self.aImage = mCanvas.create_image(0,0, image=self.ti,anchor='nw')
更多信息→here←