简体   繁体   English

如何将类/窗口从“正常” window 转换为 Tkinter 中的 Toplevel() window?

[英]How do I transform a class/window from a “normal” window to a Toplevel() window in Tkinter?

I'm new to programming in Tkinter and I'm trying to make the window/class "GraphPage_cpu" a Toplevel() window within this structure.我是 Tkinter 编程的新手,我正在尝试在此结构中使窗口/类“GraphPage_cpu”成为 Toplevel() window。 How do I go about make it so that pressing the button "CPU Usage" on the "StartPage" and make it open a new window containing the graph page?我如何 go 让它按下“StartPage”上的“CPU Usage”按钮并打开一个包含图形页面的新 window?

Also I have to give a huge credit to the user, "j_4321".此外,我必须对用户“j_4321”给予极大的赞扬。 He really helped me a lot with figuring out how to plot cpu measures!他真的帮了我很多,弄清楚如何 plot 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()

You can make GraphPage_cpu inherit from Toplevel instead of Frame :您可以使GraphPage_cpu继承自Toplevel而不是Frame

class GraphPage_cpu(tk.Toplevel):

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

Then, you need to change button1 command since the graph is no longer hiding the Start Page, maybe use self.withdraw to hide the graph when clicking on the button.然后,您需要更改button1命令,因为图形不再隐藏起始页,也许在单击按钮时使用self.withdraw隐藏图形。 In this case, you no longer need the controller argument in __init__ .在这种情况下,您不再需要__init__中的controller参数。

Now, you need to modify Analyticsapp.__init__ : GraphPage_cpu is now a Toplevel, not a Frame, so you have to remove it from the for loop that creates all your pages.现在,您需要修改Analyticsapp.__init__GraphPage_cpu现在是 Toplevel,而不是 Frame,因此您必须将其从创建所有页面的 for 循环中删除。 You can create it separately, like:您可以单独创建它,例如:

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

And add a class method to show the toplevel:并添加一个 class 方法来显示顶层:

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

Finally you need to modify button3 in Start Page to show the graph:最后,您需要修改 Start Page 中的button3以显示图形:

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

Here is the full code:这是完整的代码:

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

Also, in GraphPage_cpu.__init__ , I have added另外,在GraphPage_cpu.__init__中,我添加了

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

that makes the close button in the titlebar withdraw the toplevel instead of destroying it.这使得标题栏中的关闭按钮撤回顶层而不是破坏它。

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

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