matplotlib 图在 tkinter 中改变大小 window

matplotlib plot changes size in tkinter window

在此示例中,您可以输入点坐标,然后将其保存在树视图中并绘制。很简单。不过我发现我可以 "initialize" 我的情节按照我想要的方式格式化,但是一旦我添加第一点,情节似乎 "grow" 并占用更多的 tkinter window。我不知道为什么会发生这种情况或如何控制它以保持其原始大小。谢谢

import tkinter as tk
from tkinter import ttk
import numpy as np

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib
from matplotlib.figure import Figure
matplotlib.use("TkAgg")


class MainGUI(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.title('Title')
        self.geometry('750x500')

        self.nb = ttk.Notebook(self)
        self.nb.grid(row=0, column=0, columnspan=5, rowspan=4, sticky='NESW')
        self.tab2 = ttk.Frame(self.nb)
        self.nb.add(self.tab2, text='Tab2')

        self.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)
        tab2_r = 8
        tab2_c = 4
        for i in range(tab2_r):
            self.tab2.rowconfigure(i, weight=1)
        for i in range(tab2_c):
            self.tab2.columnconfigure(i, weight=1)

        self.makeTable()
        self.makePlot()
        self.makeWidgets()

    def makeWidgets(self):
        self.Labels = []
        self.Entries = []
        self.labText = [('X Location:'), ('Y Location:')]

        self.xGrid = 1
        self.yGrid = int(np.ceil(len(self.labText) / self.xGrid))
        i = 0
        for j in range(0, self.xGrid + 1, 2):
            for k in range(self.yGrid):
                if(i == len(self.labText)):
                    break
                else:
                    self.label = tk.Label(self.tab2, text=self.labText[i])
                    self.label.grid(column=j, row=k + 8, sticky='SW')
                    self.Labels.append(self.label)
                    self.entry = tk.Entry(self.tab2)
                    self.entry.insert(0, '0.0000')
                    self.entry.grid(column=j + 1, row=k + 8, sticky='NS')
                    self.Entries.append(self.entry)
                    i += 1

        self.addBtn = tk.Button(self.tab2, text='Add Entry', command=self.addEntry)
        self.addBtn.grid(column=self.xGrid + 1, row=self.yGrid + 9, sticky='NSEW')

    def makeTable(self):
        tab_header = ['Pattern #', 'Description']
        self.tree = ttk.Treeview(self.tab2, columns=tab_header, height=5, show="headings")
        vsb = ttk.Scrollbar(self.tab2, orient="vertical", command=self.tree.yview)
        self.tree.configure(yscrollcommand=vsb.set)
        self.tree.grid(column=0, row=0, columnspan=2, rowspan=5, sticky='NSEW')
        vsb.grid(column=1, row=0, rowspan=5, sticky='ENS')
        self.tree.heading(tab_header[0], text=tab_header[0].title())
        self.tree.column(tab_header[0], width=30, anchor='center')
        self.tree.heading(tab_header[1], text=tab_header[1].title())
        self.tree.column(tab_header[1], width=170, anchor='center')
        self.tree.insert('', 'end', values=("", "(new)"))
        self.counter = 1

    def addEntry(self):
        check = (len(self.tree.get_children()) == 1)
        self.description = "Location: " + self.Entries[0].get() + ", " + self.Entries[1].get()
        self.tree.insert('', 'end', values=(self.counter, self.description))
        newEntry = [float(self.Entries[0].get()), float(self.Entries[1].get())]
        if(check == True):
            self.points = newEntry
        else:
            self.points = np.vstack((self.points, newEntry))
        self.counter += 1
        self.plotstuff()

    def makePlot(self):
        self.fig = Figure(figsize=(1, 1), dpi=100)
        self.ptrnFig = self.fig.add_subplot(111)
        self.ptrnFig.plot([1], [1])
        self.ptrnFig.axis([-1, 1, -1, 1])
        self.ptrnFig.spines['left'].set_position('zero')
        self.ptrnFig.spines['bottom'].set_position('zero')
        self.ptrnFig.grid(True)
        self.canvas = FigureCanvasTkAgg(self.fig, self.tab2)
        self.canvas.draw()
        self.canvas.get_tk_widget().grid(column=2, row=0, columnspan=2, rowspan=5, sticky='NSEW')

    def plotstuff(self):
        self.ptrnFig.cla()
        if(np.ndim(self.points) == 1):
            x = self.points[0]
            y = self.points[1]
        else:
            x = self.points[:, 0]
            y = self.points[:, 1]
        self.ptrnFig.grid(True)
        self.ptrnFig.axis('equal')
        self.ptrnFig.scatter(x, y, c="b", marker="o")
        self.canvas = FigureCanvasTkAgg(self.fig, self.tab2)
        self.canvas.draw()
        self.canvas.get_tk_widget().grid(column=2, row=0, columnspan=2, rowspan=5, sticky='NSEW')


def main():
    MainGUI().mainloop()


if __name__ == '__main__':
    main()

我真的不能说为什么地块面积增加了。不过,我可以告诉你的是,你使用了错误的策略。每次添加一个新点时,您都​​在创建一个新图形和新 canvas,这会浪费大量能量并导致您遇到问题。相反,您应该创建一个空图,其中包含一个空艺术家,并在每次单击该按钮时向该艺术家添加新点。

看代码(我做的修改主要在makePlot()plotstuff()):

import tkinter as tk
from tkinter import ttk
import numpy as np

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib
from matplotlib.figure import Figure
matplotlib.use("TkAgg")


class MainGUI(tk.Tk):

    def __init__(self):
        tk.Tk.__init__(self)
        self.title('Title')
        self.geometry('750x500')

        self.nb = ttk.Notebook(self)
        self.nb.grid(row=0, column=0, columnspan=5, rowspan=4, sticky='NESW')
        self.tab2 = ttk.Frame(self.nb)
        self.nb.add(self.tab2, text='Tab2')

        self.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)
        tab2_r = 8
        tab2_c = 4
        for i in range(tab2_r):
            self.tab2.rowconfigure(i, weight=1)
        for i in range(tab2_c):
            self.tab2.columnconfigure(i, weight=1)

        self.makeTable()
        self.makePlot()
        self.makeWidgets()

    def makeWidgets(self):
        self.Labels = []
        self.Entries = []
        self.labText = [('X Location:'), ('Y Location:')]

        self.xGrid = 1
        self.yGrid = int(np.ceil(len(self.labText) / self.xGrid))
        i = 0
        for j in range(0, self.xGrid + 1, 2):
            for k in range(self.yGrid):
                if(i == len(self.labText)):
                    break
                else:
                    self.label = tk.Label(self.tab2, text=self.labText[i])
                    self.label.grid(column=j, row=k + 8, sticky='SW')
                    self.Labels.append(self.label)
                    self.entry = tk.Entry(self.tab2)
                    self.entry.insert(0, '0.0000')
                    self.entry.grid(column=j + 1, row=k + 8, sticky='NS')
                    self.Entries.append(self.entry)
                    i += 1

        self.addBtn = tk.Button(self.tab2, text='Add Entry', command=self.addEntry)
        self.addBtn.grid(column=self.xGrid + 1, row=self.yGrid + 9, sticky='NSEW')

    def makeTable(self):
        tab_header = ['Pattern #', 'Description']
        self.tree = ttk.Treeview(self.tab2, columns=tab_header, height=5, show="headings")
        vsb = ttk.Scrollbar(self.tab2, orient="vertical", command=self.tree.yview)
        self.tree.configure(yscrollcommand=vsb.set)
        self.tree.grid(column=0, row=0, columnspan=2, rowspan=5, sticky='NSEW')
        vsb.grid(column=1, row=0, rowspan=5, sticky='ENS')
        self.tree.heading(tab_header[0], text=tab_header[0].title())
        self.tree.column(tab_header[0], width=30, anchor='center')
        self.tree.heading(tab_header[1], text=tab_header[1].title())
        self.tree.column(tab_header[1], width=170, anchor='center')
        self.tree.insert('', 'end', values=("", "(new)"))
        self.counter = 1

    def addEntry(self):
        check = (len(self.tree.get_children()) == 1)
        self.description = "Location: " + self.Entries[0].get() + ", " + self.Entries[1].get()
        self.tree.insert('', 'end', values=(self.counter, self.description))
        newEntry = [float(self.Entries[0].get()), float(self.Entries[1].get())]
        if(check == True):
            self.points = np.array(newEntry, ndmin=2)
        else:
            self.points = np.vstack((self.points, newEntry))
        self.counter += 1
        self.plotstuff()

    def makePlot(self):
        self.fig = Figure(figsize=(1, 1), dpi=100)
        self.ptrnFig = self.fig.add_subplot(111)
        self.ptrnFig.axis([-1, 1, -1, 1])
        self.ptrnFig.spines['left'].set_position('zero')
        self.ptrnFig.spines['bottom'].set_position('zero')
        self.ptrnFig.grid(True)
        self.canvas = FigureCanvasTkAgg(self.fig, self.tab2)
        self.canvas.draw()
        self.canvas.get_tk_widget().grid(column=2, row=0, columnspan=2, rowspan=5, sticky='NSEW')
        self.scat = self.ptrnFig.scatter([], [], c="b", marker="o")

    def plotstuff(self):
        self.scat.set_offsets(self.points)
        # adjust the limits of the axes
        xmin = min(self.points[:, 0])
        xmax = max(self.points[:, 0])
        ymin = min(self.points[:, 1])
        ymax = max(self.points[:, 1])
        self.ptrnFig.set_xlim(xmin - 0.1 * (xmax - xmin), xmax + 0.1 * (xmax - xmin))
        self.ptrnFig.set_ylim(ymin - 0.1 * (ymax - ymin), ymax + 0.1 * (ymax - ymin))
        self.canvas.draw_idle()


def main():
    MainGUI().mainloop()


if __name__ == '__main__':
    main()