2012-03-06 62 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