Невозможно показать более 4-5 гистограмм с помощью matplotlib

Я пытаюсь отобразить 4-5 гистограмму Matplotlib в окне Tkinter. Но почему-то в рамку помещаются только 3. Пожалуйста, найдите приведенный ниже код.

import tkinter as tk
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.figure import Figure
import matplotlib.
# --- main ---

x = [1, 2, 3, 4]
y = [1, 2, 3, 4]
AS = [10 / 2 ** 0]

# ---

root = tk.Tk()
root.geometry("1000x1000")
root.title("eggs")

# ---

frame_top = tk.Frame(root)
frame_top.pack(fill='both', expand=True)

fig = Figure(dpi=100)  # figsize=(10, 6),
fig.add_subplot(111).plot(x, y)
# fig.add_subplot(111).plot(AS)

canvas = FigureCanvasTkAgg(fig, master=frame_top)  # A tk.DrawingArea.
canvas.draw()
canvas.get_tk_widget().pack(side = "left",fill='both', expand=True)

fig1 = Figure(dpi=100)  # figsize=(10, 6),
fig1.add_subplot(111).plot(x, y)
# fig.add_subplot(111).plot(AS)

canvas1 = FigureCanvasTkAgg(fig1, master=frame_top)  # A tk.DrawingArea.
canvas1.draw()
canvas1.get_tk_widget().pack(side = "left",fill='both', expand=True)

fig2 = Figure(dpi=100)  # figsize=(10, 6),
fig2.add_subplot(111).plot(x, y)
# fig.add_subplot(111).plot(AS)

canvas2 = FigureCanvasTkAgg(fig2, master=frame_top)  # A tk.DrawingArea.
canvas2.draw()
canvas2.get_tk_widget().pack(side = "left",fill='both', expand=True)


fig3 = Figure(dpi=100)  # figsize=(10, 6),
fig3.add_subplot(111).plot(x, y)
# fig.add_subplot(111).plot(AS)

canvas3 = FigureCanvasTkAgg(fig3, master=frame_top)  # A tk.DrawingArea.
canvas3.draw()
canvas3.get_tk_widget().pack(side = "left",fill='both', expand=True)
# toolbar = NavigationToolbar2Tk(canvas, frame_top)
# toolbar.update()

# tool = tk.Button(toolbar, text = "my tool")
# tool.pack(side='left')#, fill='x', expand=True)


root.mainloop()

Пробовал использовать горизонтальную полосу прокрутки, но она тоже почему-то не работает. Если есть какие-либо другие предложения или какой-либо другой способ показать несколько гистограмм внутри фрейма.

Вы можете уменьшить диаграммы или объединить их. И как вы пытались добавить полосу прокрутки? Почему это не работает?

TheLizzard 22.06.2024 16:49

в вашем коде я вижу только 3 графика - так где же остальные? Покажите код, который действительно создает проблему.

furas 22.06.2024 17:38

возможно, создайте только один рисунок с 5 подграфиками. И он может автоматически вместить все графики на рисунке.

furas 22.06.2024 17:39

код мог бы быть короче и проще в использовании, если бы вы использовали for-цикл для создания всех графиков и сохраняли бы их в списке - вместо отдельных переменных canvas1,canvas2,canvas3fig1,fig2,fig3 и т. д.

furas 22.06.2024 17:41

возможно, используйте grid() вместо pack() — это позволяет установить weight для всех столбцов, и они должны иметь одинаковую ширину. ИЛИ вам придется вручную добавлять ширину к каждому графику canvas3.get_tk_widget()['width'] = 100, но размер может не рассчитываться автоматически

furas 22.06.2024 17:45
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
5
70
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В моем Linux помогает, когда я присваиваю любое значение (событие 1) ширине всего холста.

canvas.get_tk_widget()['width'] = 1
canvas1.get_tk_widget()['width'] = 1
canvas2.get_tk_widget()['width'] = 1
canvas3.get_tk_widget()['width'] = 1

Минимальный рабочий код с 10 графиками

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

# --- main ---

x = [1, 2, 3, 4]
y = [1, 2, 3, 4]
AS = [10 / 2 ** 0]

# ---

root = tk.Tk()
root.geometry("1000x1000")
root.title("eggs")

# ---

frame_top = tk.Frame(root)
frame_top.pack(fill='both', expand=True)

plots = []

for _ in range(10):
    fig = Figure(dpi=100)  # figsize=(10, 6),
    fig.add_subplot(111).plot(x, y)
    # fig.add_subplot(111).plot(AS)

    canvas = FigureCanvasTkAgg(fig, master=frame_top)  # A tk.DrawingArea.
    canvas.draw()
    canvas.get_tk_widget().pack(side = "left", fill='both', expand=True)
    canvas.get_tk_widget()['width'] = 1
    plots.append({'fig': fig, 'canvas': canvas})

root.mainloop()

Результат:

Но это не так полезно, потому что все участки маленькие.


Это также работает, когда я помещаю все графики на один холст.

for i in range(10):
    fig.add_subplot(1, 10, i+1).plot(x, y)

Но это может быть бесполезно, если вы планируете добавить панели инструментов или переместить/закрыть некоторые графики.

Полный рабочий код:

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

# --- main ---

x = [1, 2, 3, 4]
y = [1, 2, 3, 4]
AS = [10 / 2 ** 0]

# ---

root = tk.Tk()
root.geometry("1000x1000")
root.title("eggs")

# ---

frame_top = tk.Frame(root)
frame_top.pack(fill='both', expand=True)

plots = []

fig = Figure(dpi=100)  # figsize=(10, 6),
canvas = FigureCanvasTkAgg(fig, master=frame_top)  # A tk.DrawingArea.
canvas.draw()
canvas.get_tk_widget().pack(side = "left", fill='both', expand=True)

for i in range(10):
    line = fig.add_subplot(1, 10, i+1).plot(x, y)
    plots.append(line)

root.mainloop()


Используя grid(), мне нужно было установить правильное значение ширины и высоты, поэтому я использовал событие <Configure>, чтобы сделать это при создании (или изменении размера) окна.

Но с grid() я могу разложить это во много рядов.

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

# --- functions ---

def resize_widgets(event):
    #print(dir(event))
    print(event.widget, event.width/5, event.height/2)

    for row in range(2):
        for col in range(5):
            widget = plots[(row,col)]['canvas'].get_tk_widget()
            widget['width'] = event.width / 5 
            widget['height'] = event.height / 2 
        
    
# --- main ---

x = [1, 2, 3, 4]
y = [1, 2, 3, 4]
AS = [10 / 2 ** 0]

# ---

root = tk.Tk()
root.geometry("1000x1000")
root.title("eggs")

# ---

frame_top = tk.Frame(root)
frame_top.pack(fill='both', expand=True)

plots = {}

for row in range(2):
    for col in range(5):
        fig = Figure(dpi=100)  # figsize=(10, 6),
        fig.add_subplot(111).plot(x, y)
        #fig.add_subplot(212).plot(x, AS)

        canvas = FigureCanvasTkAgg(fig, master=frame_top)  # A tk.DrawingArea.
        canvas.draw()
        canvas.get_tk_widget().grid(row=row, column=col)
        #canvas.get_tk_widget()['width'] = 200
        #canvas.get_tk_widget()['height'] = 500
        
        plots[(row,col)] = {'fig': fig, 'canvas': canvas}

frame_top.bind('<Configure>', resize_widgets)

root.mainloop()


Работает также, когда я устанавливаю weight=1 для каждой строки и столбца в grid() - и в этом нет необходимости <Configure> - так что это кажется самым простым методом.

for row in range(2):
    frame_top.rowconfigure(row, weight=1)

for col in range(5):
    frame_top.columnconfigure(col, weight=1)

Полный рабочий код:

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

# --- main ---

x = [1, 2, 3, 4]
y = [1, 2, 3, 4]
AS = [10 / 2 ** 0]

# ---

root = tk.Tk()
root.geometry("1000x1000")
root.title("eggs")

# ---

frame_top = tk.Frame(root)
frame_top.pack(fill='both', expand=True)

plots = {}

for row in range(2):
    frame_top.rowconfigure(row, weight=1)

for col in range(5):
    frame_top.columnconfigure(col, weight=2)

frame_top.columnconfigure(0, weight=1) # resize first column
frame_top.columnconfigure(4, weight=1) # resize last column

for row in range(2):
    for col in range(5):
        fig = Figure(dpi=100)  # figsize=(10, 6),
        fig.add_subplot(111).plot(x, y)
        #fig.add_subplot(212).plot(x, AS)

        canvas = FigureCanvasTkAgg(fig, master=frame_top)  # A tk.DrawingArea.
        canvas.draw()
        canvas.get_tk_widget().grid(row=row, column=col)
        
        plots[(row,col)] = {'fig': fig, 'canvas': canvas}

root.mainloop()

Это позволяет задавать разные размеры, используя пропорции - например. первый и последний столбец в 2 раза шире.

for col in range(5):
    frame_top.columnconfigure(col, weight=2)

frame_top.columnconfigure(0, weight=1)
frame_top.columnconfigure(4, weight=1)


Другим решением может быть установка Frame на tkinter.Canvas и использование скроллеров для перемещения по холсту — таким образом график может быть больше размера окна. Но это требует дополнительной работы — например, мой класс ScrolledFrame на GitHub.

Привет, Фурас, спасибо. Теперь я могу показать несколько диаграмм, но я пробовал аналогичный подход с полосой прокрутки, но он не работает. Найдите ветку ниже stackoverflow.com/questions/78656980/…

Chandrakanth Reddy 23.06.2024 08:31

если вы хотите прокручивать все элементы в окне, вам следует поместить все графики в один tkinter.Frame, а в этот кадр вставить tkinter.Canvas и прокрутить его. Но кажется, вы пытаетесь прокручивать каждый сюжет отдельно. Если вы хотите прокручивать данные/строку на графике, то у него есть собственные функции для перехвата событий мыши и выполнения функции, которая будет изменять данные на графике - у него даже есть панель инструментов, инструменты для масштабирования и прокрутки данных.

furas 23.06.2024 12:25

Другие вопросы по теме