1

I want to ask you if anyone can fix ScrollableTkAggX,

The problem is that the tk.Canvas() or tk.Tk() in the grid position always need to set the gridrowconfigure and columnconfigure, to make the widget expand and resize, in the normal condition we can set width and height for the widget to get a window predefined, but in this situation, I can't do it because ScrollableTkAggX(tk.Canvas) it's auto-resizing.

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()

or with other 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()

DaniyalAhmadSE
  • 807
  • 11
  • 20
NajmiAchraf
  • 21
  • 2
  • 5

1 Answers1

1

this is a very strange solution

steps :

delete self.on_configure_y

add height in call class and set it initial in self.create_window

finaly call and set first tk.Canvas(win), call and set second ScrollableTkAggX(win) in same position grid one under other.

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()
NajmiAchraf
  • 21
  • 2
  • 5