如何在Tkinter中将类/窗口从“普通”窗口转换为Toplevel()窗口?

2024-04-23 10:33:16 发布

您现在位置:Python中文网/ 问答频道 /正文

我是Tkinter编程新手,我正在尝试使窗口/类“GraphPage\u cpu”成为此结构中的顶级()窗口。我该怎么做才能让按下“开始页面”上的“CPU使用率”按钮并打开一个包含图形页面的新窗口

我还必须给用户“j_4321”一个巨大的赞誉。他真的帮了我很大的忙,弄清楚了如何绘制cpu测量值

import tkinter as tk
from tkinter import ttk
from tkinter import filedialog
from tkinter import Toplevel
from tkinter.filedialog import askopenfilename
from tkinter.messagebox import showinfo, showwarning, askquestion
from tkinter import OptionMenu
from tkinter import StringVar

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib.figure import Figure
from matplotlib import style
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import matplotlib.dates as mdates
from psutil import cpu_percent
from psutil import virtual_memory
from datetime import datetime, timedelta

from sklearn.metrics import silhouette_score
from sklearn.cluster import KMeans
import sklearn.cluster as cluster
import scipy.spatial.distance as sdist
from sklearn.ensemble import IsolationForest

import pandas as pd
import numpy as np
import seaborn as sn

from sklearn.preprocessing import MinMaxScaler
from sklearn.preprocessing import StandardScaler

RANDOM_STATE = 42 #used to help randomly select the data points
low_memory=False
LARGE_FONT= ("Verdana", 12)
style.use("ggplot")

f = Figure(figsize=(5,5), dpi=100)
a = f.add_subplot(111)


class Analyticsapp(tk.Tk):

    def __init__(self, *args, **kwargs):
        
        tk.Tk.__init__(self, *args, **kwargs)
        
        #tk.Tk.iconbitmap(self, default="iconimage_kmeans.ico") #Icon for program
        tk.Tk.wm_title(self, "Advanched analytics")
        
        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand = True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)
        
        self.frames = {} 
        
        for F in (StartPage, GraphPage_cpu):

            frame = F(container, self)

            self.frames[F] = frame

            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame(StartPage)

    def show_frame(self, cont):

        frame = self.frames[cont]
        frame.tkraise()
        
class StartPage(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text=
                         "Advanched analytics", font=LARGE_FONT)
        label.pack(pady=10, padx=10)
        
        button3 = ttk.Button(self, text="CPU Usage", 
                            command=lambda: controller.show_frame(GraphPage_cpu))
        button3.pack(fill='x')

class GraphPage_cpu(tk.Frame):

    def __init__(self, parent, controller, nb_points=360):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="CPU Usage", font=LARGE_FONT)
        label.pack(pady=10, padx=10, side='top')

        # matplotlib figure
        self.figure = Figure(figsize=(5, 5), dpi=100)
        self.ax = self.figure.add_subplot(111)
        # format the x-axis to show the time
        myFmt = mdates.DateFormatter("%H:%M:%S")
        self.ax.xaxis.set_major_formatter(myFmt)
        # initial x and y data
        dateTimeObj = datetime.now() + timedelta(seconds=-nb_points)
        self.x_data = [dateTimeObj + timedelta(seconds=i) for i in range(nb_points)]
        self.y_data = [0 for i in range(nb_points)]
        # create the plot
        self.plot = self.ax.plot(self.x_data, self.y_data, label='CPU')[0]
        self.ax.set_ylim(0, 100)
        self.ax.set_xlim(self.x_data[0], self.x_data[-1])

        self.canvas = FigureCanvasTkAgg(self.figure, self)

        toolbar = NavigationToolbar2Tk(self.canvas, self)
        toolbar.update()

        button1 = ttk.Button(self, text="Back",
                             command=lambda: controller.show_frame(StartPage))
        button1.pack(side='bottom')
        
        self.canvas.get_tk_widget().pack(side='top', fill=tk.BOTH, expand=True)
        self.animate_cpu()

    def animate_cpu(self):
        # append new data point to the x and y data
        self.x_data.append(datetime.now())
        self.y_data.append(cpu_percent())
        # remove oldest data point
        self.x_data = self.x_data[1:]
        self.y_data = self.y_data[1:]
        #  update plot data
        self.plot.set_xdata(self.x_data)
        self.plot.set_ydata(self.y_data)
        self.ax.set_xlim(self.x_data[0], self.x_data[-1])
        self.canvas.draw_idle()  # redraw plot
        self.after(1000, self.animate_cpu)  # repeat after 1s
        
app = Analyticsapp()
app.geometry('500x400')
app.mainloop()

1条回答
网友
1楼 · 发布于 2024-04-23 10:33:16

您可以使GraphPage_cpuToplevel而不是Frame继承:

class GraphPage_cpu(tk.Toplevel):

    def __init__(self, parent, controller, nb_points=360):
        tk.Toplevel.__init__(self, parent)
        ...

然后,您需要更改button1命令,因为图形不再隐藏起始页,可能在单击按钮时使用self.withdraw隐藏图形。在本例中,您不再需要__init__中的controller参数

现在,您需要修改Analyticsapp.__init__GraphPage_cpu现在是顶层,而不是框架,因此您必须将其从创建所有页面的for循环中删除。您可以单独创建它,如:

 self.graph_cpu = GraphPage_cpu(self, nb_points=360)
 self.graph_cpu.withdraw()  # hide the toplevel

并添加一个类方法以显示顶级:

def show_graph_cpu(self):
    self.graph_cpu.deiconify()

最后,您需要修改起始页中的button3以显示图形:

button3 = ttk.Button(self, text="CPU Usage", 
                     command=controller.show_graph_cpu)

以下是完整的代码:

import tkinter as tk
from tkinter import ttk

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib.figure import Figure
from matplotlib import style
import matplotlib.dates as mdates
from psutil import cpu_percent
from datetime import datetime, timedelta


RANDOM_STATE = 42 #used to help randomly select the data points
low_memory = False
LARGE_FONT = ("Verdana", 12)
style.use("ggplot")


class Analyticsapp(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        #tk.Tk.iconbitmap(self, default="iconimage_kmeans.ico") #Icon for program
        tk.Tk.wm_title(self, "Advanched analytics")

        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}

        for F in (StartPage,):

            frame = F(container, self)

            self.frames[F] = frame

            frame.grid(row=0, column=0, sticky="nsew")

        self.graph_cpu = GraphPage_cpu(self, nb_points=360)
        self.graph_cpu.withdraw()  # hide window

        self.show_frame(StartPage)

    def show_frame(self, cont):

        frame = self.frames[cont]
        frame.tkraise()

    def show_graph(self):
        self.graph_cpu.deiconify()

class StartPage(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="Advanched analytics", font=LARGE_FONT)
        label.pack(pady=10, padx=10)

        button3 = ttk.Button(self, text="CPU Usage",
                             command=controller.show_graph)
        button3.pack(fill='x')

class GraphPage_cpu(tk.Toplevel):

    def __init__(self, parent, nb_points=360):
        tk.Toplevel.__init__(self, parent)
        self.protocol('WM_DELETE_WINDOW', self.withdraw)  # make the close button in the titlebar withdraw the toplevel instead of destroying it
        label = tk.Label(self, text="CPU Usage", font=LARGE_FONT)
        label.pack(pady=10, padx=10, side='top')

        # matplotlib figure
        self.figure = Figure(figsize=(5, 5), dpi=100)
        self.ax = self.figure.add_subplot(111)
        # format the x-axis to show the time
        myFmt = mdates.DateFormatter("%H:%M:%S")
        self.ax.xaxis.set_major_formatter(myFmt)
        # initial x and y data
        dateTimeObj = datetime.now() + timedelta(seconds=-nb_points)
        self.x_data = [dateTimeObj + timedelta(seconds=i) for i in range(nb_points)]
        self.y_data = [0 for i in range(nb_points)]
        # create the plot
        self.plot = self.ax.plot(self.x_data, self.y_data, label='CPU')[0]
        self.ax.set_ylim(0, 100)
        self.ax.set_xlim(self.x_data[0], self.x_data[-1])

        self.canvas = FigureCanvasTkAgg(self.figure, self)

        toolbar = NavigationToolbar2Tk(self.canvas, self)
        toolbar.update()

        button1 = ttk.Button(self, text="Hide", command=self.withdraw)
        button1.pack(side='bottom')

        self.canvas.get_tk_widget().pack(side='top', fill=tk.BOTH, expand=True)
        self.animate_cpu()

    def animate_cpu(self):
        # append new data point to the x and y data
        self.x_data.append(datetime.now())
        self.y_data.append(cpu_percent())
        # remove oldest data point
        self.x_data = self.x_data[1:]
        self.y_data = self.y_data[1:]
        #  update plot data
        self.plot.set_xdata(self.x_data)
        self.plot.set_ydata(self.y_data)
        self.ax.set_xlim(self.x_data[0], self.x_data[-1])
        self.canvas.draw_idle()  # redraw plot
        self.after(1000, self.animate_cpu)  # repeat after 1s

app = Analyticsapp()
app.geometry('500x400')
app.mainloop()

另外,在{}中,我添加了

self.protocol('WM_DELETE_WINDOW', self.withdraw)

这使得标题栏中的“关闭”按钮收回顶层而不是销毁顶层

相关问题 更多 >