Matplotlib 不僅能繪製靜態圖表,透過事件處理機制還能實現互動式繪圖。本文示範如何利用 matplotlib.patches.Rectangle 搭配滑鼠事件(button_press_event、button_release_event),在座標系中以拖曳方式畫出矩形,並即時更新顯示。
Rectangle 物件並加入 Axes(ax.add_patch)。(x0, y0)。(x1, y1),計算寬高並更新 Rectangle 的幾何屬性。canvas.draw() 重繪畫布。import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
class RectangleDrawer:
"""互動式矩形繪製器"""
def __init__(self):
self.fig, self.ax = plt.subplots()
self.ax.set_title('拖曳滑鼠繪製矩形,關閉視窗結束')
self.ax.set_xlim(0, 10)
self.ax.set_ylim(0, 10)
# 初始矩形(寬高為 0,不可見)
self.rect = Rectangle((0, 0), 0, 0,
edgecolor='red', facecolor='none', linewidth=2)
self.ax.add_patch(self.rect)
self.x0 = self.y0 = None
self.cid_press = self.fig.canvas.mpl_connect('button_press_event', self.on_press)
self.cid_release = self.fig.canvas.mpl_connect('button_release_event', self.on_release)
def on_press(self, event):
if event.inaxes != self.ax:
return
self.x0, self.y0 = event.xdata, event.ydata
# 重置矩形到起點,寬高歸零
self.rect.set_xy((self.x0, self.y0))
self.rect.set_width(0)
self.rect.set_height(0)
self.fig.canvas.draw()
def on_release(self, event):
if event.inaxes != self.ax or self.x0 is None:
return
x1, y1 = event.xdata, event.ydata
# 計算寬高(允許負值,自動修正)
w, h = x1 - self.x0, y1 - self.y0
self.rect.set_width(w)
self.rect.set_height(h)
self.fig.canvas.draw()
print(f"矩形座標:({self.x0:.2f}, {self.y0:.2f}) 寬高:({w:.2f}, {h:.2f})")
def show(self):
plt.show()
if __name__ == '__main__':
drawer = RectangleDrawer()
drawer.show()
若希望在拖曳過程中即時看到矩形變化,可改綁定 motion_notify_event:
self.cid_motion = self.fig.canvas.mpl_connect('motion_notify_event', self.on_motion)
def on_motion(self, event):
if event.inaxes != self.ax or self.x0 is None:
return
w, h = event.xdata - self.x0, event.ydata - self.y0
self.rect.set_width(w)
self.rect.set_height(h)
self.fig.canvas.draw_idle() # 非阻塞重繪,效能更好
event.xdata/ydata),非像素座標;若需像素座標請用 event.x/y。%matplotlib widget 或 %matplotlib qt 後端,否則事件迴圈無法正常運作。透過不到 50 行代碼,即可擁有一個可互動的矩形繪製工具,作為更複雜標註系統的基礎模組非常合適。