Python 3.x 正确构造Tkinter应用程序

Python 3.x 正确构造Tkinter应用程序,python-3.x,class,oop,model-view-controller,tkinter,Python 3.x,Class,Oop,Model View Controller,Tkinter,我对面向对象编程相当陌生,虽然我理解基本概念,但在组织应用程序时仍有一些困难。我正在构建一个小的Tkinter应用程序,并试图确保遵循正确的面向对象原则。关于到目前为止我所做的工作,我有几个具体的问题。不过,我感谢所有的建议 经常使用静态方法正确吗?我想将逻辑与应用程序的其余部分分开,我意识到我将以构建应用程序的方式编写许多静态方法 是否最好分别为每个小部件创建一个类?我创建了我的框架类(见下面的代码),并将它们和进入特定框架的小部件打包在一起。这导致框架类相当大 总体而言,我非常喜欢MVC架构

我对面向对象编程相当陌生,虽然我理解基本概念,但在组织应用程序时仍有一些困难。我正在构建一个小的Tkinter应用程序,并试图确保遵循正确的面向对象原则。关于到目前为止我所做的工作,我有几个具体的问题。不过,我感谢所有的建议

经常使用静态方法正确吗?我想将逻辑与应用程序的其余部分分开,我意识到我将以构建应用程序的方式编写许多静态方法 是否最好分别为每个小部件创建一个类?我创建了我的框架类(见下面的代码),并将它们和进入特定框架的小部件打包在一起。这导致框架类相当大 总体而言,我非常喜欢MVC架构。在设计GUI应用程序时,它通常是一个好的体系结构吗? 为了说明我的代码结构,我只包括了左框,没有小部件。我计划以同样的方式构造顶部和右侧框架

代码


这可能更适合于,我当然建议您将sqlite.connect放在模型类的init中,不要在这个类中使用静态方法。好的,谢谢!我会把我的问题放在那里。对不起,我不确定,因为我也有一些具体的问题
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()