python - matplotlib 图表缩小了 tkinter 窗口

标签 python matplotlib tkinter

我已经在我的 tkinter 窗口中实现了一个 matplotlib 图表,但是每次我点击“确定”并将其添加到应用程序时,它都会调整整个窗口的大小并切断轴刻度。我玩过 figsizecanvas ,但没有设法解决它。有没有人对这种行为有解释?
我已经简化了代码,以便它通过单击“确定”来运行。
单击确定之前:
Before
点击确定后:
After

from tkinter import *
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

class StockApp(Frame):
    def __init__(self, master):
        super(StockApp, self).__init__(master)
        self.place()
        self.widgets()

    def widgets(self):
        # width * height
        root.geometry('500x400')
        root.configure(bg='#FFFFFF')

        # Header
        header_label = Label(text='Stock Prices', font=(
            'Calibri', 22, 'bold'), bg='#FFFFFF')
        header_label.place(x=30, y=15)

        # Enter your API key
        api_key_label = Label(text='API key', font=(
            'Calibri', 10), bg='#FFFFFF')
        api_key_label.place(x=30, y=65)

        self.api_key_field = Entry(
            width=32, font=('Calibri', 10), bg='#F4F4F4')
        self.api_key_field.config(show="*")
        self.api_key_field.place(x=30, y=90)

        # Enter an index
        index_label = Label(text='Stock index', font=(
            'Calibri', 10), bg='#FFFFFF')
        index_label.place(x=280, y=65)

        self.index_field = Entry(width=15, font=('Calibri', 10), bg='#F4F4F4')
        self.index_field.place(x=280, y=90)

        # OK button
        ok_btn = Button(text='OK', command=self.ok, font=(
            'Calibri', 8), bg='#F4F4F4', width=5)
        ok_btn.place(x=400, y=88)

    def call_api(self):
        pass
       
    def format_df(self):

        self.df = pd.DataFrame({'date': ['2020-11-06', '2020-11-07', '2020-11-08', '2020-11-09'], 'adj_close': [200, 210, 205, 215]})
        self.df['date'] = pd.to_datetime(self.df['date'])
        self.df.set_index('date', inplace = True)

    def draw_chart(self):

        #plot data
        fig, ax = plt.subplots(figsize=(2,1), dpi=50)
        self.df.plot(ax=ax)

        # #set major ticks format
        ax.xaxis.set_major_formatter(mdates.DateFormatter('%b %Y'))

        ax.spines['top'].set_visible(False)
        ax.spines['right'].set_visible(False)

        ax.get_legend().remove()

        canvas = FigureCanvasTkAgg(fig, master=root)
        canvas.draw() # TK-Drawingarea
        # Do I need to place both?
        canvas.get_tk_widget().place(x = 30, y = 150)
        canvas._tkcanvas.place(x = 30, y = 150)

    def ok(self):
        self.call_api()
        self.format_df()
        self.draw_chart()


if __name__ == "__main__":
    root= Tk()
    app= StockApp(root)
    root.title('Stock prices')
    mainloop()

最佳答案

一段时间以来,这个问题一直困扰着我。在我包含“ctypes.windll.shcore.SetProcessDpiAwareness(1)”之前,我得到了与您描述的完全相同的行为。
这是一个 DPI 问题,尽管在 tkinter 中我无法找到修复它的方法。
根据 Microsoft documentation对于 SetProcessDpiAwareness(value):

value: The DPI awareness value to set. Possible values are from the PROCESS_DPI_AWARENESS enumeration.


“值”为 1(如上)指向:

PROCESS_SYSTEM_DPI_AWARE: System DPI aware. This app does not scale for DPI changes. It will query for the DPI once and use that value for the lifetime of the app. If the DPI changes, the app will not adjust to the new DPI value. It will be automatically scaled up or down by the system when the DPI changes from the system value.


下面的示例代码基于您提供的简化版本,似乎可以解决问题:
from tkinter import *
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import ctypes


class StockApp(Frame):
    def __init__(self, master):
        self.master = master
        super(StockApp, self).__init__(master)
        self.place()
        self.widgets()

    def widgets(self):
        # width * height
        root.geometry('500x400')

        # OK button
        ok_btn = Button(text='OK', command=self.ok, bg='#F4F4F4', width=5)
        ok_btn.pack(side=tk.TOP)

    def format_df(self):
        self.df = pd.DataFrame({'date': ['2020-11-06', '2020-11-07', '2020-11-08', '2020-11-09'], 'adj_close': [200, 210, 205, 215]})
        self.df['date'] = pd.to_datetime(self.df['date'])
        self.df.set_index('date', inplace=True)

    def draw_chart(self):
        fig, ax = plt.subplots(figsize=(2, 1), dpi=100)
        self.df.plot(ax=ax)

        canvas = FigureCanvasTkAgg(fig, master=root)
        canvas.draw()
        canvas.get_tk_widget().pack(side=tk.TOP)

    def ok(self):
        self.format_df()
        self.draw_chart()


if __name__ == "__main__":
    ctypes.windll.shcore.SetProcessDpiAwareness(1)
    root= Tk()

    app= StockApp(root)
    root.title('Stock prices')
    mainloop()

关于python - matplotlib 图表缩小了 tkinter 窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64777654/

相关文章:

python - 使用 threading 和 tkinter 模块在 python 中停止线程并避免 'RuntimeError' 的最佳方法是什么?

python - 在python中将字符串转换为字典

python - 使用辅助轴线图制作分类或分组条形图

python - Python Pillow 不支持保存到 EPS?

python - 使用 matplotlib.animation 从 matplotlib 制作视频后创建的空 .mp4 文件

python - 如何使用渐变颜色为分布图的条形着色?

python - 将 “stdout” 重定向到多个滚动文本小部件?

带有 Tkinter 的 Python 聊天机器人

python - 使用特定单词在字符串中查找 n 个单词的最优雅方法

java应用程序的python mechanize问题