我对面向对象的编程还很陌生,虽然我了解基本概念,但是在组织应用程序时仍然遇到一些麻烦。我正在构建一个小型Tkinter应用程序,并尝试确保遵循正确的面向对象原则。关于我到目前为止所做的事情,我有几个具体问题(不过,我很感谢所有建议!)。
我只包含左框架,没有小部件,只是为了说明我的代码结构。我打算以相同的方式构造顶部和右侧框架。
代码
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()