close

想要設計一個物件分類的管理,如下:

MVC架構設計順序:  view -> model -> controller

ObjectNameView:

1. 首先,定義5個signals,每種signal有不同輸入引數,依照實際需求決定輸入引數的資料型態

分別如下

 

由Qt desinger預先設計好介面main_view,

並將一部分主介面中的元件依照需求傳入

好處是: ObjectNameView類別相當於一個中間層

如此可以解偶'事件'與'人機介面', 未來使用者可以依照需求傳入不同元件;

換句話說,上層(人機介面)變更時 但底層(事件)運作邏輯不受影響(不需要改寫)

 

2. 連接(connect)人機介面互動的通訊(signal-slot)

例如

add按鈕clicked signal,連接 _handle_add slot 

modify按鈕clicked signal,連接 _handle_modify slot

delete按鈕clicked signal,連接 _handle_delete slot

object_name_list_widget清單itemClicked signal,連接 _handle_selection slot

save按鈕clicked signal,連接 匿名函式 slot

 _handle_add:

1. 獲取view上輸入的物件名稱(name),並將name發送(emit)

2. emit相當於把資料(name)丟出,讓後續的controller或model使用

 

 """Emit signal to add a new object name."""
    def _handle_add(self):    
        name = self.object_name_lineEdt.text().strip()
        if name:
            # 獲取view上輸入的物件名稱
            self.add_requested.emit(name)
        else:
            QMessageBox.warning(self, "物件名稱錯誤", "物件名稱不可以為空值!")

 

_handle_modify:

1. 獲取哪一筆需修改(current_row)和對應新的物件名稱(new_name),並將兩者資料發送(emit)

2. emit相當於把資料(current_row, new_name)丟出,讓後續的controller或model使用

 

"""Emit signal to modify the selected object name."""
    def _handle_modify(self):      
        current_row = self.object_name_list_widget.currentRow()
        if current_row != -1:
            new_name = self.object_name_lineEdt.text().strip()
            if new_name:
                # 通知哪一筆需修改和對應新的物件名稱
                self.modify_requested.emit(current_row, new_name)
            else:
                QMessageBox.warning(self, "物件名稱錯誤", "物件名稱不可以為空值!")

 

_handle_delete:

1. 獲取哪一筆需刪除(current_row),並將current_row發送(emit)

2. emit相當於把資料(current_row)丟出,讓後續的controller或model使用

 

"""Emit signal to delete the selected object name."""
    def _handle_delete(self):    
        current_row = self.object_name_list_widget.currentRow()
        if current_row != -1:
            self.delete_requested.emit(current_row)
        else:
            QMessageBox.warning(self, "刪除物件錯誤", "請選擇欲刪除的物件名稱!")

 

_handle_selection:

1. 獲取哪一筆資料正被選取(current_row),並將current_row發送(emit)

2. emit相當於把資料(current_row)丟出,讓後續的controller或model使用

    """Emit signal to notify the selected object's index"""
    def _handle_selection(self):
        current_row = self.object_name_list_widget.currentRow()
        # 通知被選取的物件索引
        self.item_selected.emit(current_row)

 Public member function:update_object_list和set_line_edit_text

    """Update the list of object_name_list_widget"""
    def update_object_list(self, object_names):
        # 更新view本身,所以不需要通知外部(無emit訊號)
        self.object_name_list_widget.clear()
        self.object_name_list_widget.addItems(object_names)
   
    """Set the text in the input line edit."""
    def set_line_edit_text(self, text):
        # 更新view本身,所以不需要通知外部(無emit訊號)
        self.object_name_lineEdt.setText(text)

 ObjectNameModel:

初始化階段

class ObjectNameModel:
    """object_names儲存所有物件名稱"""
    def __init__(self, file_name ="classname.txt"):
        self.file_name = file_name
        self.object_names = []

 

add_object_name輸入引數的資料格式,和view中add_reqested(str)一樣

 """Add an object name to the list."""
    def add_object_name(self, name):      
        self.object_names.append(name)

modify_object_name輸入引數的資料格式,和view中modify_reqested(int, str)一樣

   """Modify an object name at a specific index."""
    def modify_object_name(self, index, new_name):        
        if 0<= index < len(self.object_names):
            self.object_names[index] = new_name

delete_object_name輸入引數的資料格式,和view中delete_reqested(int)一樣

    """Delete an object name at a specific index."""
    def delete_object_name(self, index):        
        if 0<= index <len(self.object_names):
            self.object_names.pop(index)

save_object_name輸入引數的資料格式,和view中save_reqested()一樣

"""Save object names to the file."""
    def save_object_names(self):      
        try:
            with open(self.file_name, "w") as file:
                file.write("\n".join(self.object_names))
        except:
            print("save_object_names failed.")

 load_object_name: 從檔案讀取物件名稱

 """Load object names from the file."""
    def load_object_names(self):
        try:
            with open(self.file_name, "r") as file:
                self.object_names = file.read().splitlines()
        except FileNotFoundError:
            self.object_names = []

 

ObjectNameController:

初始化階段

1. 傳入model和view

2. 連結view signals至controller's slots

    所以slots輸入引數必須符合view signals的資料格式

3. view 人機介面動作通知view本身的slot,

    接著該slot會將signal emit,

    由於步驟2有預先連結,

    因此controller slot會接收到view signal並處理

class ObjectNameController:
    def __init__(self, model:ObjectNameModel, view:ObjectNameView):
        self.model = model
        self.view = view

        # Connect "view signals" to "controller slots"
        # 1. 相當於在controller的slots中去呼叫view和model的API
        # 2. "controller slots"都是公開成員函數(API),由main_controller去呼叫之
        self.view.add_requested.connect(self.add_object_name)
        self.view.modify_requested.connect(self.modify_object_name)
        self.view.delete_requested.connect(self.delete_object_name)
        self.view.save_requested.connect(self.save_object_names)
        self.view.item_selected.connect(self.display_selected_object_name)
        # Load initial data
        self.model.load_object_names()
        self.view.update_object_list(self.model.object_names)

 4. controller收到view signal通知,進行model/view整合

 4.1 以add_object_name slot為例,該輸入引數符合view add_requested訊號格式 Signal(str)

 4.2 model呼叫add_object_name,

      相當於將name加入 model.object_names

 4.3 接著,view呼叫update_object_list更新清單,

       其輸入來源model.object_names

def add_object_name(self, name):
        self.model.add_object_name(name)
        self.view.update_object_list(self.model.object_names)
        self.view.object_name_lineEdt.clear()

5. controller收到view signal通知,進行model/view整合

 5.1 以modify_object_name slot為例,該輸入引數符合view modify_requested訊號格式 Signal(int, str)

 5.2 model呼叫modify_object_name,

      相當於將index和new_name傳入model

      並修改model.object_names對應索引(index),

      該筆資料寫入新名稱(new_name)

 5.3 接著,view呼叫update_object_list更新清單,

       其輸入來源model.object_names

    def modify_object_name(self, index, new_name):
        self.model.modify_object_name(index, new_name)
        self.view.update_object_list(self.model.object_names)

 其他controller的slots如下,就不在贅述

 def delete_object_name(self, index):
        self.model.delete_object_name(index)
        self.view.update_object_list(self.model.object_names)

    def save_object_names(self):
        self.model.save_object_names()
        QMessageBox.information(self.view, "Success", "Object names saved successfully!")

    def display_selected_object_name(self, index):
        if 0<= index < len(self.model.object_names):
            self.view.set_line_edit_text(self.model.object_names[index])

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 me1237guy 的頭像
    me1237guy

    天天向上

    me1237guy 發表在 痞客邦 留言(0) 人氣()