2012-08-09 162 views
1

我想在Tk中創建一個具有自定義標題欄和框架的窗口。我在這個網站上看到了很多處理這個問題的問題,但我正在尋找的是使用畫布實際渲染框架,然後將內容添加到畫布。我不能用框架來做到這一點,因爲邊框是漸變的。Tkinter自定義窗口

根據這個網站:http://effbot.org/tkinterbook/canvas.htm#Tkinter.Canvas.create_window-method,我不能把上的小工具(使用create_window法)頂部的任何帆布項目,但我必須這樣做,因爲我的一些小部件的使用畫布渲染。

有關如何做到這一點的任何建議?我在這裏無能爲力。

編輯:Bryan Oakley證實用畫布渲染是不可能的。那麼是否可以有一個自定義邊框顏色的框架?如果是這樣,有人可以舉個簡單的例子嗎?我有點新的python。

+0

我不明白的問題,你的編輯使它更加明確。是的,可以使用畫布創建帶有自定義邊框的框架。這與在小部件頂部繪製畫布項無關 - 這是兩個不同的問題。 – 2012-08-10 01:53:38

+0

我以爲有bordercolor屬性......這不適用於頂級框架,對吧? – MiJyn 2012-08-10 02:06:44

+0

我沒有確認「用畫布渲染是不可能的」。我只是確認,您不能在畫布中嵌入的小部件頂部繪製畫布項目。當然,您可以使用畫布呈現邊框和自定義標題欄。 – 2012-08-10 02:12:01

回答

2

您可以使用畫布,就好像它是一個框架,以繪製您自己的窗口邊框。然而,就像你說的那樣,你不能在畫布中嵌入的小部件上畫畫布;小部件始終具有最高的堆疊順序。這是沒有辦法的,儘管目前還不清楚你是否真的需要這樣做。

下面是一個快速而髒的示例,展示如何使用自定義邊框的漸變創建窗口。爲了保持這個例子的簡短,我沒有添加任何代碼來允許你移動或調整窗口的大小。此外,它爲漸變使用固定的顏色。

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

感謝您的解釋!我已更新我的問題 – MiJyn 2012-08-10 00:52:48

+0

好的,謝謝,我現在看到了!還有一個關於這個的問題,我將如何用4個畫布(1xH或者Wx1)圍繞一個框架? – MiJyn 2012-08-12 17:09:37

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←

+0

謝謝!我想我必須找出一種方法在每一面上製作4幅畫布(以及中間的一幅畫框)。 – MiJyn 2012-08-10 16:16:00