【问题标题】:Delivering data between instances of different classes in tkinter在 tkinter 中不同类的实例之间传递数据
【发布时间】:2018-12-10 10:29:59
【问题描述】:

tkinder初学者,python版本是3.6。

我正在尝试制作一个用于数据处理的 python GUI。

为不同的工作设计了不同类的多个实例。

当使用EMDFrame类中的click_emd函数处理数据时,应该在使用matplotlib显示数据的PreviewFrame类中进行绘制。但是我不知道如何在两个类之间传递数据。

我搜索过类似的问题,但没有用。

现在我正在考虑两种可能的解决方案。

一种是想办法把data_processed传给emdframe.click_emd中的previewframe.cplot。

另一个是充分利用MainPage类。它可以从一个类中获取data_processed并调用另一个类中的cplot进行绘制。但是一旦 data_processed 生成,MainPage 怎么能被注意到呢?

感到困惑,不知道该怎么办。非常感谢您的耐心。

有两个py代码文件。

Mainframe.py:

import tkinter as tk
from view import *  # initiate the subframes

class MainPage():
    def __init__(self, master=None):
        self.root = master
        root.geometry('%dx%d' % (800, 600))
        self.createPage()

    def createPage(self):
        self.emdPage = EMDFrame(root)  # subframe
        self.emdPage.place(x=20, y=300)
        self.preview = PreviewFrame(root)
        self.preview.place(x=340, y=20)
        self.aboutPage = AboutFrame(root)

        menubar = Menu(root)
        menubar.add_command(label='EMD', command=self.emd)
        menubar.add_command(label='About', command=self.aboutDisp)
        root['menu'] = menubar  # set menu

    def emd(self):
        self.emdPage.place(x=20, y=300)
        self.preview.place(x=340, y=20)
        self.aboutPage.place_forget()

    def aboutDisp(self):
        self.emdPage.place_forget()
        self.preview.place_forget()
        self.aboutPage.place(x=20, y=300)

    def plot_update(self, data, t):
        self.preview.cplot(data, t)

root = tk.Tk()
root.title("Demo")
app = MainPage(root)
root.mainloop()

view.py:

from tkinter import *
from pyhht.emd import EMD
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import numpy as np

data = []

class EMDFrame(LabelFrame):
    def __init__(self, master=None):
        LabelFrame.__init__(self, master, width=300, height=250, text='EMD')
        self.root = master
        self.createPage()

    def createPage(self):
        b = Button(self, text='EMD', width=20, height=2, command=self.click_emd)
        b.place(x=40, y=160, anchor='nw', width=80, height=40)

    def click_emd(self):
        global data
        decomposer = EMD(data)
        data_processed = decomposer.decompose()
        # Deliever data_processed to PreviewFrame's cplot function

class PreviewFrame(LabelFrame):
    def __init__(self, master=None):
        LabelFrame.__init__(self, master, width=440, height=530, text='Preview')
        self.root = master
        self.createPage()

    def cplot(self, data, t):
        f = Figure(figsize=(4, 4.8), dpi=100)
        a = f.add_subplot(111)
        a.plot(t, data)

        canvas = FigureCanvasTkAgg(f, master=self)
        canvas.draw()
        canvas.get_tk_widget().place(x=20, y=0)


    def createPage(self):
        t = np.arange(0.0, 3, 0.01)
        s = np.sin(2 * np.pi * t)
        self.cplot(s,t)

class AboutFrame(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.root = master
        self.createPage()

    def createPage(self):
        Label(self, text='About').pack()

【问题讨论】:

    标签: python-3.x tkinter


    【解决方案1】:

    您不是在类之间传递数据,而是在类的两个实例之间传递数据。

    为了让一个实例向类的另一个实例发送数据,它需要知道它。所以在 MainFrame.py 中我们将预览类的引用传递给 emdPage。

    def createPage(self):
        self.preview = PreviewFrame(root)
        self.preview.place(x=340, y=20)
        self.emdPage = EMDFrame(root,self.preview)  # subframe
        self.emdPage.place(x=20, y=300)
        self.aboutPage = AboutFrame(root)
    

    然后在另一个 view.py 中,更新类以跟踪预览引用,然后在处理完数据后使用它。

    class EMDFrame(LabelFrame):
        def __init__(self, preview, master=None):
            LabelFrame.__init__(self, master, width=300, height=250, text='EMD')
            self.preview = preview
            self.root = master
            self.createPage()
    
        def createPage(self):
            b = Button(self, text='EMD', width=20, height=2, command=self.click_emd)
            b.place(x=40, y=160, anchor='nw', width=80, height=40)
    
        def click_emd(self):
            global data
            decomposer = EMD(data)
            data_processed = decomposer.decompose()
            # Deliever data_processed to PreviewFrame's cplot function
            self.preview.cplot(.....)
    

    (代码示例未经测试且不完整,但应说明原理) (考虑到 MainPage 类可能有更好的方法,但这会涉及更多代码。)

    【讨论】:

    • 感谢您提供优雅的解决方案。没有语法错误,可以编译运行应用程序。执行self.preview.cplot 时,出现错误。 AttributeError: '_tkinter.tkapp' object has no attribute 'cplot' 还有一个关于 tkinter 的怪事。当我使用代码EMDFrame(root,self.preview)创建emdpage实例时,我必须在启动emdpage实例之前创建预览实例,这是可以理解的。然后 emdpage 似乎是预览实例的一部分。在 GUI 中,emdpage 实例被直接移动到预览实例中。
    • 感谢您的提示。现在我知道类和实例之间的区别。问题已更新。
    猜你喜欢
    • 2017-05-21
    • 2018-09-16
    • 2016-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多