Не отображается график matplotlib в окне tkinter

Рейтинг: 0Ответов: 2Опубликовано: 13.01.2023

Пустой экран при вводе данных в программу. Пока не добавил окно matplotlib в tkinter все работало. Может это из-за графика зависит. введите сюда описание изображения введите сюда описание изображения

import matplotlib.pyplot as plt
import matplotlib
import numpy as np
import tkinter as tk
from matplotlib.figure import Figure 
from matplotlib.colors import LinearSegmentedColormap
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)

win = tk.Tk()
win.geometry ('900x900+600+300')

def draw_graph():
    x, y, z, X, Y, mask = makeData()
    global canvas1
    if canvas1:
        canvas1.get_tk_widget().destroy()
    fig = Figure(figsize=(10, 6), dpi=100)
    canvas1 = FigureCanvasTkAgg(fig, master = win)
    canvas1.draw()
    axes = plt.axes(projection="3d")
    cmap = LinearSegmentedColormap.from_list('red_blue', ['b', 'g', 'y', 'r'], 256)
    axes.scatter(x, y, z *(1 + mask * 0.75), c=z *(1 + mask * 0.75), cmap=cmap)
    toolbar = NavigationToolbar2Tk(canvas1, win)
    toolbar.update()
    canvas1.get_tk_widget().pack(side=tk.TOP, fill=tk.NONE, expand=0)
    win.after(200, None)

def makeData():
    a=int(q.get()) #19
    b=float(w.get()) #20
    c=int(e.get()) #200
    x0=float(t.get()) #19.3
    y0=float(u.get()) #19.6
    r=float(i.get()) #.1
    x = np.linspace(a, b, c)  # создаем массив из 100 чисел float от 19 до 20 с равномернов шагом
    y = np.linspace(a, b, c)
    xgrid, ygrid = np.meshgrid(x, y)
    z = np.random.normal(xgrid, ygrid)
    r = .1  # радиус маски
    X, Y = np.meshgrid(x, y)
    mask = (X - x0) ** 2 + (Y - y0) ** 2 < r ** 2
    return xgrid, ygrid, z, X, Y, mask

canvas1 = None
tk.Label(win, text='Введите начало массива a = ').pack(padx = 5, pady = 5)
tk.Label(win, text='Введите конец массива b = ').pack(padx = 5, pady = 5)
tk.Label(win, text='Введите количество точек массива:  ').pack(padx = 5, pady = 5)
tk.Label(win, text='Центр маски по x от a = ').pack(padx = 5, pady = 5)
tk.Label(win, text='Центр маски по y до b = ').pack(padx = 5, pady = 5)
tk.Label(win, text='Радиус маски r = ').pack(padx = 5, pady = 5)

q = tk.Entry()
w = tk.Entry()
e = tk.Entry()
t = tk.Entry()
u = tk.Entry()
i = tk.Entry()

q.pack(padx = 5, pady = 5)
w.pack(padx = 5, pady = 5)
e.pack(padx = 5, pady = 5)
t.pack(padx = 5, pady = 5)
u.pack(padx = 5, pady = 5)
i.pack(padx = 5, pady = 5)

tk.Button(win, text='Ввести точки', command=draw_graph).pack(padx = 5, pady = 5)
win.mainloop()

Ответы

▲ 0Принят

Почитал по поводу создания различных графиков в Matplotlib тут: https://devpractice.ru/matplotlib-lesson-5-1-mplot3d-toolkit/#p4

В соответствие с информацией о построение графиков "Поверхность" изменил отрисовку осей:

    ax = fig.add_subplot(111, projection='3d')
    cmap = LinearSegmentedColormap.from_list('red_blue', ['b', 'g', 'y', 'r'], 256)
    ax.plot_surface(x, y, z *(1 + mask * 0.75), cmap=cmap)

В общем виде код выглядит так:

import numpy as np
import tkinter as tk
from matplotlib.figure import Figure
from matplotlib.colors import LinearSegmentedColormap
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)

win = tk.Tk()
win.geometry ('900x900+600+300')

def draw_graph():
    x, y, z, X, Y, mask = makeData()
    global canvas1
    if canvas1:
        canvas1.get_tk_widget().destroy()
    fig = Figure(figsize=(10, 6), dpi=100)
    canvas1 = FigureCanvasTkAgg(fig, master = win)
    canvas1.draw()
    ax = fig.add_subplot(111, projection='3d')
    cmap = LinearSegmentedColormap.from_list('red_blue', ['b', 'g', 'y', 'r'], 256)
    ax.plot_surface(x, y, z *(1 + mask * 0.75), cmap=cmap)
    toolbar = NavigationToolbar2Tk(canvas1, win)
    toolbar.update()
    canvas1.get_tk_widget().pack(side=tk.TOP, fill=tk.NONE, expand=0)
    win.after(200, None)


def makeData():
    a=int(q.get()) #19
    b=float(w.get()) #20
    c=int(e.get()) #200
    x0=float(t.get()) #19.3
    y0=float(u.get()) #19.6
    r=float(i.get()) #.1
    x = np.linspace(a, b, c)  # создаем массив из 100 чисел float от 19 до 20 с равномернов шагом
    y = np.linspace(a, b, c)
    xgrid, ygrid = np.meshgrid(x, y)
    z = np.random.normal(xgrid, ygrid)
    r = .1  # радиус маски
    X, Y = np.meshgrid(x, y)
    mask = (X - x0) ** 2 + (Y - y0) ** 2 < r ** 2
    return xgrid, ygrid, z, X, Y, mask

canvas1 = None
tk.Label(win, text='Введите начало массива a = ').pack(padx = 5, pady = 5)
tk.Label(win, text='Введите конец массива b = ').pack(padx = 5, pady = 5)
tk.Label(win, text='Введите количество точек массива:  ').pack(padx = 5, pady = 5)
tk.Label(win, text='Центр маски по x от a = ').pack(padx = 5, pady = 5)
tk.Label(win, text='Центр маски по y до b = ').pack(padx = 5, pady = 5)
tk.Label(win, text='Радиус маски r = ').pack(padx = 5, pady = 5)

q = tk.Entry()
w = tk.Entry()
e = tk.Entry()
t = tk.Entry()
u = tk.Entry()
i = tk.Entry()

q.pack(padx = 5, pady = 5)
w.pack(padx = 5, pady = 5)
e.pack(padx = 5, pady = 5)
t.pack(padx = 5, pady = 5)
u.pack(padx = 5, pady = 5)
i.pack(padx = 5, pady = 5)

tk.Button(win, text='Ввести точки', command=draw_graph).pack(padx = 5, pady = 5)
win.mainloop()

График выводит в таком виде

▲ 0

Для более удобного вида программы лучше применить позиционирование .grid(column,row)

tk.Label(win, text='Введите начало массива a = ').grid(column=1,row=1)
tk.Label(win, text='Введите конец массива b = ').grid(column=1,row=2)
tk.Label(win, text='Введите количество точек массива:  ').grid(column=1,row=3)
tk.Label(win, text='Центр маски по x от a = ').grid(column=1,row=4)
tk.Label(win, text='Центр маски по y до b = ').grid(column=1,row=5)
tk.Label(win, text='Радиус маски r = ').grid(column=1,row=6)

q.grid(column=2,row=1)
w.grid(column=2,row=2)
e.grid(column=2,row=3)
t.grid(column=2,row=4)
u.grid(column=2,row=5)
i.grid(column=2,row=6)

tk.Button(win, text='Ввести точки', command=draw_graph).grid(column=2,row=7)

Почитайте побольше о размещении виджетов в tkinter

А какой график при этих введенных данных должен получиться?