Исправьте размер холста, который содержит Scrollable FigureCanvasTkAgg - PullRequest
0 голосов
/ 18 апреля 2020

Я хочу спросить вас, может ли кто-нибудь исправить ScrollableTkAggX,

Проблема заключается в том, что tk.Canvas() или tk.Tk() в позиции сетки всегда нужно устанавливать gridrowconfigure и columnconfigure, чтобы заставить виджет расширяться и изменять его размер, в нормальных условиях мы можем установить width и height для виджета, чтобы получить предопределенное окно, но в этой ситуации я не могу сделать это, потому что ScrollableTkAggX(tk.Canvas) это автоматическое изменение размера.

import tkinter as tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from matplotlib.colors import to_hex


class ScrollableTkAggX(tk.Canvas):
    def __init__(self, figure, master, **kw):
        # --- create canvas with scrollbar ---
        facecolor = str(to_hex(figure.get_facecolor()))
        super(ScrollableTkAggX, self).__init__(master, **kw) # , background=facecolor
        self.grid(row=0, column=0, sticky=tk.NSEW)
        self.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)

        self.fig_wrapper = tk.Frame(self) # , background=facecolor
        self.fig_wrapper.grid(row=0, column=0, sticky=tk.NSEW)
        self.fig_wrapper.rowconfigure(0, weight=1)
        self.fig_wrapper.columnconfigure(0, weight=1)

        self.TkAgg = FigureCanvasTkAgg(figure, master=self.fig_wrapper)
        self.TkAggWidget = self.TkAgg.get_tk_widget()
        self.TkAggWidget.configure(background=facecolor)
        self.TkAggWidget.grid(row=0, column=0, sticky=tk.NSEW)

        self.hbar = tk.Scrollbar(self, orient=tk.HORIZONTAL, command=self.xview)
        self.hbar.grid(row=1, column=0, sticky=tk.EW)

        self.configure(xscrollcommand=self.hbar.set, scrollregion=self.bbox(tk.ALL))

        # when all widgets are in canvas
        self.bind('<Configure>', self.on_configure_y)
        # --- put frame in canvas ---
        self.canvas_frame = self.create_window((0, 0), window=self.fig_wrapper, anchor=tk.NW)

    # expand canvas_frame when canvas changes its size
    def on_configure_y(self, event):
        # when all widgets are in canvas
        canvas_height = event.height
        self.itemconfigure(self.canvas_frame, height=canvas_height)
        # update scrollregion after starting 'mainloop' - 20
        self.configure(scrollregion=self.bbox(tk.ALL))

    def on_configure_x(self, width):
        # when all widgets are in canvas
        self.itemconfigure(self.canvas_frame, width=width)
        # update scrollregion after starting 'mainloop'
        self.configure(scrollregion=self.bbox(tk.ALL))

    def Draw(self, width):
        self.on_configure_x(width)
        self.TkAgg.draw()
        self.xview_moveto(0)


if __name__ == '__main__':
    win = tk.Tk()

    fig = Figure(figsize=(2, 2), dpi=120, facecolor='#212121')

    mpl_white_rgb = ((255. / 255.), (255. / 255.), (255. / 255.))
    fig.text(0, 0.5, 'test', fontsize=72, color=mpl_white_rgb)

    tkagg = ScrollableTkAggX(fig, win)

    # try like that and disable them to understand what the problem
    win.rowconfigure(0, weight=1)
    win.columnconfigure(0, weight=1)

    # like that 
    # win.rowconfigure(0, weight=1)
    # win.columnconfigure(0, weight=1)

    win.mainloop()

или с другими tk.Canvas()

if __name__ == '__main__':
    win = tk.Tk()

    cnv = tk.Canvas(win, width=200, height=200)
    cnv.grid(row=0, column=0, sticky=tk.NSEW)

    # try like that and disable them to understand what the problem
    cnv.rowconfigure(0, weight=1)
    cnv.columnconfigure(0, weight=1)

    # like that
    # cnv.rowconfigure(0, weight=1)
    # cnv.columnconfigure(0, weight=1)

    fig = Figure(figsize=(2, 2), dpi=120, facecolor='#212121')

    mpl_white_rgb = ((255. / 255.), (255. / 255.), (255. / 255.))
    fig.text(0, 0.5, 'test', fontsize=72, color=mpl_white_rgb)

    tkagg = ScrollableTkAggX(fig, cnv)

    # try like that and disable them to understand what the problem
    win.rowconfigure(0, weight=1)
    win.columnconfigure(0, weight=1)


    win.mainloop()

1 Ответ

0 голосов
/ 19 апреля 2020

это очень странное решение

шаги:

удалить self.on_configure_y

добавить height в класс вызова и установить его начальным в self.create_window

окончательно позвоните и установите первый tk.Canvas(win), позвоните и установите второй ScrollableTkAggX(win) в том же положении grid один под другим.

import tkinter as tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from matplotlib.colors import to_hex


class ScrollableTkAggX(tk.Canvas):
    def __init__(self, figure, height, master, **kw):
        self.height = height
        facecolor = str(to_hex(figure.get_facecolor()))
        # --- create canvas with scrollbar ---
        super(ScrollableTkAggX, self).__init__(master, height=self.height, background=facecolor, **kw)
        self.grid(row=0, column=0, sticky=tk.NSEW)
        self.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)

        self.fig_wrapper = tk.Frame(self, background=facecolor)
        self.fig_wrapper.grid(row=0, column=0, sticky=tk.NSEW)
        self.fig_wrapper.rowconfigure(0, weight=1)
        self.fig_wrapper.columnconfigure(0, weight=1)

        self.TkAgg = FigureCanvasTkAgg(figure, master=self.fig_wrapper)
        self.TkAggWidget = self.TkAgg.get_tk_widget()
        self.TkAggWidget.configure(background=facecolor)
        self.TkAggWidget.grid(row=0, column=0, sticky=tk.NSEW)

        self.hbar = tk.Scrollbar(self, orient=tk.HORIZONTAL, command=self.xview)
        self.hbar.grid(row=1, column=0, sticky=tk.EW)

        # --- put frame in canvas ---
        self.canvas_frame = self.create_window((0, 0), window=self.fig_wrapper, height=self.height, anchor=tk.NW)
        self.configure(xscrollcommand=self.hbar.set, scrollregion=self.bbox(tk.ALL))

    # expand canvas_frame when canvas changes its size
    def on_configure_x(self, width):
        # when all widgets are in canvas
        self.itemconfigure(self.canvas_frame, width=width)
        # update scrollregion after starting 'mainloop'
        self.configure(scrollregion=self.bbox(tk.ALL))

    def Draw(self, width):
        self.on_configure_x(width)
        self.TkAgg.draw()
        self.xview_moveto(0)

if __name__ == '__main__':
    win = tk.Tk()

    cnv = tk.Canvas(win, width=200, height=200)
    cnv.grid(row=0, column=0, sticky=tk.NSEW)

    fig = Figure(figsize=(2, 2), dpi=120, facecolor='#212121')

    mpl_white_rgb = ((255. / 255.), (255. / 255.), (255. / 255.))
    fig.text(0, 0.5, 'test', fontsize=72, color=mpl_white_rgb)

    tkagg = ScrollableTkAggX(figure=fig,  master=win, height=200)
    tkagg.grid(row=0, column=0, sticky=tk.NSEW)


    win.mainloop()
...