简体   繁体   English

matplotlib图在tkinter窗口中更改大小

[英]matplotlib plot changes size in tkinter window

In this example you can input point coordinates which are then saved in a treeview and plotted. 在此示例中,您可以输入点坐标,然后将其保存在树形视图中并进行绘制。 Simple enough. 很简单。 What I've found though is that I can "initialize" my plot to be formatted how I want, but as soon as I add the first point, the plot seems to "grow" and take up more of the tkinter window. 不过,我发现我可以“初始化”我的绘图以按照自己的意愿进行格式化,但是一旦我添加了第一个点,绘图就似乎在“增长”并占用了更多的tkinter窗口。 I have no idea why this happens or how to control this so it maintains its original size. 我不知道为什么会发生这种情况或如何控制这种情况,以使其保持其原始大小。 Thanks. 谢谢。

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

I cannot really say why the plot area grows. 我不能真正说出为什么地积增加。 What I can tell you, though, is that you are using the wrong strategy. 不过,我可以告诉您的是您使用了错误的策略。 You are creating a new figure and new canvas everytime you're adding a new point, which is wasting a lot of energy and causing you your problems. 每当您添加新点时,您就在创建新图形和新画布,这浪费了大量精力并给您带来了麻烦。 Instead, you should create an empty plot, with an empty artist, and add new points to this artist everytime the button is clicked. 相反,您应该创建一个具有空艺术家的空情节,并在每次单击该按钮时向该艺术家添加新点。

Consider the code (the modifications I made are mostly in makePlot() and plotstuff() ): 考虑一下代码(我所做的修改大部分在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()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM