matplotlib 如何控制多边形的zorder

4ioopgfo  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(81)

我修改了Poly Editor(来自Matplotlib库),使其能够一次加载多个多边形。这工作正常,除了一点:我不知道如何控制多边形的zorder。
下面是我的代码(只有有趣的几行):

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import polygons # a list of matplotlib.patches.Polygon
import poly_editor

root = tk.Tk()

fig = Figure(figsize=(10, 8))
ax = fig.add_subplot(aspect='equal')

canvas = FigureCanvasTkAgg(fig, root)

poly_editors = []
for poly in polygons:
    ax.add_patch(poly)
    poly_editors.append(poly_editor.PolygonInteractor(ax, poly, canvas))

有了这段代码,第一个多边形在下面,最后一个在上面。

我试图在这个时候测试zorder的使用:

for i,poly in enumerate(polygons):
    poly.set_zorder(10 - i)
    ax.add_patch(poly)
    poly_editors.append(poly_editor.PolygonInteractor(ax, poly, canvas))

那么结果是一样的,zorder没有考虑在内。
我的目标是在多边形内部按下字母“t”时,将多边形置于所有其他多边形之上。我在poly_editor中编写了此代码,但显然无法工作。

def on_key_press(self, event):
    if event.key == 't':
        if self.poly.contains_point((event.x, event.y)):
            self.poly.set(zorder=10)
        else:
            self.poly.set(zorder=0)
        self.ax.draw_artist(self.poly)
        self.canvas.draw_idle()

我是matplotlib的新手,有人能帮助我了解zorder是如何工作的吗?我看到了许多与zorder相关的问题,但我找不到任何答案。

balp4ylt

balp4ylt1#

我终于解决了我的问题。由于zorder不能使用,唯一可用的方法是在ax.patches列表中播放,因为这个列表的最后一个多边形是所有其他多边形中的最后一个。
所以如果我把第一个多边形放在上面:

ax.patches.remove(polygons[0])
ax.add_patch(polygons[0])

这还不够,我还必须重新创建多边形交互器

instance:ax.patches.remove(polygons[0])
ax.add_patch(polygons[0])
p = poly_editor.PolygonInteractor(ax, poly, canvas)
canvas.draw_idle()

这个手工测试可以像预期的那样工作,但是我必须在PolygonInteractor示例内部进行。
下面是最终解决方案的有趣代码,它实现了我所要求的:

### main
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import polygons # a list of matplotlib.patches.Polygon
import poly_editor

root = tk.Tk()

fig = Figure(figsize=(10, 8))
ax = fig.add_subplot(aspect='equal')

canvas = FigureCanvasTkAgg(fig, root)
poly_editors = {}
for poly in polygons:
    ax.add_patch(poly)
    poly_editors[poly] = poly_editor.PolygonInteractor(ax, poly, poly_editors)

### PolygonInteractor.__init__
    def __init__(self, ax, poly, container):
        self.ax = ax
        self.poly = poly
        self.canvas = ax.figure.canvas
        self.container = container

### inside PolygonInteractor
    def on_key_press(self, event):
        if event.key == 't':
            if self.poly.contains_point((event.x, event.y)):
                self.ax.patches.remove(self.poly)
                self.ax.add_patch(self.poly)
                self = self.__class__(self.ax, self.poly, self.container)
                self.container[self.poly] = self

用一个新创建的示例替换当前示例非常简单。这似乎有点古怪和神奇... Python总是让我感到惊讶,尽管我有很长的经验!

相关问题