嵌入 Tk

嵌入 Tk#

from tkinter import ttk, Tk, Scale
import numpy as np
# Implement the default Matplotlib key bindings.
from matplotlib.backend_bases import key_press_handler
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg,
                                               NavigationToolbar2Tk)
from matplotlib.figure import Figure


class Window(Tk):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.button_quit = ttk.Button(text="Quit", command=self.destroy)
        self.slider_update = Scale(
            from_=1, to=5, orient='horizontal',
            command=self.update_frequency,
            label="Frequency [Hz]",
        )

        fig = Figure(figsize=(5, 4), dpi=100)
        self.t = np.arange(0, 3, .01)
        ax = fig.add_subplot()
        self.line, = ax.plot(self.t, 2 * np.sin(2 * np.pi * self.t))
        ax.set_xlabel("time [s]")
        ax.set_ylabel("f(t)")

        self.canvas = FigureCanvasTkAgg(fig)  # A tk.DrawingArea.
        self.canvas.draw()

        # pack_toolbar=False will make it easier to use a layout manager later on.
        self.toolbar = NavigationToolbar2Tk(self.canvas, pack_toolbar=False)
        self.toolbar.update()
        
        # pack顺序很重要。部件是按顺序处理的,如果因为窗口太小而没有剩余空间,它们就不会被显示。
        # 画布的大小相当灵活,所以我们将其放在最后打包,这样可以确保UI控件在可能的情况下尽可能长时间地显示。
        self.button_quit.pack(side='bottom')
        self.slider_update.pack(side='bottom')
        self.toolbar.pack(side='bottom', fill="x")
        self.canvas.get_tk_widget().pack(side="top", fill="both", expand=True)

        self.canvas.mpl_connect(
            "key_press_event", lambda event: print(f"you pressed {event.key}"))
        self.canvas.mpl_connect("key_press_event", key_press_handler)

    def update_frequency(self, new_val):
        # retrieve frequency
        f = float(new_val)

        # update data
        y = 2 * np.sin(2 * np.pi * f * self.t)
        self.line.set_data(self.t, y)

        # required to update canvas and attached toolbar!
        self.canvas.draw()
win = Window()
win.wm_title("Embedding in Tk")
# win.mainloop()
---------------------------------------------------------------------------
TclError                                  Traceback (most recent call last)
Cell In[2], line 1
----> 1 win = Window()
      2 win.wm_title("Embedding in Tk")
      3 # win.mainloop()

Cell In[1], line 12, in Window.__init__(self, *args, **kwargs)
     11 def __init__(self, *args, **kwargs):
---> 12     super().__init__(*args, **kwargs)
     13     self.button_quit = ttk.Button(text="Quit", command=self.destroy)
     14     self.slider_update = Scale(
     15         from_=1, to=5, orient='horizontal',
     16         command=self.update_frequency,
     17         label="Frequency [Hz]",
     18     )

File /opt/hostedtoolcache/Python/3.12.7/x64/lib/python3.12/tkinter/__init__.py:2346, in Tk.__init__(self, screenName, baseName, className, useTk, sync, use)
   2344         baseName = baseName + ext
   2345 interactive = False
-> 2346 self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
   2347 if _debug:
   2348     self.tk.settrace(_print_command)

TclError: no display name and no $DISPLAY environment variable