【问题标题】:Getting 2 separate tkinter windows instead of navigating through 3 pages获取 2 个单独的 tkinter 窗口,而不是浏览 3 个页面
【发布时间】:2019-12-21 00:24:58
【问题描述】:

我正在尝试将我的图表从 matplot 合并到 tkinter 窗口中,并能够浏览不同的图表。我现在已经尝试过实验并有一张图表。但是,我从 tkinter 获得 2 个窗口而不是 1 个。

我已经插入了我到目前为止所做的代码:

import tkinter as tk
from tkinter import ttk
import matplotlib
matplotlib.use('TkAgg')
import numpy as np
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from tkinter import *
import itertools
import copy
import networkx as nx
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, 
NavigationToolbar2Tk
from tkinter import *
import tkinter.messagebox as tm


LARGE_FONT=("Verdana", 12) #font type and font size

df1= pd.read_csv(r"U:\\GE90\nodes_fixed.csv")

df2 = pd.read_csv(r"U:\\GE90\edge_list_3_fixed.csv")

g=nx.Graph()
# Add edges and edge attributes
for i, elrow in df2.iterrows():
# g.add_edge(elrow[0], elrow[1], attr_dict=elrow[2:].to_dict())  # 
deprecated after NX 1.11
g.add_edge(elrow[0], elrow[1], **elrow[2:].to_dict())

app=Tk()

class Trial(tk.Tk):

#self -implied but does not need to be passed at all depending on the 
structure
#* = args   --> arguments, unlimited number of variables --> can pass 
through as many variables as you want
#** = kwargs --> keyboard arguments, passing through dictionaries 
def __init__(self, *args, **kwargs):

    tk.Tk.__init__(self, *args, **kwargs)
    tk.Tk.wm_title(self, "Trial Only")
    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, PageOne, PageTwo, plot):

        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="Start Page", font=LARGE_FONT)
    label.pack(pady=10,padx=10)

    button = ttk.Button(self, text="Visit Page 1",
                       command=lambda: controller.show_frame(PageOne))
    button.pack()

#Adding a page

class PageOne(tk.Frame):
def __init__(self, parent, controller):

    tk.Frame.__init__(self, parent)
    label = tk.Label(self, text="Page One", font=LARGE_FONT)
    label.pack(pady=10,padx=10)

    button1 = ttk.Button(self, text="Back to home",
                           command=lambda: 
controller.show_frame(StartPage))
    button1.pack()

    button2 = ttk.Button(self, text="Visit page two",
                        command=lambda: controller.show_frame(PageTwo))
    button2.pack()

class PageTwo(tk.Frame):

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

    button3 = ttk.Button(self, text="Back to Home",
                        command=lambda: controller.show_frame(StartPage))
    button3.pack()

    button4 = ttk.Button(self, text="Page One",
                        command=lambda: controller.show_frame(PageOne))
    button4.pack()

    button5 = ttk.Button(self, text="Visit Page 3",
                        command=lambda: controller.show_frame(PageThree))
    button5.pack()

class plot (tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label= tl.Label(self, text= "Figure 1", font = LARGE_FONT)
        label.pack(pady=10,padx=10)


# Edge list example
        print(elrow[0]) # node1
        print(elrow[1]) # node2
        print(elrow[2:].to_dict()) # edge attribute dict


# Add node attributes
for i, nlrow in df1.iterrows():
# g.node[nlrow['id']] = nlrow[1:].to_dict()  # deprecated after NX 1.11
nx.set_node_attributes(g, {nlrow['ID']:  nlrow[1:].to_dict()}) 

# Node list example
print(nlrow)

# Preview first 5 edges

list(g.edges(data=True))[0:5] 

# Preview first 10 nodes

list(g.nodes(data=True))[0:10] 

print('# of edges: {}'.format(g.number_of_edges()))
print('# of nodes: {}'.format(g.number_of_nodes()))

# Define node positions data structure (dict) for plotting
for node in g.nodes(data=True):
print(node)
print("")
node_positions = {node[0]: (node[1]['X'], -node[1]['Y']) for node in 
g.nodes(data=True)}

# Preview of node_positions
dict(list(node_positions.items())[0:5])

# Define data structure (list) of edge colors for plotting

# edge_colors = [e[2]['color'] for e in g.edges(data=True)]  
edge_colors = [e[2]['color'] for e in list(g.edges(data=True))]

# Preview first 10
edge_colors[0:10]
fig = plt.figure(figsize=(8, 6))
nx.draw(g, pos=node_positions, edge_color=edge_colors, node_size=10, 
node_color='black')
plt.title('Graph Representation of repair trail', size=15)




canvas = FigureCanvasTkAgg(fig, app)
canvas.get_tk_widget().pack()
canvas.draw()


app = Trial()
app.mainloop()

我想显示一个来自 tkinter 的窗口来显示所有不同的页面,但是,输出给了我来自 tkinter 的 2 个不同的窗口 第一个带有所有起始页面和按钮 第二个只是来自类图的图表

【问题讨论】:

  • 您使用app=Tk() 创建第一个窗口,然后在您初始化Trial 时创建第二个窗口,因为它继承自Tk。我认为您可以删除行 app=Tk(),因为您稍后会使用 app = Trial() 覆盖它。顺便说一句,您的代码中存在缩进问题,并且您发布的代码超出了 Minimal, Reproducible Example 所需的数量。
  • @j_4321 对于乱七八糟的编码和发布的代码过多,我深表歉意。我是新编码并且处于堆栈溢出状态。我想进一步询问有关用 app=Trial() 替换 app=Tk() 的问题。我刚刚在我的代码上尝试过,它给了我一个错误 NameError: name 'app' is not defined
  • 那么请修正问题中的缩进。由于您有错误,这意味着您在app = Trial() 之前使用app。要么您希望 Trial 成为根窗口,在这种情况下,在 canvas = FigureCanvasTkAgg(fig, app) 之前创建它,或者您不这样做,在这种情况下,让 Trial 继承自 Frame 并将其打包到应用程序中。
  • @j_4321 我已经这样做了,它确实结合了两者,但是,我无法离开情节,尽管点击到不同的页面,它仍然显示
  • 您需要在其中一个页面中创建绘图:首先创建Trial,然后使用canvas = FigureCanvasTkAgg(fig, <master>)创建图表,例如用PageOne替换master(存储在app.frames中的那个) .看起来您正在尝试将您不理解的代码段放在一起,所以我建议您花时间分别分析每段代码,并首先查看使用 tkinter 的 OOP 的简单示例。

标签: python-3.x csv matplotlib tkinter tkinter-canvas


【解决方案1】:

您会得到两个窗口,因为您使用app = Tk() 创建了第一个窗口,然后在您初始化Trial 时创建了第二个窗口,因为它继承自Tk。事实上你不需要app = Tk()

您希望您的情节位于其中一页中,因此您需要将创建 matplotlib 图形的所有代码移动到您的 Page 类之一中,例如PageTwo:

class PageTwo(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="Page Two")
        label.pack(pady=10, padx=10)

        # code for the plot
        fig = plt.figure(figsize=(8, 6))  # create matplotlib figure
        # add axes and plot (replace this by your matplotlib code)
        ax = fig.subplots() 
        ax.plot(range(10))
        ax.set_title('Graph Representation of repair trail', size=15)
        # create the tkinter widget to display the figure
        canvas = FigureCanvasTkAgg(fig, self)  # here self is the widget in which you want to display the figure
        canvas.get_tk_widget().pack()
        toolbar = NavigationToolbar2Tk(canvas, self)  # add toolbar
        canvas.draw()  # show content

        # navigation button 
        button3 = ttk.Button(self, text="Back to Home",
                            command=lambda: controller.show_frame(StartPage))
        button3.pack()

        button4 = ttk.Button(self, text="Page One",
                            command=lambda: controller.show_frame(PageOne))
        button4.pack()

【讨论】:

  • 我能问一下“canvas.get_tk_widget().pack()”的作用吗? .get_tk_widget 是什么?
  • @ElizabethDC canvas.get_tk_widget() 返回包含 matplotlib 图的 tkinter 小部件。 pack 是用于在页面中显示此小部件的方法,您也可以使用 gridplace 代替。
  • 我已将代码替换为:fig = Figure() canvas= plt.figure(figsize=(8, 6)) nx.draw(g, pos=node_positions, edge_color=edge_colors, node_size=10, node_color='black') plt.title('Graph Representation of repair trail', size=15) toolbar = NavigationToolbar2Tk(canvas, self) canvas.draw()' 如果我错了,请纠正我,但 fig=Figure() 提供了一个空白画布?我试过这个但是:AttributeError: 'NoneType' object has no attribute 'bbox'我不确定 bbox 来自哪里?
  • 根据您发布的代码,您应该有fig = plt.figure(figsize=(8, 6))canvas = FigureCanvasTkAgg(fig, self)。不是canvas= plt.figure(figsize=(8, 6)),因为canvas 是包含图形的FigureCanvasTkAgg,而不是matplotlib 图形。
  • 这对我来说很有意义,但是,我不明白为什么我现在收到 NameError: name 'fig' is not defined 的错误?我们已将 fig 定义为 fig = plt.figure(figsize=(8, 6))?那么为什么这个返回 fig 没有定义呢?我刚刚移动了代码顶部的所有其他计算代码,这会影响它吗?
【解决方案2】:

您正在显式创建两个窗口。

第一行是这一行:app=Tk()

第二个是app = Trial() 行,因为Trial 继承自tk.Tk

【讨论】:

  • 如果我将 app=Trial() 移动到画布线上方,它确实会将它们组合在一起,但我无法将页面更改为远离图
猜你喜欢
  • 2012-10-20
  • 2020-05-11
  • 1970-01-01
  • 2018-03-06
  • 1970-01-01
  • 2018-04-03
  • 1970-01-01
  • 2013-03-08
  • 1970-01-01
相关资源
最近更新 更多