На этом шаге мы рассмотрим пример одновременного использования векторной графики и графики matplotlib.
Холст, создаваемый конструктором FigureCanvasTkAgg(), можно использовать для рисования matplotlib графики и векторной графики одновременно. Однако нужно учитывать одну особенность, которая состоит в том, что векторную графику следует создавать в процедуре обработки сообщения <Configure>. Соответствующее событие происходит, когда изменяется размер, положение или внешний вид виджета. Например, оно происходит тогда, когда окно приложения открывается после удаления перекрывающего окна другого приложения. В результате, инструкция
canvas.bind('<Configure>', myredraw, '+')
Ниже приведен текст примера, где используются эти два вида графики.
from tkinter import * import numpy as np import matplotlib.pyplot as plt from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk def mydraw(event): # векторная графика canvas.create_line([[0, 0], [800, 800]], fill="blue", width=3) canvas.create_polygon([300, 20], [340, 150], [500, 200], fill="orange") canvas.create_rectangle(150, 250, 220, 320, fill="cyan") canvas.create_image(30, 100, image=img) # отображение картинки def myplotcode(): # графика x = np.linspace(0, 2 * np.pi) fig = plt.figure(facecolor='white') ax = fig.add_subplot(111) ax.plot(x, np.sin(x), '-rh', linewidth=3, markersize=12, markerfacecolor='b', label=r'$\ y=sin(x)$') ax.plot(x, -x * np.exp(-x ** 2 / 4), '-go', linewidth=3, markersize=12, markerfacecolor='y', label=r'$ y=-x*exp(-x^2)$') ax.grid(color='b', alpha=0.5, linestyle='dashed', linewidth=0.5) plt.legend(fontsize=12) plt.title('Functions graphs') plt.xlabel('X-ось абсцисс', {'fontname': 'Times New Roman'}) plt.ylabel('Ордината', {'fontname': 'Times New Roman'}) return fig root = Tk() root.title('Графики функций') frm = Frame(root) fgr = myplotcode() canvasAgg = FigureCanvasTkAgg(fgr, master=frm) # составной холст canvasAgg.draw() canvas = canvasAgg.get_tk_widget() # объект стандартного холста canvas.pack(fill=BOTH, expand=1) frm.pack(fill=BOTH, expand=1) # создание объекта img для отображение картинки images = "van.gif" img = PhotoImage(file=images) canvas.bind('<Configure>', mydraw, '+') toolbar = NavigationToolbar2Tk(canvasAgg, root) toolbar.update() root.mainloop()
Программа начинается с импортирования необходимых модулей и функций. Далее мы создаем две функции. В первой из них (mydraw) вызываются графические функции стандартного холста canvas. Вторая (myplotcode) - демонстрирует использование различных двумерных графических функций модуля matplotlib.pyplot:
def mydraw(event): # векторная графика canvas.create_line([[0, 0], [800, 800]], fill="blue", width=3) canvas.create_polygon([300, 20], [340, 150], [500, 200], fill="orange") canvas.create_rectangle(150, 250, 220, 320, fill="cyan") canvas.create_image(30, 100, image=img) # отображение картинки def myplotcode(): # графика x = np.linspace(0, 2 * np.pi) fig = plt.figure(facecolor='white') ax = fig.add_subplot(111) ax.plot(x, np.sin(x), '-rh', linewidth=3, markersize=12, markerfacecolor='b', label=r'$\ y=sin(x)$') ax.plot(x, -x * np.exp(-x ** 2 / 4), '-go', linewidth=3, markersize=12, markerfacecolor='y', label=r'$ y=-x*exp(-x^2)$') ax.grid(color='b', alpha=0.5, linestyle='dashed', linewidth=0.5) plt.legend(fontsize=12) plt.title('Functions graphs') plt.xlabel('X-ось абсцисс', {'fontname': 'Times New Roman'}) plt.ylabel('Ордината', {'fontname': 'Times New Roman'}) return fig
Затем мы создаем объект окна root и контейнерный элемент Frame. Вызов функции myplotcode() создает matplotlib-графику и возвращает объект графического окна fgr:
root = Tk()
root.title('Графики функций')
frm = Frame(root)
fgr = myplotcode()
Потом fgr передается первым аргументом конструктору FigureCanvasTkAgg(). Он создает объект составного холста на родительском виджете frm. Инструкция canvasAgg.draw() отображаеет matplotlib-графику:
canvasAgg = FigureCanvasTkAgg(fgr, master=frm) # составной холст
canvasAgg.draw()
Используя метод canvasAgg.get_tk_widget(), мы получаем ссылку canvas на объект "стандартного" холста Canvas. Она используется при его размещении упаковщиком pack(). Следом размещаем виджет-рамку и создаем объекта img, который используется в функции mydraw() при отображении изображения.
canvas = canvasAgg.get_tk_widget() # объект стандартного холста canvas.pack(fill=BOTH, expand=1) frm.pack(fill=BOTH, expand=1) # создание объекта img для отображение картинки images = "van.gif" img = PhotoImage(file=images)
Инструкция
canvas.bind('<Configure>', mydraw, '+')
В завершении мы добавляем стандартную панель с кнопками управления matplotlib-графикой.
toolbar = NavigationToolbar2Tk(canvasAgg, root) toolbar.update() root.mainloop()
Окно программы показано на рисунке 1.
Рис.1. Результат работы приложения
Попробуйте менять его размер, а также протестируйте работу кнопок панели NavigationToolbar2Tk. Они управляют только matplotlib-графикой.
На следующем шаге мы закончим изучение этого вопроса.