import tkinter as tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from PIL import Image, ImageTk
class ScrollableLabel(tk.Frame):
def __init__(self, master, **kwargs):
super().__init__(master, **kwargs)
# Переменная для хранения LaTeX-текста
self.latex_text = r'$\\sum_{i=0}^5(x_i); $' * 100
# Создаем Canvas и Scrollbar (вертикальный и горизонтальный)
self.canvas = tk.Canvas(self, bg="white")
self.v_scrollbar = tk.Scrollbar(self, orient="vertical", command=self.canvas.yview)
self.h_scrollbar = tk.Scrollbar(self, orient="horizontal", command=self.canvas.xview)
# Настраиваем Canvas для поддержки прокрутки
self.scrollable_frame = tk.Frame(self.canvas, bg="white")
self.scrollable_frame.bind(
"<Configure>",
lambda e: self.canvas.configure(
scrollregion=self.canvas.bbox("all")
)
)
self.canvas.create_window((20, 20), window=self.scrollable_frame, anchor="nw")
self.canvas.configure(yscrollcommand=self.v_scrollbar.set, xscrollcommand=self.h_scrollbar.set)
# Размещаем Canvas и Scrollbar
self.v_scrollbar.pack(side="right", fill="y")
self.h_scrollbar.pack(side="bottom", fill="x")
self.canvas.pack(side="left", fill="both", expand=True)
# Привязываем прокрутку колесом мыши
self.bind_mouse_wheel()
# Создаем LaTeX-изображение
self.create_latex_label()
def bind_mouse_wheel(self):
"""
Привязывает прокрутку колесом мыши к Canvas.
"""
# Для вертикальной прокрутки (Windows/Linux)
self.canvas.bind_all("<MouseWheel>", self._on_mouse_wheel)
# Для горизонтальной прокрутки (Shift + колесо мыши)
self.canvas.bind_all("<Shift-MouseWheel>", self._on_shift_mouse_wheel)
def _on_mouse_wheel(self, event):
"""
Обрабатывает событие вертикальной прокрутки колесом мыши.
"""
if event.num == 4 or event.delta > 0: # Прокрутка вверх
self.canvas.yview_scroll(-1, "units")
elif event.num == 5 or event.delta < 0: # Прокрутка вниз
self.canvas.yview_scroll(1, "units")
def _on_shift_mouse_wheel(self, event):
"""
Обрабатывает событие горизонтальной прокрутки колесом мыши (Shift + колесо).
"""
if event.delta > 0: # Прокрутка влево
self.canvas.xview_scroll(-1, "units")
elif event.delta < 0: # Прокрутка вправо
self.canvas.xview_scroll(1, "units")
def create_latex_label(self):
"""
Создает Label с LaTeX-изображением и добавляет его в scrollable_frame.
"""
# Создаем фигуру matplotlib для рендеринга LaTeX
fig = Figure(figsize=(20, 20)) # Размер фигуры
fig.patch.set_alpha(1) # Прозрачный фон
ax = fig.add_subplot(111)
ax.axis("off") # Отключаем оси
# Рендерим LaTeX-текст
ax.text(0.0, 1.0, self.latex_text, fontsize=20, ha="left", va="top", usetex=True)
# Отчекрыживаем поля
fig.subplots_adjust(left=0, right=1, bottom=0, top=1)
# Преобразуем фигуру в изображение
canvas = FigureCanvasTkAgg(fig, master=self.scrollable_frame)
canvas.draw()
# Получаем изображение из canvas
width, height = fig.get_size_inches() * fig.get_dpi() # Размеры в пикселях
image = Image.frombytes('RGBA', (int(width), int(height)), bytes(canvas.buffer_rgba()))
# Для версий matplotlib <= 3.8:
# image = Image.frombytes('RGB', (int(width), int(height)), canvas.tostring_rgb())
# image.save('lol.png')
# Преобразуем изображение в формат, поддерживаемый Tkinter
self.image = ImageTk.PhotoImage(image)
# Создаем Label с изображением и добавляем его в scrollable_frame
self.label = tk.Label(self.scrollable_frame, image=self.image, bg="white")
self.label.pack(pady=10)
# Сохраняем ссылку на изображение, чтобы оно не удалялось сборщиком мусора
self.label.image = self.image
def update_latex_text(self, new_text):
"""
Обновляет LaTeX-текст и перерисовывает Label.
"""
self.latex_text = new_text
# Очищаем scrollable_frame и создаем новый Label
for widget in self.scrollable_frame.winfo_children():
widget.destroy()
self.create_latex_label()
if __name__ == "__main__":
root = tk.Tk()
root.title("LaTeX в Tk.Label с прокруткой")
# Создаем ScrollableLabel
scrollable_label = ScrollableLabel(root)
scrollable_label.pack(fill="both", expand=True, padx=10, pady=10)
# Создаем Entry для ввода текста
entry = tk.Entry(root, font=("Arial", 14))
entry.pack(fill="x", padx=10, pady=5)
# Создаем Button для обновления текста
def on_button_click():
new_text = entry.get()
scrollable_label.update_latex_text(new_text)
button = tk.Button(root, text="Обновить", command=on_button_click, font=("Arial", 14))
button.pack(pady=5)
root.mainloop()