2012-03-06 61 views
2

有沒有一種方法來保持從Tkinter內部的窗口小部件(特別是圖像)的堆疊順序一致?例如,我可能在畫布的同一位置有兩個矩形,兩個三角形和一個圓。圓圈移動到鼠標最後一次點擊的位置,但我總是希望它在矩形頂部和三角形後面繪製。默認行爲當然是將最後繪製的對象放在頂部的給定位置。在Tkinter堆疊訂單維護

我只找到lift()和lower()方法來解決Tkinter到目前爲止的堆棧問題。理論上我可以在每次重繪時進行一些凌亂的檢查,看看目標是否存在三角形,併爲每個形狀做一些lift()/ lower(),直到事情按照我想要的方式進行,但這似乎是一個荒謬的解決方案。我期望在畫布對象上存在一種「圖層」變量,所以它會被動地記住層3的項目應該始終落後於層1的項目。

如果有一種簡單的方法來解決我的問題,我表示歉意,但至今我所有的搜索都無濟於事。我會感謝任何輸入!

回答

4

用「三角形」標記所有三角形,用「矩形」表示所有矩形,用「圓」表示所有圓形。然後,您可以使用liftlower方法同時升高或降低所有三角形,圓形或矩形。這隻需要幾個表述,即使你有成千上萬的項目,也只會在眨眼之間發生。

由於您詢問了內置圖層機制:tk沒有這種東西,但它很容易添加,所有的工具都在那裏。因此,不要在任何地方噴灑liftlower命令,讓所有繪圖都通過專門的命令來處理分層。

例如,這裏是一個接受層編號,並使其平確保一切是層上的命令的例子:

def add_to_layer(self, layer, command, coords, **kwargs): 
    layer_tag = "layer %s" % layer 
    if layer_tag not in self._layers: self._layers.append(layer_tag) 
    tags = kwargs.setdefault("tags", []) 
    tags.append(layer_tag) 
    item_id = command(coords, **kwargs) 
    self._adjust_layers() 
    return item_id 

def _adjust_layers(self): 
    for layer in sorted(self._layers): 
     self.canvas.lift(layer) 

你可以這樣稱呼它:

# draw a circle on layer 1: 
self.add_to_layer(1, self.canvas.create_oval, (x0,y0,x1,y1), outline="red") 
# draw a square on layer 2: 
self.add_to_layer(2, self.canvas.create_rectangle, (x0,y0,x1,y1), fill="blue") 

還有很多其他的方法可以完成同樣的事情,上面只是一個快速和骯髒的例子,我的頭頂(並不保證100%正確,但我認爲這說明了這一點)。

基本思想是所有的對象創建都要經過一個單一的函數,每次創建項目時都可以調整堆疊順序。這樣你只需要在一個地方添加這些提升/降低命令。

+0

謝謝布萊恩。我希望我不必在整個代碼中分散這些聲明,但看起來好像沒有更簡單的方法。我感謝幫助! – Taugosz 2012-03-06 18:35:01

+0

@Taugosz:我已經更新了我的答案,以展示如何擁有實現分層系統所需的一切。沒有任何內置的東西,但它只需要一點點的想象力來實現自己的分層。 – 2012-03-06 20:38:39

+0

我很尷尬我以前沒有提出這樣的解決方案;我當然有我需要的工具。非常感謝您花時間整理完整的代碼來說明您的觀點。 – Taugosz 2012-03-19 01:43:12