как открыть рамку, которая строит график, один раз нажав на кнопку в строке меню в tkinter

#python #matplotlib #tkinter #canvas

Вопрос:

Я попытался построить график, как только нажму «домой» в строке меню и отобразю его в правой части строки меню в новом кадре, но в том же корне. рамка отображается, но график не отображается. вот мой код:

 from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.figure import Figure
import pandas as pd
from tkinter import *
from PIL import Image, ImageTk
import matplotlib.pyplot as plt
import matplotlib
matplotlib.use('TkAgg')

root = Tk()
width = root.winfo_screenwidth()
height = root.winfo_screenheight()
# setting tkinter window size
root.geometry("%dx%d" % (width, height))

min_w = 50  # Minimum width of the frame
max_w = 200  # Maximum width of the frame
cur_width = min_w  # Increasing width of the frame
expanded = False  # Check if it is completely exanded


def Graph():
    df = pd.read_csv('nbrePieces.csv', encoding='Utf-8')
    # display x: session of the employ, y: number of "OK" pieces producted
    x = df['SESSION']
    y = df['OK']

    fig = Figure(figsize=(12, 10))
    ax = fig.add_subplot(111)

    ax.bar(x, y, color='g')
    ax.set_xlabel('SESSION')
    ax.set_ylabel('DATA')

    ax.legend()
    ax.grid()

    canvas = FigureCanvasTkAgg(fig, master=frameG)

    canvas.get_tk_widget().grid(rows=0, column=0)
    canvas.draw()


def expand():
    global cur_width, expanded
    cur_width  = 10  # Increase the width by 10
    rep = root.after(5, expand)  # Repeat this func every 5 ms
    frame.config(width=cur_width)  # Change the width to new increase width
    if cur_width >= max_w:  # If width is greater than maximum width
        expanded = True  # Frame is expended
        root.after_cancel(rep)  # Stop repeating the func
        fill()


def fill():
    if expanded:  # If the frame is exanded
        # Show a text, and remove the image
        home_b.config(text='Home', image='', font=(0, 15))
        liste_b.config(text='liste employés', image='', font=(0, 15))
        ajout_b.config(text='ajouter employés', image='', font=(0, 15))
        settings_b.config(text='settings', image='', font=(0, 15))
    else:
        # Bring the image back
        home_b.config(image=home, font=(0, 15))
        liste_b.config(image=liste, font=(0, 15))
        ajout_b.config(image=ajouter, font=(0, 15))
        settings_b.config(image=settings, font=(0, 15))


 def contract():
    global cur_width, expanded
    cur_width -= 10  # Reduce the width by 10
    rep = root.after(5, contract)  # Call this func every 5 ms
    frame.config(width=cur_width)  # Change the width to new reduced width
    if cur_width <= min_w:  # If it is back to normal width
        expanded = False  # Frame is not expanded
        root.after_cancel(rep)  # Stop repeating the func
        fill()


# Define the icons to be shown and resize it
home = ImageTk.PhotoImage(Image.open(
    'home.png').resize((40, 40), Image.ANTIALIAS))
liste = ImageTk.PhotoImage(Image.open(
    'liste.png').resize((40, 40), Image.ANTIALIAS))
ajouter = ImageTk.PhotoImage(Image.open(
    'ajouter.png').resize((40, 40), Image.ANTIALIAS))
settings = ImageTk.PhotoImage(Image.open(
    'settings.png').resize((40, 40), Image.ANTIALIAS))

root.update()  # For the width to get updated
frame = Frame(root, bg='#C1FFC1', width=50, height=root.winfo_height())
frame.grid(row=0, column=0)
# create the frame where the graph will appear
frameG = Frame(root, bg='gray2', width=1000,
               height=root.winfo_height(), padx=3, pady=3)
frameG.grid(row=0, column=1, sticky="nsew")

# Make the buttons with the icons to be shown
home_b = Button(frame, image=home, bg='#C1FFC1',
                command=lambda: Graph, relief='flat')
liste_b = Button(frame, image=liste, bg='#C1FFC1', relief='flat')
ajout_b = Button(frame, image=ajouter, bg='#C1FFC1', relief='flat')
settings_b = Button(frame, image=settings, bg='#C1FFC1', relief='flat')

# Put them on the frame
home_b.grid(row=0, column=0, pady=10)
liste_b.grid(row=1, column=0, pady=10)
ajout_b.grid(row=2, column=0, pady=10)
settings_b.grid(row=3, column=0, pady=10)

# Bind to the frame, if entered or left
frame.bind('<Enter>', lambda e: expand())
frame.bind('<Leave>', lambda e: contract())


# So that it does not depend on the widgets inside the frame
frame.grid_propagate(False)


root.mainloop()
 

я хочу, чтобы, как только я нажму на кнопку «домой» в строке меню, в полной правой части строки меню появится график.
заранее спасибо

Комментарии:

1. мы не можем запускать код без изображений. Используйте кнопки с текстом вместо изображений, и тогда мы сможем запустить его.

2. у вас есть ошибка — она должна быть command=lambda: Graph() с () вами . Или command=Graph без lambda и без () . И это может быть всей вашей проблемой. У меня нет файла cvs для тестирования остальной части кода.

3. Появляются ли какие-либо сообщения об ошибках?

4. после использования собственных данных вместо файла я могу видеть график, если я удалю label() и если я использую pack() вместо grid() — но он показывает его в средней области (черный), а не в правой части (серый). Но, может быть, это только ошибка с цветами.

Ответ №1:

Я обнаружил две проблемы

  1. Это должно быть command=lambda:Graph() с () или command=Graph без () и без lambda
  2. опечатка в строке
      canvas.get_tk_widget().grid(row=0, column=0)
     

    это должно быть row вместо rows

После этого это работает.


Минимальный рабочий код.

Я использую пустые изображения Image.new() для отображения без файлов.

Я помещаю примеры данных непосредственно в код.

Таким образом, каждый может просто скопировать и запустить его.

 from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.figure import Figure
import pandas as pd
from tkinter import *
from PIL import Image, ImageTk
import matplotlib.pyplot as plt
import matplotlib
matplotlib.use('TkAgg')

root = Tk()
width = root.winfo_screenwidth()
height = root.winfo_screenheight()
# setting tkinter window size
root.geometry("%dx%d" % (width, height))

min_w = 50  # Minimum width of the frame
max_w = 200  # Maximum width of the frame
cur_width = min_w  # Increasing width of the frame
expanded = False  # Check if it is completely exanded


def Graph():
    #df = pd.read_csv('nbrePieces.csv', encoding='Utf-8')
    df = pd.DataFrame({'SESSION':[1,2,3], 'OK':[10,12,14]})
    
    # display x: session of the employ, y: number of "OK" pieces producted
    x = df['SESSION']
    y = df['OK']

    fig = Figure(figsize=(12, 10))
    ax = fig.add_subplot(111)

    ax.bar(x, y, color='g')
    ax.set_xlabel('SESSION')
    ax.set_ylabel('DATA')

    ax.legend()
    ax.grid()

    canvas = FigureCanvasTkAgg(fig, master=frameG)

    canvas.get_tk_widget().grid(row=0, column=0)  # typo: `row`
    canvas.draw()


def expand():
    global cur_width, expanded
    cur_width  = 10  # Increase the width by 10
    rep = root.after(5, expand)  # Repeat this func every 5 ms
    frame.config(width=cur_width)  # Change the width to new increase width
    if cur_width >= max_w:  # If width is greater than maximum width
        expanded = True  # Frame is expended
        root.after_cancel(rep)  # Stop repeating the func
        fill()


def fill():
    if expanded:  # If the frame is exanded
        # Show a text, and remove the image
        home_b.config(text='Home', image='', font=(0, 15))
        liste_b.config(text='liste employés', image='', font=(0, 15))
        ajout_b.config(text='ajouter employés', image='', font=(0, 15))
        settings_b.config(text='settings', image='', font=(0, 15))
    else:
        # Bring the image back
        home_b.config(image=home, font=(0, 15))
        liste_b.config(image=liste, font=(0, 15))
        ajout_b.config(image=ajouter, font=(0, 15))
        settings_b.config(image=settings, font=(0, 15))


def contract():
    global cur_width, expanded
    cur_width -= 10  # Reduce the width by 10
    rep = root.after(5, contract)  # Call this func every 5 ms
    frame.config(width=cur_width)  # Change the width to new reduced width
    if cur_width <= min_w:  # If it is back to normal width
        expanded = False  # Frame is not expanded
        root.after_cancel(rep)  # Stop repeating the func
        fill()


# Define the icons to be shown and resize it
#home = ImageTk.PhotoImage(Image.open('home.png').resize((40, 40), Image.ANTIALIAS))
#liste = ImageTk.PhotoImage(Image.open('liste.png').resize((40, 40), Image.ANTIALIAS))
#ajouter = ImageTk.PhotoImage(Image.open('ajouter.png').resize((40, 40), Image.ANTIALIAS))
#settings = ImageTk.PhotoImage(Image.open('settings.png').resize((40, 40), Image.ANTIALIAS))

home = ImageTk.PhotoImage(Image.new('RGB', (40,40), 'red'))
liste = ImageTk.PhotoImage(Image.new('RGB', (40,40), 'green'))
ajouter = ImageTk.PhotoImage(Image.new('RGB', (40,40), 'blue'))
settings = ImageTk.PhotoImage(Image.new('RGB', (40,40), 'yellow'))

root.update()  # For the width to get updated
frame = Frame(root, bg='#C1FFC1', width=50, height=root.winfo_height())
frame.grid(row=0, column=0)

# create the frame where the graph will appear
frameG = Frame(root, bg='gray2', width=1000,
               height=root.winfo_height(), padx=3, pady=3)
frameG.grid(row=0, column=1, sticky="nsew")

# Make the buttons with the icons to be shown
home_b = Button(frame, image=home, bg='#C1FFC1',
                command=lambda: Graph(), relief='flat')
liste_b = Button(frame, image=liste, bg='#C1FFC1', relief='flat')
ajout_b = Button(frame, image=ajouter, bg='#C1FFC1', relief='flat')
settings_b = Button(frame, image=settings, bg='#C1FFC1', relief='flat')

# Put them on the frame
home_b.grid(row=0, column=0, pady=10)
liste_b.grid(row=1, column=0, pady=10)
ajout_b.grid(row=2, column=0, pady=10)
settings_b.grid(row=3, column=0, pady=10)

# Bind to the frame, if entered or left
frame.bind('<Enter>', lambda e: expand())
frame.bind('<Leave>', lambda e: contract())


# So that it does not depend on the widgets inside the frame
frame.grid_propagate(False)


root.mainloop()
 

введите описание изображения здесь

Комментарии:

1. большое вам спасибо за эту помощь, у меня осталась только одна проблема, если у вас есть какие-либо идеи : когда я нажимаю на кнопку и на графике отображается строка меню, она немного опускается, как показано на рисунке: drive.google.com/drive/folders/…

2. во-первых: было бы быстрее, если бы вы поместили изображение на imgur.com — мне не пришлось бы ждать принятия, чтобы увидеть изображение. Я думаю, что левая (зеленая) сторона может быть height ниже, plot и она центрирована grid — если вы используете grid(..., sticky="nsew") , то она будет использоваться полностью height . Я не могу воспроизвести эту проблему на своем компьютере.

3. так что я увижу высоты, большое вам спасибо за эту большую помощь., я ценю это.