草庐IT

python - 通过 Tkinter 类传递数据帧

coder 2023-05-26 原文

我正在使用 Python 2.7 和 Tkinter。我几乎是面向对象程序的新手。我有一个带有许多 Tkinter 窗口的长程序,有时我要求用户加载我用 Pandas 读取的 Excel 文件,并希望永久使用和更新该值(data 变量) .我现在这样做的方式是使用全局变量,但我知道它是危险的、低效的而且一点也不优雅。

尽管根据我的 gui 类的构建方式我可以执行 controller.show_frame(framename),但我最终还是自己构建了一些框架,以便数据变量能够自行更新。

我在 Stack Overflow 中阅读并尝试了一些答案,但可能实现错误:

  • 尝试在 gui 类中创建一个字典,例如 self.app_data = {data=[],filename=""} 并从其他窗口更新它,这里的事情是我认为类 gui 仅实例化一次,它创建了所有其他窗口类,所以这不起作用。也许我在那里做错了什么。 (代码中未显示)。
  • 尝试按照建议做一些事情 here但我无法让它发挥作用。

主框架是我需要用于其他目的的某种中间步骤;以下代码是我的程序的简化。

我知道这是一个可怕的噩梦代码!谢谢你:)

import Tkinter as tk
import pandas as pd 
import tkFileDialog
import tkMessageBox
global data, strat_columns, filename
data = pd.DataFrame([])
strat_columns = []
filename = ""

class gui(tk.Tk):

    data = pd.DataFrame([])
    filename = ""
    def __init__(self):
        tk.Tk.__init__(self)
        container = tk.Frame(self)
        container.pack(side="top",fill="both",expand=True)
        self.frames = {}

        for F in (main_frame, first_frame):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")
        self.show_frame(main_frame)

    def show_frame(self,sel_frame):
        frame = self.frames[sel_frame]
        frame.tkraise()

    def get_page(self, page_class):
        return self.frames[page_class]


class main_frame(tk.Frame):

    def __init__(self,parent,controller):

        tk.Frame.__init__(self,parent)
        self.parent = parent 
        self.controller = controller
        button_new = tk.Button(self,
                           text="New window",
                           command=lambda: self.button_new_callback())
        button_new.pack()

    def button_new_callback(self,*args,**kwargs):
        self.controller.show_frame(first_frame)


class first_frame(tk.Frame):

    def __init__(self,parent,controller):
        tk.Frame.__init__(self,parent)
        self.controller = controller
        self.parent = parent
        self.show_frame = controller.show_frame
        statusText.set("Press Browse button and browse for file, then press the Go button")
        label = tk.Label(self, text="Please load a file: ")
        label.pack()
        entry = tk.Entry(self, width=50)
        entry.pack()
        button_go = tk.Button(self,
                           text="Go",
                           command=lambda: self.button_go_callback(entry,statusText,message))
        button_browse = tk.Button(self,
                               text="Browse",
                               command=lambda: self.button_browse_callback(entry))
        button_go.pack()
        button_browse.pack()
        message = tk.Label(self, textvariable=statusText)
        message.pack()

    def button_browse_callback(self,entry):
        global filename
        filename = tkFileDialog.askopenfilename()
        entry.delete(0, tk.END)
        entry.insert(0, filename)

    def button_go_callback(self,entry,statusText,message):
        global data
        input_file = entry.get()
        data = pd.read_excel(filename)
        sf = second_frame(self.parent, self)
        sf.grid(row=0, column=0, sticky="nsew")
        sf.tkraise()

class second_frame(tk.Frame):
     pass

if __name__ == "__main__":

    my_gui = gui()
    my_gui.mainloop()
    my_gui.title("TEST")

最佳答案

有几件事会导致您的程序无法正常运行。

我首先注意到的是全局变量的使用。这可以通过使用类属性来避免。

对于 class gui(tk.Tk): 行下方的 2 个变量,您需要将它们移动到 __init__ 部分,以便可以实例化这些变量.您还需要将它们变成类属性,以便其他方法甚至其他类可以与它们交互。我们可以通过将 self. 前缀添加到变量名来做到这一点。

类似于以下内容:

self.data = pd.DataFrame([])
self.filename = ""

要访问 gui 类的方法/属性,您需要将 gui 类的对象传递给使用它的其他类。

您的代码中的

statusText 未定义,因此 set() 不会在这里工作。只需添加 self.statusText 作为类属性。

您的某些小部件不需要分配给变量名称,因为没有对它们进行任何编辑。例如:

label = tk.Label(self, text="Please load a file: ")
label.pack()

这可以简单地改为:

tk.Label(self, text="Please load a file: ").pack()

这将有助于减少您编写的代码量并保持 namespace 更整洁。

有几种方法可以纠正这一切,但最简单的方法是将这段代码移到一个类中。您提供的代码没有充分的理由将多个框架与主 gui 类分开。

以下代码是您的代码的重写版本,它使用一个类来完成您的代码试图完成的任务,并减少大约 30 多行所需的代码量。我相信它可以进一步完善,但这个例子应该会有所帮助。

import Tkinter as tk
import pandas as pd
import tkFileDialog

class gui(tk.Frame):


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

        self.master = master
        self.data = pd.DataFrame([])
        self.filename = ""
        self.strat_columns = []

        self.main_frame()
        self.first_frame()
        self.mainframe.tkraise()

    def get_page(self, page_class):
        return self.frames[page_class]

    def main_frame(self):
        self.mainframe = tk.Frame(self.master)
        self.mainframe.grid(row=0, column=0, sticky="nsew")

        tk.Button(self.mainframe, text="New window", 
                  command=lambda: self.firstframe.tkraise()).pack()


    def first_frame(self):
        self.firstframe = tk.Frame(self.master)
        self.firstframe.grid(row=0, column=0, sticky="nsew")

        self.statusText = tk.StringVar()
        self.statusText.set("Press Browse button and browse for file, then press the Go button")
        label = tk.Label(self.firstframe, text="Please load a file: ").pack()
        self.first_frame_entry = tk.Entry(self.firstframe, width=50)
        self.first_frame_entry.pack()
        tk.Button(self.firstframe, text="Go", command=self.button_go_callback).pack()
        tk.Button(self.firstframe, text="Browse", command=self.button_browse_callback).pack()
        self.message = tk.Label(self.firstframe, textvariable=self.statusText)
        self.message.pack()


    def button_browse_callback(self):
        self.filename = tkFileDialog.askopenfilename()
        self.first_frame_entry.delete(0, tk.END)
        self.first_frame_entry.insert(0, self.filename)

    def button_go_callback(self):
        self.data = pd.read_excel(self.filename)


if __name__ == "__main__":
    root = tk.Tk()
    root.title("TEST")
    my_gui = gui(root)
    root.mainloop()

关于python - 通过 Tkinter 类传递数据帧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45644243/

有关python - 通过 Tkinter 类传递数据帧的更多相关文章

  1. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby - 通过 rvm 升级 ruby​​gems 的问题 - 2

    尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub

  4. ruby - 通过 erb 模板输出 ruby​​ 数组 - 2

    我正在使用puppet为ruby​​程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby​​不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这

  5. ruby - 通过 ruby​​ 进程共享变量 - 2

    我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

  6. ruby - 通过 RVM (OSX Mountain Lion) 安装 Ruby 2.0.0-p247 时遇到问题 - 2

    我的最终目标是安装当前版本的RubyonRails。我在OSXMountainLion上运行。到目前为止,这是我的过程:已安装的RVM$\curl-Lhttps://get.rvm.io|bash-sstable检查已知(我假设已批准)安装$rvmlistknown我看到当前的稳定版本可用[ruby-]2.0.0[-p247]输入命令安装$rvminstall2.0.0-p247注意:我也试过这些安装命令$rvminstallruby-2.0.0-p247$rvminstallruby=2.0.0-p247我很快就无处可去了。结果:$rvminstall2.0.0-p247Search

  7. ruby-on-rails - Enumerator.new 如何处理已通过的 block ? - 2

    我在理解Enumerator.new方法的工作原理时遇到了一些困难。假设文档中的示例:fib=Enumerator.newdo|y|a=b=1loopdoy[1,1,2,3,5,8,13,21,34,55]循环中断条件在哪里,它如何知道循环应该迭代多少次(因为它没有任何明确的中断条件并且看起来像无限循环)? 最佳答案 Enumerator使用Fibers在内部。您的示例等效于:require'fiber'fiber=Fiber.newdoa=b=1loopdoFiber.yieldaa,b=b,a+bendend10.times.m

  8. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  9. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  10. 通过 MacPorts 的 RubyGems 是个好主意吗? - 2

    从MB升级到新的MBP后,Apple的迁移助手没有移动我的gem。我这次是通过macports安装ruby​​gems,希望在下次升级时避免这种情况。有什么我应该注意的陷阱吗? 最佳答案 如果你想把你的gems安装在你的主目录中(在传输过程中应该复制过来,作为一个附带的好处,会让你以你自己的身份运行geminstall,而不是root),将gemhome:键设置为您在~/.gemrc中的主目录中的路径. 关于通过MacPorts的RubyGems是个好主意吗?,我们在StackOverf

随机推荐