#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:
Я обнаружил две проблемы
- Это должно быть
command=lambda:Graph()
с()
илиcommand=Graph
без()
и безlambda
- опечатка в строке
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. так что я увижу высоты, большое вам спасибо за эту большую помощь., я ценю это.