Задать вопрос
  • Как разместить в tkinter окне matplotlib-фигуру, выходящую за границы экрана?

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    Код
    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()

    6797dc8ec49ac263327616.png

    З.Ы. Это решение отображает формулы LaTex и латиницу. Если нужна кириллица, то нужно установить XeLaTeX или LuaLaTeX через MiKTeX (если его используете) или, если вы используете стандартный LaTeX (pdfLaTeX), можно добавить пакет babel. И настроить matplotlib на их использование. Ну, и не забыть, чтобы используемый шрифт поддерживал кириллицу.
    Ответ написан
    3 комментария