繁体   English   中英

正确构造Tkinter应用程序

Properly Structuring a Tkinter Application

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

我对面向对象的编程还很陌生,虽然我了解基本概念,但是在组织应用程序时仍然遇到一些麻烦。 我正在构建一个小型Tkinter应用程序,并尝试确保遵循正确的面向对象原则。 关于目前为止我所做的事情,我有几个具体问题(不过,我感谢所有建议!)。

  • 经常使用静态方法是否正确? 我想将逻辑与应用程序的其余部分分开,我意识到我会从构造应用程序的方式编写很多静态方法
  • 为每个小部件分别创建一个类会更好吗? 我创建了Frame类(请参见下面的代码),并将它们与进入特定框架的小部件一起打包。 这导致Frame类很大
  • 我总体上很喜欢MVC架构。 设计GUI应用程序时,通常遵循一个好的架构吗?

我只包含左框架,没有小部件,只是为了说明我的代码结构。 我打算以相同的方式构造顶部和右侧框架。

import tkinter as tk
import sqlite3

# I kept the database in the global scope
con = sqlite3.connect('../database/a_db.db')
cur = con.cursor()

# Controls all of the logic
class Model:
    def __init__(self):
        pass

    @staticmethod
    def get_tasks():
        query = ''' SELECT * FROM tasks '''
        tasks = cur.execute(query).fetchall()
        return tasks

    @staticmethod
    def get_task_details(selected_task_id):
        query = '''SELECT * FROM tasks WHERE task_id=? '''
        db_task = cur.execute(query, (selected_task_id,))
        db_task_details = db_task.fetchall()[0][2]
        return db_task_details

    @staticmethod
    def get_task_status(selected_task_id):
        query = ''' SELECT assigned.emp_id FROM assigned
                    INNER JOIN tasks ON tasks.task_id = assigned.task_id
                    WHERE assigned.task_id=? '''

        db_active_task = cur.execute(query, (selected_task_id,)).fetchall()
        if len(db_active_task) > 0:
            return 'Assigned'
        else:
            return 'Not Assigned'

# Controls what the user of the app sees
class View(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("My App")
        self.middle_of_screen()
        self.resizable(False, False)
        self.iconbitmap(r'../images/a_logo.ico')

        # These three frames fill up the entire space
        self.top_panel = TopFrame() # Another frame with widgets
        self.left_panel = LeftFrame() 
        self.right_panel = RightFrame() # Another frame with widgets

    def display_task_details(self, status, task_details):
        if self.left_panel.list_details.get(0):
            self.left_panel.list_details.delete(0, 'end')

        self.left_panel.list_details.insert(0, "Status: {}".format(status))
        if self.left_panel.list_details:
            self.left_panel.list_details.insert(1, "Task Description: {}".format(task_details))
        else:
            self.left_panel.list_details.insert(1, "Task Description: None")

    def display_tasks(self, tasks):
        # self.left_panel.list_tasks.delete(0, 'end')
        for count, task in enumerate(tasks):
            self.left_panel.list_tasks.insert(count, '{}. {}'.format(task[0], task[1]))

    def middle_of_screen(self):
        window_width = 1350
        window_height = 750
        screen_width = self.winfo_screenwidth()
        screen_height = self.winfo_screenheight()

        x = (screen_width // 2) - (window_width // 2)
        y = (screen_height // 2) - (window_height // 2)

        self.geometry(f'{window_width}x{window_height}+{x}+{y}')

    def start(self):
        self.mainloop()


class LeftFrame:
    def __init__(self):
        self.left_frame = tk.Frame(width=900, height=700, relief='sunken', bg='#e0f0f0',
                                   borderwidth=2)
        self.left_frame.pack(side='left')

        # Widgets that would fill the frame would go here

# Code runs through here only and keeps the Model and View seperated
class Controller:
    def __init__(self):
        self.model = Model()
        self.view = View()
        self.show_tasks()
        self.view.left_panel.list_tasks.bind('<<ListboxSelect>>', self.show_task_details)

        self.view.start()

    def show_task_details(self, event):
        if self.view.left_panel.list_tasks.curselection():
            selected_task = self.view.left_panel.list_tasks.get(self.view.left_panel.list_tasks.curselection())
            selected_task_id = selected_task.split('.')[0]

            db_task_details = self.model.get_task_details(selected_task_id)
            status = self.model.get_task_status(selected_task_id)

            self.view.display_task_details(status, db_task_details)

    def show_tasks(self):
        tasks = self.model.get_tasks()
        self.view.display_tasks(tasks)

if __name__ == '__main__':
    c = Controller()
    c.view.start()



问题暂未有回复.您可以查看右边的相关问题.
1 如何使用线程正确关闭Tkinter应用程序

我正在尝试构建一个显示基本GUI并在后台运行简单Web服务器的简单应用。 目前,我的代码运行良好: 如果使用窗口关闭按钮(OSX中的红色圆圈)关闭GUI窗口,则该应用程序将花费几秒钟并正确退出。 当我尝试使用Cmd + Q关闭应用程序时会出现问题,在这种情况下,应用程序将冻结并且不会 ...

2014-07-25 13:43:25 1 269   python
2 如何组织我的 tkinter 应用程序?

我看到并看到了很多关于 tkinter 的问题,这些问题经常不是问他们代码中的错误,而是问我如何组织我的 GUI。 所以我想有一个专注于这一点的答案,并帮助初学者稍微定位他们。 ...

3 Tkinter应用程序重启

我有一个应用程序编写的类,我想用一个按钮重新启动 我正在使用我在一个线程上找到的代码,但这只是退出程序并且不会重新启动它 我的代码太长了,但它包含一个包含我的应用程序所有函数的类 我想重新启动应用程序,以便所有小部件都被销毁 ...

4 为什么cons的嵌套应用程序会构造不正确的列表?

缺点嵌套的应用程序构造不正确的列表是什么? 我正在学习方案,并对cons感到困惑。 我遇到了这个答案: 方案中要列出的缺点元素与方案中要列出的缺点列表 我知道当cons的第二个参数是列表时,它将第一个参数添加到列表的开头 以下对我来说很有意义: 但是我不明白为什么 ...

5 如何在WinForms应用程序中正确构造类和事件

我正在使用VB.NET开发我的第一个真正的WinForms应用程序,并且该项目的规模比最初预期的要大-因此,我或多或少地不得不处理更好地构造代码的挑战。 我不习惯在WinForms中执行此操作,因此不确定所找到的解决方案是否是正确的方法: 因为我有很多Control元素,尤其是TextBoxes, ...

6 如何构造应用程序的代码

我有一个关于如何构造应用程序代码的一般性问题。 我将QT用于GUI,并且通过单击不同的GUI元素,有一个对应的插槽(事件处理程序)。 所有这些都发生在Main Window类中。 但是现在我想知道如何更好地组织它。 例如,如果一个插槽创建一个对象,而另一个插槽(功能)想要访问该对象,那么 ...

2012-06-26 15:18:13 2 1357   qt
7 我应该如何构造我的应用程序?

我知道这个问题可能含糊不清,我会尽力解释我的问题,并希望能从经验丰​​富的人那里获得很多见识,并希望这不会被解决。 我正在基于Symfony 2的组件和捆绑包编写一个PHP Web应用程序框架,但是我的问题可能与此无关。 该框架旨在向第三方插件开放 ,这些插件将具有自己的配置文件(yam ...

8 我应该如何构造该应用程序?

我正在编写一个iPhone应用程序,要求用户输入手机号码和个人密码,然后按接受按钮,然后他们才能继续进入该应用程序。 我以前有过(每个视图在不同的Xib中) AppDelegate-如果{已注册,则将加载RootView(即主视图)添加到NavigationController中), ...

10 TKinter应用程序崩溃的问题

我有一个正在运行的程序,当计时器运行时出现问题。 每次点击“开始”,应用程序就会崩溃。 有什么想法吗? 请注意,大多数程序尚未完成。 我似乎无法使此计时器正常运行。 ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2022 STACKOOM.COM