首页 > 解决方案 > Tkinter 主属性及其可能的用途

问题描述

很抱歉这篇长文,但这个话题值得一个完整的解释。

在研究 Tkinter 的主属性时,我想到了使用它在各种 Toplevel 中传递一系列方法和属性,这些方法和属性分组在我的一个类中,我称之为“引擎”,对应用程序的任何部分都很有用。

所以基本思想是创建一个类来从 Tkinter 应用程序外部管理各种小部件以及对数据库进行的操作。

问题是如何从所有应用程序点调用我的类的各种方法、属性,在应用程序“ init ”上初始化我的类。

基本上如何在应用程序的所有主循环期间保持对此的引用。

所以我想将我的类与 Tkinter 提供的master属性相关联,并且使用一个简单的self.master将整个应用程序可见,在我的例子中,访问我的类方法变成了 self.master.engine

因此,例如调用位于从 Engine 类继承的 DBMS 类中的 on_read 函数,我们可以简单地做

self.master.engine.on_read()

然而,这是链接到下面显示的简单应用程序代码的各个按钮的功能的含义,“引擎”类正在初始化

self.engine = Engine()

调用 inint of

App(tk.TK)

Connection 返回到读取 self.master.engine.con 的数据库的连接

并在 0x7f97668e11f0> 返回 sqlite3.Connection 对象

Engine 显示类 Engine 的方法

孩子打开一个顶层

Sqlite 读取人在 DBMS 类中创建的表中的数据

话虽如此,听起来如何?

用硕士带走你的“工具箱”有危险吗?

#!/usr/bin/python3
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import sqlite3 as lite


class DBMS:
    def __init__(self):
        super().__init__()

        self.on_connect()
        self.set_data()
        
    def __str__(self):
        return "class: %s" % (self.__class__.__name__, )

    def on_connect(self,):
        self.con = lite.connect(':memory:')

    def set_data(self):

        cur = self.con.cursor()
        cur.execute("CREATE TABLE people (name_last, age)")

        who = "Yeltsin"
        age = 72
        cur.execute("insert into people values (?, ?)", (who, age))

        who = "Guido"
        age = 64
        cur.execute("insert into people values (?, ?)", (who, age))
        cur.close()

    def on_read(self):
        
        cur = self.con.cursor()
        sql = "SELECT * FROM people"
        cur.execute(sql)
        rs = cur.fetchall()
        cur.close()
        return rs
        

class Engine(DBMS,):
    def __init__(self):
        super().__init__()
    def __str__(self):
        return "class: %s" % (self.__class__.__name__, )
    def get_frame(self, parent, padding=None):
        return ttk.Frame(parent, padding=padding)
    def get_button(self, parent, text, underline=0, ):
        return ttk.Button(parent, text=text, underline=underline,)
    def get_label(self, parent, text=None, padding=None):
        print(parent)
        return ttk.Label(parent, text=text, padding=padding,relief=tk.RIDGE,)
    
class Child(tk.Toplevel):
    def __init__(self, parent,):
        super().__init__(name="child")

        self.parent = parent
        self.init_ui()
        
    def init_ui(self):

        msg = ("I'm the {0} frame of {1}".format(self.winfo_name().capitalize(),
                                                 self.master.title()))

        self.title(msg)

        w = self.master.engine.get_frame(self, 8)

        btn = self.master.engine.get_button(w, "Sqlite")
        btn.bind("<Button-1>", self.on_read)
        btn.pack()

        btn = self.master.engine.get_button(w, "Close")
        btn.bind("<Button-1>", self.on_cancel)
        btn.pack()

        w.pack(fill=tk.BOTH, expand=0)

    def on_read(self, evt=None):

        print(self.master.engine.on_read())
        
    def on_cancel(self, evt=None):
        self.destroy()
    
            
class Main(ttk.Frame):

    def __init__(self, parent,):
        super().__init__(name="main")

        #parent.get_class_dir(self.master)
        #parent.get_class_dir(self.master.engine)
        self.parent = parent
        self.init_ui()

    def init_ui(self):

        self.pack(fill=tk.BOTH, expand=1)

        w = self.master.engine.get_frame(self, 8)
        
        btn = self.master.engine.get_button(w, "Connection")
        btn.bind("<Button-1>", self.on_get_con)
        btn.pack()

        btn = self.master.engine.get_button(w, "Engine")
        btn.bind("<Button-1>", self.on_get_engine_attributes)
        btn.pack()

        btn = self.master.engine.get_button(w, "Child")
        btn.bind("<Button-1>", self.on_open_child)
        btn.pack()

        btn = self.master.engine.get_button(w, "Close")
        btn.bind("<Button-1>", self.master.on_exit)
        btn.pack()
        
        w.pack(fill=tk.BOTH, expand=0)

    def on_get_con(self, evt=None):

        print(self.master.engine.con)

        msg = self.master.engine.con

    def on_get_engine_attributes(self, evt=None):

        print(self.master.engine)

        attributes = [x for x in dir(self.master.engine) if not x.startswith('__')]

        for attribute in attributes:
            print(attribute)

    def on_open_child(self, evt=None):
        Child(self,)
                
class App(tk.Tk):
    def __init__(self):
        super().__init__()
        
        self.protocol("WM_DELETE_WINDOW", self.on_exit)
        self.title("Simple App")

        #here we add Engine class to master...
        self.engine = Engine()

        Main(self,)

        #self.get_class_dir(self)
        #self.get_class_dir(self.master)

    def get_class_dir(self, obj):

        attributes = [x for x in dir(obj) if not x.startswith('_')]

        for attribute in attributes:

            if attribute == "engine":
                print("attribute {0}  type {1}".format(attribute, type(attribute)))
               
                    
            elif attribute == "master":
                print("attribute {0}  type {1}".format(attribute, type(attribute)))

                    
    def on_exit(self, evt=None):
        if messagebox.askokcancel(self.title(), "Do you want to quit?", parent=self):
            self.destroy()               
    
if __name__ == '__main__':
    app = App()
    app.mainloop()

标签: pythontkinter

解决方案


推荐阅读