Scrollbars for Matplotlib Figure in Tkinter

谁说我不能喝 提交于 2020-08-09 08:13:22

问题


I am trying to get scrollbars to work in Tkinter for matplotlib figures. The scrollbars don't adjust to the width and height of the loaded image and I don't know how to troubleshoot this. Any help would be appreciated.

Image:

End Result:

Code:

import os

from PIL import Image

import tkinter as tk
from tkinter import ttk, filedialog

import matplotlib as mpl
import matplotlib.pyplot as plt

mpl.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk

import numpy as np

from functools import partial

class AutoScrollbar(ttk.Scrollbar):

    def __init__(self,
                 parent,
                 *args,
                 **kwargs):
        '''
        '''
        self.parent = parent

        super().__init__(self.parent,
                         *args,
                         **kwargs)

    def set(self,
            low,
            high):
        '''
        '''
        if float(low) <= 0.0 and float(high) >= 1.0:
            self.tk.call('grid',
                         'remove',
                         self)
        else:
            self.grid()
        ttk.Scrollbar.set(self,
                          low,
                          high)

class DoubleScrollbarFrame(ttk.Frame):

    def __init__(self,
                 parent,
                 *args,
                 **kwargs):
        '''
        '''
        self.parent = parent

        super().__init__(self.parent,
                         *args,
                         **kwargs)

        #Set widgets to fill main window such that they are
        #all the same size
        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)

        self.create_widgets()
        self.position_widgets()

    def create_widgets(self):
        '''
        '''
        self.canvas = tk.Canvas(self)
        self.frame = ttk.Frame(self.canvas)
        self.scroll_x = AutoScrollbar(self,
                                      orient = tk.HORIZONTAL)
        self.scroll_y = AutoScrollbar(self,
                                      orient = tk.VERTICAL)
        self.sizegrip = ttk.Sizegrip(self)
        
        self.canvas.config(xscrollcommand = self.scroll_x.set,
                           yscrollcommand = self.scroll_y.set)
        self.scroll_x.config(command = self.canvas.xview)
        self.scroll_y.config(command = self.canvas.yview)
        
        self.canvas.create_window((0,0),
                                  window = self.frame,
                                  anchor = 'nw')
        
        self.frame.bind('<Configure>',
                        self.set_scrollregion)

    def position_widgets(self,
                         **kwargs):
        '''
        '''
        self.scroll_x.grid(row = 1,
                           column = 0,
                           sticky = 'ew')

        self.scroll_y.grid(row = 0,
                           column = 1,
                           sticky = 'ns')

        self.canvas.grid(row = 0,
                         column = 0,
                         sticky = 'nsew')

        self.sizegrip.grid(row = 1,
                           column = 1,
                           sticky = 'se')

        #NOTE: Do not use geometry manager with `self.frame`. This will
        # pass control from the canvas to grid and the canvas will then
        # no longer know how much to grow.
        
    def set_scrollregion(self,
                         event):
        '''
        '''
        self.canvas.configure(scrollregion = self.canvas.bbox('all'))

class Graph(ttk.Frame):

    def __init__(self,
                 parent,
                 axis_off = True,
                 *args,
                 **kwargs):
        '''
        '''
        self.parent = parent
        self.axis_off = axis_off

        super().__init__(self.parent,
                         *args,
                         **kwargs)

        #Set widgets to fill main window such that they are
        #all the same size
        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)

        self.create_widgets()
        self.position_widgets()

    def create_widgets(self):
        '''
        '''
        self.graph_container = DoubleScrollbarFrame(self)
        
        self.figure = plt.figure()
        self.figure.subplots_adjust(top = 1,
                                    right = 1,
                                    left= 0,
                                    bottom = 0,
                                    wspace = 0,
                                    hspace = 0)
            
        self.axis = self.figure.add_subplot(1,1,1)

        if self.axis_off:
            self.axis.set_axis_off()

        self.mpl_canvas = FigureCanvasTkAgg(self.figure,
                                            self.graph_container.frame)

        self.toolbar_frame = ttk.Frame(self)

        self.toolbar = NavigationToolbar2Tk(self.mpl_canvas,
                                            self.toolbar_frame)
        
    def position_widgets(self):
        '''
        '''
        self.toolbar.update()
        self.toolbar_frame.grid(row = 1,
                                column = 0,
                                sticky = 'sew')

        self.mpl_canvas.draw()
        self.mpl_canvas.get_tk_widget().grid(row = 0,
                                             column = 0,
                                             sticky = 'nsew')

        self.graph_container.grid(row = 0,
                                  column = 0,
                                  sticky = 'nsew')

    def load_image(self,
                   path):
        '''
        '''
        self.mpl_canvas.flush_events()
        self.axis.clear()
        
        self.image = Image.open(path)

        #NOTE: Dots per inch (dpi) in matplotlib should be used for
        # printing to paper media only. dpi is set at the time of
        # printing/scanning. Computer screen resolution is fixed by
        # the screen hardware and given in pixels per inch (ppi).
        # An image scanned at higher dpi will appear crisper on a
        # computer screen because of the difference in halftone/
        # dithering at each pixel, but the total size and number of
        # pixels in the image will be the same.
        # Matplotlib use 72 pixels per inch (ppi) for its figures by
        # default, and this cannot be changed. Thus, if you increase
        # dots per inch (dpi), the figure will appear bigger when
        # printed to screen (i.e. on the computer monitor) because
        # it will use more pixels to represent the same features.
        # When printed to paper media, however, the image will be
        # the same size regardless of dpi, but have finer halftoning/
        # dithering for an improved appearance.
        # Matplotlib sets sizes in terms of inches, so the scan dpi
        # must be known in order to get the physical size of the
        # image.
        if self.image.info.get('dpi'):
            self.scan_dpi, _ = self.image.info['dpi']
        else:
            self.scan_dpi = 100
        self.w_pel, self.h_pel = self.image.size

        self.graph_w_in = self.w_pel / self.scan_dpi
        self.graph_h_in = self.h_pel / self.scan_dpi
        self.graph_aspect_ratio = self.graph_h_in / self.graph_w_in

        self.zoom = 1
        
        self.figure.set_size_inches(self.graph_w_in * self.zoom,
                                    self.graph_h_in * self.zoom)
        
        self.image = np.array(self.image)
        
        self.axis.imshow(self.image)

        self.mpl_canvas.draw()

class FileBrowser(tk.Frame):

    def __init__(self,
                 parent,
                 path_type = 'file',
                 label_text = '',
                 file_types = (('*','All File Types...'),),
                 *args,
                 **kwargs):
        '''
        '''
        self.parent = parent
        self.path_type = path_type
        self.label_text = label_text
        self.file_types = file_types
        
        super().__init__(parent,
                         *args,
                         **kwargs)

        self.create_widgets()
        self.position_widgets()

    def create_widgets(self):
        '''
        '''
        self.label = tk.Label(self.parent,
                              text = self.label_text)

        self.path_entry = tk.Entry(self.parent,
                                   width = 50)

        self.button = ttk.Button(self.parent,
                                 text = 'Browse...',
                                 command = partial(self.open_file_dialog,
                                                   self.path_type,
                                                   self.file_types))

    def position_widgets(self):
        '''
        '''
        opts = {'padx': (5,5),
                'pady': (5,5)}
        
        self.label.grid(row = 0,
                        column = 0,
                        sticky = 'e',
                        **opts)
        self.path_entry.grid(row = 0,
                             column = 1,
                             sticky = 'w',
                             **opts)
        self.button.grid(row = 0,
                         column = 2,
                         sticky = 'w',
                         **opts)

    def open_file_dialog(self,
                         path_type,
                         file_types):
        '''
        '''
        init_dir = os.getcwd()

        if path_type == 'file':
             self.path = filedialog.askopenfilename(initialdir = init_dir,
                                                    title = 'Select file...',
                                                    filetypes = file_types)
        elif path_type == 'directory':
            self.path = filedialog.askdirectory(initialdir = init_dir,
                                                title = 'Select directory...')

        self.path_entry.delete(0,tk.END)
        self.path_entry.insert(0,self.path)

    def get_path(self):
        '''
        '''
        return self.path_entry.get()

class Loader(ttk.Frame):
    '''
    '''
    def __init__(self,
                 parent,
                 *args,
                 **kwargs):
        '''
        '''
        self.parent = parent

        super().__init__(self.parent,
                         *args,
                         **kwargs)

        #Set widgets to fill main window such that they are
        #all the same size
        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)

        self.create_widgets()
        self.position_widgets()

    def create_widgets(self):
        '''
        '''
        self.input_label_frame = ttk.LabelFrame(self,
                                                text = 'Input')
        self.output_label_frame = ttk.LabelFrame(self,
                                                 text = 'Output')
        
        self.create_file_browser(self.input_label_frame)
        self.create_ok_button(self.input_label_frame)

        self.create_output_window(self.output_label_frame)

    def create_file_browser(self,
                            label_frame):
        '''
        '''
        self.browser_frame = ttk.LabelFrame(label_frame,
                                            text = 'Select File')
        self.file_browser = FileBrowser(self.browser_frame,
                                        path_type = 'file',
                                        label_text = 'File:',
                                        file_types = (('*.tif', 'TIF'),
                                                      ('*.png', 'PNG'),))

    def create_ok_button(self,
                         label_frame):
        '''
        '''
        self.input_ok_button = ttk.Button(label_frame,
                                          text = 'OK',
                                          command = self.calibrate)

    def calibrate(self):
        '''
        '''
        path = self.file_browser.get_path()

        if path == '':
            messagebox.showerror(title = 'No File Selected',
                                 message = 'No file chosen. Please select file.')
            return

        _, ext = os.path.splitext(path)

        if ext.lower() not in ('.tif', '.png'):
            messagebox.showerror(title = 'File Is Not \"*.tif\" or \"*.png\"',
                                 message = 'File must be a \"*.tif\" or \"*.png\" image file. Please reselect file and try again.')

        img = plt.imread(path)

        self.graph.load_image(path)
        
    def create_output_window(self,
                             label_frame):
        '''
        '''
        self.output_frame = ttk.Frame(label_frame)
        self.graph = Graph(self.output_frame)

    def position_widgets(self,
                         **kwargs):
        '''
        '''
        #OK Button
        self.input_ok_button.grid(row = 4,
                                  column = 0,
                                  sticky = 'e')
        
        #Frames
        self.input_label_frame.grid(row = 0,
                                    column = 0,
                                    sticky = 'nsew')
        
        self.browser_frame.grid(row = 1,
                                column = 0,
                                sticky = 'nw')

        self.file_browser.grid(row = 0,
                               column = 0,
                               sticky = 'nsew')

        self.output_label_frame.grid(row = 0,
                                     column = 1,
                                     sticky = 'nw')

        self.graph.grid(row = 0,
                        column = 0,
                        sticky = 'nsew')

        self.output_frame.grid(row = 0,
                               column = 0,
                               sticky = 'nsew')


class MainApp(tk.Tk):

    def __init__(self,
                 title,
                 *args,
                 **kwargs):
        '''
        '''
        self._title = title

        super().__init__(*args,
                         **kwargs)

        #Set widgets to fill main window such that they are
        #all the same size
        self.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)

        #Set window title
        self.title(self._title)

        self.create_widgets()
        self.position_widgets()

    def create_widgets(self):
        '''
        '''
        self.loader = Loader(self)

    def position_widgets(self):
        '''
        '''
        self.loader.grid(row = 0,
                         column = 0,
                         sticky = 'nsew')

if __name__ == '__main__':

    #Create GUI
    root = MainApp('MainApp')

    #Run program
    root.mainloop()

回答1:


matplotlib figures are canvases. Therfore, its container frame won't resize to it, and bbox("all") won't work. Instead, we have to update the matplotlib canvas size to match the figure size and the toplevel canvas scrollregion to the figure size.

Here is the working output.

Working Output

Here is the working code.

Code

import os

from PIL import Image

import tkinter as tk
from tkinter import ttk, filedialog

import matplotlib as mpl
import matplotlib.pyplot as plt

mpl.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk

import numpy as np

from functools import partial

#Matplotlib Default DPI
DEFAULT_DPI = 100

#Matplotlib Default PPI
DEFAULT_PPI = 72

class AutoScrollbar(ttk.Scrollbar):

    def __init__(self,
                 parent,
                 *args,
                 **kwargs):
        '''
        '''
        self.parent = parent

        super().__init__(self.parent,
                         *args,
                         **kwargs)

    def set(self,
            low,
            high):
        '''
        '''
        if float(low) <= 0.0 and float(high) >= 1.0:
            self.tk.call('grid',
                         'remove',
                         self)
        else:
            self.grid()
        ttk.Scrollbar.set(self,
                          low,
                          high)

class DoubleScrollbarFrame(ttk.Frame):

    def __init__(self,
                 parent,
                 *args,
                 **kwargs):
        '''
        '''
        self.parent = parent

        super().__init__(self.parent,
                         *args,
                         **kwargs)

        #Set widgets to fill main window such that they are
        #all the same size
        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)

        self.create_widgets()
        self.position_widgets()

    def create_widgets(self):
        '''
        '''
        self.canvas = tk.Canvas(self)
        self.frame = ttk.Frame(self.canvas)
        self.scroll_x = AutoScrollbar(self,
                                      orient = tk.HORIZONTAL)
        self.scroll_y = AutoScrollbar(self,
                                      orient = tk.VERTICAL)
        self.sizegrip = ttk.Sizegrip(self)
        
        self.canvas.config(xscrollcommand = self.scroll_x.set,
                           yscrollcommand = self.scroll_y.set)
        self.scroll_x.config(command = self.canvas.xview)
        self.scroll_y.config(command = self.canvas.yview)
        
        self.canvas.create_window((0,0),
                                  window = self.frame,
                                  anchor = 'nw')
        
        self.frame.bind('<Configure>',
                        self.set_scrollregion)

    def position_widgets(self,
                         **kwargs):
        '''
        '''
        self.scroll_x.grid(row = 1,
                           column = 0,
                           sticky = 'ew')

        self.scroll_y.grid(row = 0,
                           column = 1,
                           sticky = 'ns')

        self.canvas.grid(row = 0,
                         column = 0,
                         sticky = 'nsew')

        self.sizegrip.grid(row = 1,
                           column = 1,
                           sticky = 'se')

        #NOTE: Do not use geometry manager with `self.frame`. This will
        # pass control from the canvas to grid and the canvas will then
        # no longer know how much to grow.
        
    def set_scrollregion(self,
                         event):
        '''
        '''
        self.canvas.configure(scrollregion = self.canvas.bbox('all'))

class Graph(ttk.Frame):

    def __init__(self,
                 parent,
                 axis_off = True,
                 *args,
                 **kwargs):
        '''
        '''
        self.parent = parent
        self.axis_off = axis_off

        super().__init__(self.parent,
                         *args,
                         **kwargs)

        #Set widgets to fill main window such that they are
        #all the same size
        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)

        self.create_widgets()
        self.position_widgets()

    def create_widgets(self):
        '''
        '''
        self.figure = plt.figure()
        self.figure.subplots_adjust(top = 1,
                                    right = 1,
                                    left= 0,
                                    bottom = 0,
                                    wspace = 0,
                                    hspace = 0)
            
        self.axis = self.figure.add_subplot(1,1,1)

        if self.axis_off:
            self.axis.set_axis_off()

        self.canvas = tk.Canvas(self)
        self.frame = ttk.Frame(self.canvas)

        self.mpl_canvas = FigureCanvasTkAgg(self.figure,
                                            self.frame)

        self.mpl_canvas.draw()

        self.scroll_x = AutoScrollbar(self,
                                      orient = tk.HORIZONTAL)
        self.scroll_y = AutoScrollbar(self,
                                      orient = tk.VERTICAL)
        self.sizegrip = ttk.Sizegrip(self)
        
        self.canvas.config(xscrollcommand = self.scroll_x.set,
                           yscrollcommand = self.scroll_y.set)
        self.scroll_x.config(command = self.canvas.xview)
        self.scroll_y.config(command = self.canvas.yview)
        
        self.cwid = self.canvas.create_window((0,0),
                                              window = self.frame,
                                              anchor = 'nw')

        self.frame.bind('<Configure>',
                        self.set_scrollregion)

        self.toolbar_frame = ttk.Frame(self)

        self.toolbar = NavigationToolbar2Tk(self.mpl_canvas,
                                            self.toolbar_frame)

    def set_scrollregion(self,
                         event):
        '''
        '''
        w, h = self.figure.get_size_inches()
        w = int(w * DEFAULT_DPI)
        h = int(h * DEFAULT_DPI)
        scrollregion = (0,0,w,h)
        
        self.canvas.configure(scrollregion = scrollregion)
        
    def position_widgets(self):
        '''
        '''
        self.scroll_x.grid(row = 1,
                           column = 0,
                           sticky = 'ew')

        self.scroll_y.grid(row = 0,
                           column = 1,
                           sticky = 'ns')

        self.canvas.grid(row = 0,
                         column = 0,
                         sticky = 'nsew')

        self.mpl_canvas.get_tk_widget().grid(row = 0,
                                             column = 0,
                                             sticky = 'nsew')

        self.sizegrip.grid(row = 1,
                           column = 1,
                           sticky = 'se')

        #NOTE: Do not use geometry manager with `self.frame`. This will
        # pass control from the canvas to grid and the canvas will then
        # no longer know how much to grow.

        self.toolbar.update()
        self.toolbar_frame.grid(row = 2,
                                column = 0,
                                sticky = 'sew')

    def load_image(self,
                   path):
        '''
        '''
        self.mpl_canvas.flush_events()
        self.axis.clear()
        
        self.image = Image.open(path)

        #NOTE: Dots per inch (dpi) in matplotlib should be used for
        # printing to paper media only. dpi is set at the time of
        # printing/scanning. Computer screen resolution is fixed by
        # the screen hardware and given in pixels per inch (ppi).
        # An image scanned at higher dpi will appear crisper on a
        # computer screen because of the difference in halftone/
        # dithering at each pixel, but the total size and number of
        # pixels in the image will be the same.
        # Matplotlib use 72 pixels per inch (ppi) for its figures by
        # default, and this cannot be changed. Thus, if you increase
        # dots per inch (dpi), the figure will appear bigger when
        # printed to screen (i.e. on the computer monitor) because
        # it will use more pixels to represent the same features.
        # When printed to paper media, however, the image will be
        # the same size regardless of dpi, but have finer halftoning/
        # dithering for an improved appearance.
        # Matplotlib sets sizes in terms of inches, so the scan dpi
        # must be known in order to get the physical size of the
        # image.
        if self.image.info.get('dpi'):
            self.scan_dpi, _ = self.image.info['dpi']
        else:
            self.scan_dpi = DEFAULT_DPI # matplotlib default
            
        self.w_pel, self.h_pel = self.image.size

        self.graph_w_in = self.w_pel / self.scan_dpi
        self.graph_h_in = self.h_pel / self.scan_dpi        
        
        self.figure.set_size_inches(self.graph_w_in,
                                    self.graph_h_in)
        
        self.image = np.array(self.image)
        
        self.axis.imshow(self.image)

        self.mpl_canvas.get_tk_widget().configure(
            width = self.graph_w_in * DEFAULT_DPI,
            height = self.graph_h_in * DEFAULT_DPI)
        
        self.mpl_canvas.draw()
        self.canvas.update()

class FileBrowser(tk.Frame):

    def __init__(self,
                 parent,
                 path_type = 'file',
                 label_text = '',
                 file_types = (('*','All File Types...'),),
                 *args,
                 **kwargs):
        '''
        '''
        self.parent = parent
        self.path_type = path_type
        self.label_text = label_text
        self.file_types = file_types
        
        super().__init__(parent,
                         *args,
                         **kwargs)

        self.create_widgets()
        self.position_widgets()

    def create_widgets(self):
        '''
        '''
        self.label = tk.Label(self.parent,
                              text = self.label_text)

        self.path_entry = tk.Entry(self.parent,
                                   width = 50)

        self.button = ttk.Button(self.parent,
                                 text = 'Browse...',
                                 command = partial(self.open_file_dialog,
                                                   self.path_type,
                                                   self.file_types))

    def position_widgets(self):
        '''
        '''
        opts = {'padx': (5,5),
                'pady': (5,5)}
        
        self.label.grid(row = 0,
                        column = 0,
                        sticky = 'e',
                        **opts)
        self.path_entry.grid(row = 0,
                             column = 1,
                             sticky = 'w',
                             **opts)
        self.button.grid(row = 0,
                         column = 2,
                         sticky = 'w',
                         **opts)

    def open_file_dialog(self,
                         path_type,
                         file_types):
        '''
        '''
        init_dir = os.getcwd()

        if path_type == 'file':
             self.path = filedialog.askopenfilename(initialdir = init_dir,
                                                    title = 'Select file...',
                                                    filetypes = file_types)
        elif path_type == 'directory':
            self.path = filedialog.askdirectory(initialdir = init_dir,
                                                title = 'Select directory...')

        self.path_entry.delete(0,tk.END)
        self.path_entry.insert(0,self.path)

    def get_path(self):
        '''
        '''
        return self.path_entry.get()

class Loader(ttk.Frame):
    '''
    '''
    def __init__(self,
                 parent,
                 *args,
                 **kwargs):
        '''
        '''
        self.parent = parent

        super().__init__(self.parent,
                         *args,
                         **kwargs)

        #Set widgets to fill main window such that they are
        #all the same size
        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)

        self.create_widgets()
        self.position_widgets()

    def create_widgets(self):
        '''
        '''
        self.input_label_frame = ttk.LabelFrame(self,
                                                text = 'Input')
        self.output_label_frame = ttk.LabelFrame(self,
                                                 text = 'Output')
        
        self.create_file_browser(self.input_label_frame)
        self.create_ok_button(self.input_label_frame)

        self.create_output_window(self.output_label_frame)

    def create_file_browser(self,
                            label_frame):
        '''
        '''
        self.browser_frame = ttk.LabelFrame(label_frame,
                                            text = 'Select File')
        self.file_browser = FileBrowser(self.browser_frame,
                                        path_type = 'file',
                                        label_text = 'File:',
                                        file_types = (('*.tif', 'TIF'),
                                                      ('*.png', 'PNG'),))

    def create_ok_button(self,
                         label_frame):
        '''
        '''
        self.input_ok_button = ttk.Button(label_frame,
                                          text = 'OK',
                                          command = self.calibrate)

    def calibrate(self):
        '''
        '''
        path = self.file_browser.get_path()

        if path == '':
            messagebox.showerror(title = 'No File Selected',
                                 message = 'No file chosen. Please select file.')
            return

        _, ext = os.path.splitext(path)

        if ext.lower() not in ('.tif', '.png'):
            messagebox.showerror(title = 'File Is Not \"*.tif\" or \"*.png\"',
                                 message = 'File must be a \"*.tif\" or \"*.png\" image file. Please reselect file and try again.')

        img = plt.imread(path)

        self.graph.load_image(path)
        
    def create_output_window(self,
                             label_frame):
        '''
        '''
        self.output_frame = ttk.Frame(label_frame)
        self.graph = Graph(self.output_frame)

    def position_widgets(self,
                         **kwargs):
        '''
        '''
        #OK Button
        self.input_ok_button.grid(row = 4,
                                  column = 0,
                                  sticky = 'e')
        
        #Frames
        self.input_label_frame.grid(row = 0,
                                    column = 0,
                                    sticky = 'nsew')
        
        self.browser_frame.grid(row = 1,
                                column = 0,
                                sticky = 'nw')

        self.file_browser.grid(row = 0,
                               column = 0,
                               sticky = 'nsew')

        self.output_label_frame.grid(row = 0,
                                     column = 1,
                                     sticky = 'nw')

        self.graph.grid(row = 0,
                        column = 0,
                        sticky = 'nsew')

        self.output_frame.grid(row = 0,
                               column = 0,
                               sticky = 'nsew')


class MainApp(tk.Tk):

    def __init__(self,
                 title,
                 *args,
                 **kwargs):
        '''
        '''
        self._title = title

        super().__init__(*args,
                         **kwargs)

        #Set widgets to fill main window such that they are
        #all the same size
        self.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)

        #Set window title
        self.title(self._title)

        self.create_widgets()
        self.position_widgets()

    def create_widgets(self):
        '''
        '''
        self.loader = Loader(self)

    def position_widgets(self):
        '''
        '''
        self.loader.grid(row = 0,
                         column = 0,
                         sticky = 'nsew')

if __name__ == '__main__':

    #Create GUI
    root = MainApp('MainApp')

    #Run program
    root.mainloop()


来源:https://stackoverflow.com/questions/63061101/scrollbars-for-matplotlib-figure-in-tkinter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!