我对面向对象的编程还很陌生,虽然我了解基本概念,但是在组织应用程序时仍然遇到一些麻烦。 我正在构建一个小型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()



  ask by ShockDoctor translate from so

本文未有回复,本站智能推荐:

2回复

澄清构造tkinter页面的最佳方法

这是一个快速的问题,但我似乎找不到我理解的答案。 我正在用tkinter构建一个“简单”的3页“应用”,并且我已经将每个页面作为一个单独的类构建在一个单独的.py文档中。 我认为,这是确保没有一个.py文档发疯的最佳方法,因为要使每个页面成为大文件__init__内的一个框架。 我是t
2回复

frame.__init__有什么作用?-tkinter

我正在看 Sentdex 的 Tkinter 教程,并且出现了一些相关问题: 我刚接触的基本类问题:为什么Frame跟在 Window 类的声明之后(对于基本类问题很抱歉)? self.pack如何在不指定打包内容的情况下工作? frame.__init__对这段代码有什么贡献? 代
2回复

为什么不能使用tkinter网格方法放置此类?

我有一个现有的Python 3程序,无需任何面向对象的技术就可以快速编写代码(这是我的第一个Python程序)。 现在该清理一下了,在使tkinter在我的课堂上工作时遇到了问题。 这是一个简化的示例。 它只是试图将ttk.Entry小部件放置到继承自ttk.Frame的类中: 它给
1回复

Python3和Tkinter:通过OOP在调查表中显示问题和不同答案集

我正在使用Python 3和Tkinter创建一个带有问题和各种可能答案的调查表。 以下代码行未显示我的调查问题及其答案集。 相反,它们会产生错误< main .QuestionSet对象,位于0x000000B3CB464400>:
1回复

如何用可调用的类对象回调处理程序替换lambda回调处理程序?

我的以下问题与编程 Python 的示例 8-10 相关,第 4 版由 Mark Lutz编写。 该示例是关于创建一个简单按钮栏,用于启动对话框演示并在stdout 中返回这些对话框调用的值。 对话框表如下所示: 下面的代码创建按钮栏并使它们起作用。 我的问题与这部分有关: Quitter只是退出
1回复

在python3.x中从外部文件应用框架?

有什么方法可以将框架从外部模块应用到根窗口。 我有 2 个文件:在a.py中有一行self.root = root()并且我在一个类中有一个函数,它导入b.py和在b.py我有一个类并实例化了一个 Frame 以在 root 中显示窗口self.frame = Frame(root) 。 没有错误,
1回复

tkinter应用程序中的super()

我无法理解此错误。 在下面的代码中,当我使用tk.Frame一切都按预期工作。 但是,如果我使用super() ,则会抛出AttributeError (“ 应用程序对象没有属性tk ”)。 class Application(tk.Frame): def __init__(self,
1回复

如何将类应用于我的Tkinter应用程序?

我正在尝试创建一个应用程序,其中在主框架中还有两个其他框架(并排)。 左侧框架由始终可见的按钮组成。 这些按钮将更改右侧框架的内容。 通过将每个按钮分配给一个定义,该定义重新创建左框架中的按钮,清除右框架上的内容并重写进入右框架的内容,我已经成功地做到了这一点。 这有效,但我很想了解更多关于不同/更