【问题标题】:How to identify the name of sqlite database table which ttk.Treeview loads data from?如何识别 ttk.Treeview 从中加载数据的 sqlite 数据库表的名称?
【发布时间】:2021-04-13 04:25:03
【问题描述】:

我有一个用 python3 编写的tkinter 应用程序。它有一个主要的tk.Frame。使用for 循环我在那里构建了两个ttk.LabelFrames,然后每个帧得到它的ttk.Treeview。这些树视图中的每一个都从不同的表(名为 aliens1aliens2)加载其数据:

class Application:
    def __init__(self, master):
        self.master = master
        
        self.database = Database(self.master, self)
        self.turns_frame = TurnsFrame(self.master, self)

class TurnsFrame:
    def __init__(self, master, app):
        self.master = master
        self.app = app
        self.frame = tk.Frame(self.master, bd=2)
        
        # Create LabelFrames and their Treeviews
        for i in range(3):
            ap_frame = tk.LabelFrame(self.frame, text="Alien Player {}".format(str(i+1)))
            ap_frame.grid(row=0, column=i)

            tv = tk.ttk.Treeview(ap_frame,
                                 columns=tuple(range(1, 12)),
                                 show="headings",
                                 height=30)
            tv.pack()

            ... creating columns ...

            # Create rows
            with self.app.database.db:
                self.app.database.cursor.execute("SELECT turn, econ_rolls, econ_rolls_extra, cp_fleet, "
                                             "cp_tech, cp_def, fleet_launch, roll_econ, roll_fleet, "
                                             "roll_tech, roll_def FROM aliens{}".format(str(i+1)))
                rows = self.app.database.cursor.fetchall()

                for r in rows:
                    tv.insert("", "end", values=r)

            # Bind row double-click
            tv.bind("<Double-1>", self.get_turn_number)

    def get_turn_number(self, event):
        item_id = event.widget.focus()
        item = event.widget.item(item_id)
        values = item["values"]
        turn_id = values[0]

        print("Turn: ", turn_id)
        return turn_id

class Database:
    def __init__(self, master, app):
        self.master = master
        self.app = app
        self.folder = os.path.dirname(os.path.abspath(__file__))

        self.db = self.create_connection(self.folder)
        self.cursor = self.db.cursor()

    def create_connection(self, f):
        db = None
        try:
            db = sqlite3.connect(os.path.join(f, "aliens.db"))
        except sqlite3.Error as e:
            print(e)

        return db

    def initialize_tables(self, nr):
    # SOME OTHER FRAME CALLS THIS FUNCTION AND GIVES THE VARIABLE 'nr'
        with self.db:
            for i in range(1, nr+1):
                # print("Creating table aliens{}".format(str(i)))
                self.cursor.execute("CREATE TABLE aliens{}(".format(i) +
                                    "turn INTEGER PRIMARY KEY,"
                                    "econ_rolls INTEGER,"
                                    "econ_rolls_extra INTEGER,"
                                    "cp_fleet INTEGER,"
                                    "cp_tech INTEGER,"
                                    "cp_def INTEGER,"
                                    "fleet_launch STRING,"
                                    "roll_econ STRING,"
                                    "roll_fleet STRING,"
                                    "roll_tech STRING,"
                                    "roll_def STRING)")

def main():
    root = tk.Tk()
    main_app = Application(root)
    root.mainloop()

if __name__ == "__main__":
    main()

它看起来很好并且工作正常,看起来像这样 application.

现在我可以双击任何一行,它会执行self.get_turn_number。 伟大的。 为了进一步的工作,我需要获取它从中加载其行的数据库表名称(取决于我双击哪个树视图 - 第一个 Alien player 1 或第二个 Alien player 2)。外星人玩家 1 从表 alien1 加载数据,玩家 2 从 aliens2 加载数据。

我搜索了文档,但在 ttk.Treeview 中没有发现任何相关内容。似乎以前没有人遇到过这个问题。有没有办法做到这一点?

【问题讨论】:

  • 你能告诉我们你是如何实例化你的类吗
  • 已添加代码。主应用程序是一个类,turns_frame 在其 init 中实例化。 (我对 Python 很陌生,所以结构可能不是最 Python 的:/)
  • 还有哪个框架?两个 LabelFrame(Alien Player1 和 Alien Player 2)都是在“for”循环中创建的 - init 类 TurnsFrame。你是这个意思吗?
  • 对不起,我指的是另一个class。我想看看你如何传递数据库等等。
  • 您可以做的一件事是。将数据库名称存储在变量中?并将该变量作为__init__ 中的app 参数传递,或者创建一个新的参数名称db_name 并传递路径。

标签: python-3.x sqlite for-loop treeview ttk


【解决方案1】:

好吧,我刚刚注意到您正在使用的 for 循环。您可以做的是将数字传递给函数,然后将其运行,例如:

.... # Same code
    tv.bind("<Double-1>", lambda e,num=i: self.calculate_econ_phase(num)

def calculate_econ_phase(self,num):
    print(f'Alien{num}')

作为答案发布,因为对于 cmets 来说太长了。

【讨论】:

  • 太棒了!使用e, num=i+1,它会真正打印出玩家编号。那么现在,如何整合event才能得到轮号呢?这个 lambda 仍然超出我的知识范围......
  • 什么意思?为什么你需要在这里活动?你只需要双击一个小部件对吗?
  • 查看 def get_turn_number(self, event) - 我需要 event 来获取 dblclicked 行值(例如,问题代码中的轮数)
  • 我明白了! tv.bind("&lt;Double-1&gt;", lambda e,num=i+1: self.get_turn_number(e, num)def get_turn_number(self, event, num): ... 有效!它打印正确的玩家号码和右转号码。感谢您的建议和时间!
  • 是的,我更改了函数名称只是为了显示我是如何获得轮号的。现在我明白了它是如何工作的,以及我应该把这些变量放在什么地方和什么地方。谢谢!
猜你喜欢
  • 2013-08-07
  • 2018-06-21
  • 1970-01-01
  • 1970-01-01
  • 2012-01-19
  • 1970-01-01
  • 2016-04-13
  • 2013-09-09
  • 1970-01-01
相关资源
最近更新 更多