【问题标题】:Having TKinter GUI in seperate .py file and binding functions to buttons in the GUI file将 TKinter GUI 放在单独的 .py 文件中,并将函数绑定到 GUI 文件中的按钮
【发布时间】:2020-03-05 19:54:46
【问题描述】:

在用 C# 编程了几年之后,我正试图自学用 python 编码。到目前为止,我发现过渡非常困难,但希望通过一些坚持我最终会理解 python

我的问题:在尝试了 wxglade 和 wxformbuilder 之类的程序之后,我被这些程序为您提供了一个很好的独立 GUI 文件的方式所吸引,这样您就可以将所有功能放在一个单独的主文件中。但是,我想将相同的原理应用于 tkinter GUI,但我无法弄清楚,也找不到有关它的文档。

假设我有两个文件: GUI.py:

from tkinter import * 

class BotGUI:

    def __init__(self, master):
        # ***** Creation of the frame for all items to be on *****
        xWidth=800
        yWidth=500
        margin=100
        outer_frame=Frame(master, width=xWidth, height=yWidth, bg='lightgray')
        outer_frame.pack(ipadx=margin, ipady=margin)
        button1 = Button(outer_frame, text = "Print something", command = printcommand)
        button1.pack()

    #Virtual event handlers
    def printcommand(self, event):
        event.Skip()

然后是一个名为 Main.py 的文件:

from tkinter import *
import GUI

class GUI_Functions(GUI.BotGUI):

    def __init__(self,parent):
        GUI.BotGUI.__init__(self, parent)

    def printcommand(self, event):
        print("The bind was successful!")

if __name__ == '__main__':
    root = Tk()
    GUI_Frame = GUI.BotGUI(root)
    root.mainloop()

以上代码导致错误:

NameError: global name 'printcommand' is not defined

我只是想不通如何让它为 tkinter GUI 工作。希望有人能帮帮我!

(使用 Visual Studio 在 C# 中创建 GUI 要容易得多:( )

【问题讨论】:

  • 您不应该在问题帖子中提供您的问题的答案。如果您的问题得到解决,请选择解决问题的答案,或者使用最底部的文本框提供您自己的答案作为答案。
  • 感谢您的建议 Nae,我是参与堆栈溢出的新手(到目前为止,只是一直在汲取:p)。我已经从我的第一个帖子中删除了答案,并在页面底部找到了答案按钮。

标签: python user-interface tkinter


【解决方案1】:

您收到错误是因为 Python 不知道在哪里可以找到函数 printcommand

首先导入文件Main.py,以便在GUI.py中使用。

import Main.py

现在的问题是printcommand 方法是一个实例方法,这意味着你需要一个对象来调用它。

为了做到这一点。

  • 创建GUIFunctions类的实例并使用对象引用方法

guifuncs = Main.GUIFunctions(master)

command = guifuncs.printcommand

注意:您必须使用上面使用的导入语法为 Main.py 的引用添加 Main 前缀。

我希望这对您有所帮助,如果您有任何其他问题,请随时在下面发表评论!

【讨论】:

    【解决方案2】:

    Python 找不到名为“printcommand”的全局函数,而且确实没有全局函数“printcommand”。您必须通过将self. 添加到回调定义中来告诉button1 回调命令是一个本地函数。它应该如下所示:
    command = self.printcommand

    这将导致另一个问题,即按钮回调没有将事件传回。我通过删除事件参数解决了这个问题,使得 GUI.py 中的 printcommand 函数看起来像这样:

    def printcommand(self):
        pass
    

    如果您确实需要将值传递给回调函数this page at Effbot 是一个不错的起点。

    【讨论】:

      【解决方案3】:

      正如 Micheal 所回答的,我的 GUI.py 文件中缺少“import Main”,在我运行该文件后,我在代码中发现了一些其他小错误,因此请在下面找到我用来运行它的代码:

      GUI.py 文件:

      from tkinter import * 
      import Main
      
      
      class BotGUI:
      
          def __init__(self, master):
              # ***** Import the guifunctions from the Main.py file
              guifuncs = Main.GUI_Functions(master)
      
              # ***** Creation of the frame for all items to be on *****
              xWidth=800
              yWidth=500
              margin=100
              outer_frame=Frame(master, width=xWidth, height=yWidth, bg='lightgray')
              outer_frame.pack(ipadx=margin, ipady=margin)
              button1 = Button(outer_frame, text = "Print something", command = guifuncs.printcommand)
              button1.pack()
      

      和 Main.py 文件:

      from tkinter import * 
      import GUI
      
      
      class GUI_Functions():
      
          def __init__(self,parent):
              pass
      
          def printcommand(self):
              print("The bind was successful!")
      
      if __name__ == '__main__':
          root = Tk()
          GUI_Frame = GUI.BotGUI(root)
          root.mainloop()
      

      感谢 Micheal 指出问题!还要感谢 Alex 提供有用的 effbot.org 链接!

      【讨论】:

        【解决方案4】:

        希望这会有所帮助。

        创建一个名为“guiFactory.py”的文件

        def createButton(self, Button, text, command, highlightbackground, compound, x, y):
            self.nav_button = Button(self, text =text, command=command, highlightbackground=highlightbackground, compound=compound) 
            self.nav_button.place(x = x, y = y)
        

        在您的主应用程序文件中。

        import tkinter as tk
        from tkinter import StringVar, IntVar, messagebox, OptionMenu, Button, Label, filedialog as fd 
        import guiFactory
        
        class MainApplication(tk.Frame):
            def __init__(self, parent, *args, **kwargs):
                tk.Frame.__init__(self, parent, *args, **kwargs)
                self.parent = parent
        
                # Canvas Size
                parent.geometry("300x350")
                self.configure(bg="#3E4149")
                parent.title("Test Application") 
        
                # Submit Button
                def convertFilesHandler():
                    print("Do Something")
        
                # buttons
                convertBtn = guiFactory.createButton(self, Button, "Convert", convertFilesHandler, "#3E4149", "center", 200, 250)
        
        if __name__ == "__main__":
            root = tk.Tk()
            MainApplication(root).pack(side="top", fill="both", expand=True)
            root.mainloop()
        

        【讨论】:

          猜你喜欢
          • 2018-09-13
          • 1970-01-01
          • 1970-01-01
          • 2020-12-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-04-29
          • 1970-01-01
          相关资源
          最近更新 更多