Шаг 71.
Библиотека Tkinter. Компоненты и вспомогательные классы. Нестилизуемые компоненты. Компонент Canvas: построение графиков функций

    На этом шаге мы рассмотрим пример построения графиков.

    Рассмотрим пример построения графиков функций с использованием виджета Canvas.

    Создадим окно заданного размера и установим на нем виджет Notebook. Он представляет собой набор окон, которые имеют закладки. Щелчок мыши по одной из закладок открывает соответствующее окно. Для работы с виджетом Notebook следует импортировать модуль tkinter.ttk.

    На закладках виджета Notebook разместим холсты Canvas. На первом холсте нарисуем график функции y=sin(x). На втором - график функции y=sin(x)/x . На третьем - график функции y= x*exp(-x2). Вид трех закладок показан на рисунке 1.


Рис.1. Результат работы приложения

    Ниже приведен код примера и даны пояснения.

from tkinter import *
from tkinter.ttk import *
import math

def makecanvas(txt, bgclr):
    # добавление панелиNotebook с холстом
    cnvs=Canvas(nb, background=bgclr)
    nb.add(cnvs, text=txt, padding=3)
    return cnvs

# =====================================================
# функция построения на объекте холста canvas графика непрерывной
# функции fun. График строится на отрезке [a, b],
# kx,ky - масштабные множители по осям
# положение начала координат (0, 0) в точке холста (xo, yo)
# аргумент exclude - список X координат исключаемых точек
def drawFunc(canvas, fun, a, b, kx, ky, exclude=None):
    points = []
    num = 500    # количество точек
    for n in range(num):
        x = a + (b - a) / num * n
        if exclude != None:
            if x in exclude: continue
        y = fun(x)
        # положительное направление оси Y вверх
        pp = (xo + kx * x, yo - ky * y)
        points.append(pp) # список пар (xi,yi) точек кривой
    canvas.create_line(points, fill="blue", smooth=0, width=3)  # график
    xAxe = [(xo + a * kx, yo),(xo + b * kx, yo)]
    canvas.create_line(xAxe, fill="black", width=2) # ось X
    my = max([abs(e[1] - yo) for e in points])# максимальная амплитуда
    yAxe = [(xo, yo - my * 1.05), (xo, yo + my * 1.05)]
    canvas.create_line(yAxe, fill="black", width=2)# ось Y
    maxy = min([e[1] - yo for e in points])
    gorMark = [(xo - 5,yo + maxy), (xo + 5, yo + maxy)]
    canvas.create_line(gorMark, fill="black", width=1)# засечка на оси Y
    # текстовая отметка на оси Y
    canvas.create_text(xo + 28, yo + maxy, text="{0:.3f}".format(-maxy / ky))

def g(x):
    return math.sin(x) / x
def f(x):
    return x * math.exp(-x ** 2)

root = Tk()
root.title('Графики функций')
nb = Notebook(width=480, height=360)
nb.pack(expand=1, fill='both')
# создание трех холстов на закладках виджета Notebook
cnvs1 = makecanvas('  sin(x) ', '#f7ffff')
cnvs2 = makecanvas(' sin(x)/x ' , '#fff7ff')
cnvs3 = makecanvas(' x*exp(-x**2)', '#fffff7')
# ==============================================
# график функции sin(x)
xo, yo = 20, 180 # экранное положение начала координат
drawFunc(cnvs1, math.sin, 0, 12, 35, 150)
# график функции sin(x)/x
# исключить из рассмотрения точку x=0
xo, yo = 240, 180 # экранное положение начала координат
drawFunc(cnvs2, g, -20, 20, 11, 150, [0])
# график функции x*exp(-x**2)
xo, yo = 240, 180 # экранное положение начала координат
drawFunc(cnvs3, f, -3, 3, 80, 350)
root.mainloop()
Архив с файлом можно взять здесь.

    Прокомментируем приведенный пример.

def makecanvas(txt, bgclr):
    # добавление панелиNotebook с холстом
    cnvs=Canvas(nb, background=bgclr)
    nb.add(cnvs, text=txt, padding=3)
    return cnvs
.   .   .   .
# создание трех холстов на закладках виджета Notebook
cnvs1 = makecanvas('  sin(x) ', '#f7ffff')
cnvs2 = makecanvas(' sin(x)/x ' , '#fff7ff')
cnvs3 = makecanvas(' x*exp(-x**2)', '#fffff7')

    Обычно каждая панель Notebook состоит из контейнерного элемента, содержащего другие виджеты. В нашем примере таким контейнером является холст. Добавление новой панели с холстом выполняется методом

  Notebook.add(canvas[, <Заголовок>, <Опции панели>])    . 
В примере мы используем опцию padding, которая добавляет в панели пустое пространство вокруг холста. У нас метод Notebook.add() используется в функции makecanvas(), каждый вызов которой создает новую панель с холстом и возвращает объект холста.

    Для управления панелями элемента Notebook имеется множество свойств и методов. В частности, к панели, открытой в данный момент, можно обратиться с помощью инструкции Notebook.selected().

    Основной код построения графиков собран в функции drawFunc().

# =====================================================
# функция построения на объекте холста canvas графика непрерывной
# функции fun. График строится на отрезке [a, b],
# kx,ky - масштабные множители по осям
# положение начала координат (0, 0) в точке холста (xo, yo)
# аргумент exclude - список X координат исключаемых точек
def drawFunc(canvas, fun, a, b, kx, ky, exclude=None):
    points = []
    num = 500    # количество точек
    for n in range(num):
        x = a + (b - a) / num * n
        if exclude != None:
            if x in exclude: continue
        y = fun(x)
        # положительное направление оси Y вверх
        pp = (xo + kx * x, yo - ky * y)
        points.append(pp) # список пар (xi,yi) точек кривой
    canvas.create_line(points, fill="blue", smooth=0, width=3)  # график
    xAxe = [(xo + a * kx, yo),(xo + b * kx, yo)]
    canvas.create_line(xAxe, fill="black", width=2) # ось X
    my = max([abs(e[1] - yo) for e in points])# максимальная амплитуда
    yAxe = [(xo, yo - my * 1.05), (xo, yo + my * 1.05)]
    canvas.create_line(yAxe, fill="black", width=2)# ось Y
    maxy = min([e[1] - yo for e in points])
    gorMark = [(xo - 5,yo + maxy), (xo + 5, yo + maxy)]
    canvas.create_line(gorMark, fill="black", width=1)# засечка на оси Y
    # текстовая отметка на оси Y
    canvas.create_text(xo + 28, yo + maxy, text="{0:.3f}".format(-maxy / ky))

    Завершает программу код, в котором функция drawFunc() вызывается три раза. Каждый раз функции передается идентификатор холста соответствующей панели и имя функции, график которой будет строиться. Перед вызовом задается точка холста (xo, yo), в которой будет располагаться начало координат нового графика.

.   .   .   .   .
def g(x):
    return math.sin(x) / x
def f(x):
    return x * math.exp(-x ** 2)
.   .   .   .   .
# ==============================================
# график функции sin(x)
xo, yo = 20, 180 # экранное положение начала координат
drawFunc(cnvs1, math.sin, 0, 12, 35, 150)
# график функции sin(x)/x
# исключить из рассмотрения точку x=0
xo, yo = 240, 180 # экранное положение начала координат
drawFunc(cnvs2, g, -20, 20, 11, 150, [0])
# график функции x*exp(-x**2)
xo, yo = 240, 180 # экранное положение начала координат
drawFunc(cnvs3, f, -3, 3, 80, 350)

    На следующем шаге мы рассмотрим использование matplotlib в окнах tkinter.




Предыдущий шаг Содержание Следующий шаг