.tutorials/addressbook/part4/addressbook.h
.tutorials/addressbook/part4/main.cpp
.tutorials/addressbook/part4/part4.pro
在這一章,我們著眼於修改儲存在 Address Book 程式中聯絡人內容的方法。
我們現在擁有一個不只能以有系統的方式存取資料,還能夠允許導覽的 Address Book。而包含編輯和移除函式--使得聯絡人的詳細資料可以在需要時被改變--將會是方便的。然而,這需要在列舉(enum)的形式下做一點改良。在先前的章節中,我們有兩種模式(mode):AddingMode 與 NavigationMode--但是它們並不是作為列舉而被定義的。相反的,我們手動讓對應的按鈕生效或失效,結果就是多行重複的程式碼。
在這一章,我們定義了包含三種值的 Mode 列舉:
- NavigationMode,
- AddingMode, 與
- EditingMode.
Defining the AddressBook Class
addressbook.h 被更新成包含了 Mode 列舉:
enum Mode { NavigationMode, AddingMode, EditingMode };
我們也加入了兩個新的 slot--editContact() 與 removeContact()--到我們當前的公開 slot 列表。
void editContact(); void removeContact();
為了在模式間做轉換,我們引入了 updateInterface() 函式來管理所有 QPushButton 物件的生效與失效。為了先前提到的編輯和刪除函式,我們也加入了兩個新按鈕:editButton 與 removeButton。
void updateInterface(Mode mode); ... QPushButton *editButton; QPushButton *removeButton; ... Mode currentMode;
最後,我們宣告了 currentMode 以追蹤當前的列舉模式。
Implementing the AddressBook Class
我們現在必須要實現 Address Book 程式的模式改變功能。editButton 與 removeButton 被實體化,並在預設情況下使其失效,因為 Address Book 啟動時並無聯絡人在記憶體中。
editButton = new QPushButton(tr("&Edit")); editButton->setEnabled(false); removeButton = new QPushButton(tr("&Remove")); removeButton->setEnabled(false);
然後,這些按鈕被連接到它們各自的 slot:editContact() 與 removeContact()。且我們將這些按鈕加入到 buttonLayout1e 中。
connect(editButton, SIGNAL(clicked()), this, SLOT(editContact())); connect(removeButton, SIGNAL(clicked()), this, SLOT(removeContact())); ... buttonLayout1->addWidget(editButton); buttonLayout1->addWidget(removeButton);
在模式轉換成 EditingMode 之前,editContact() 函式將聯絡人的舊資料儲存在 oldName 與 oldAddress 中。在這個模式,submitButton 與 cancelButton 都是有效的。因此,使用者可以改變聯絡人的詳細資料並點擊任一按鈕。
void AddressBook::editContact() { oldName = nameLine->text(); oldAddress = addressText->toPlainText(); updateInterface(EditingMode); }
submitContact() 函式被一個 if-else 敘訴(statement)分割成兩個部分。我們檢查 currentMode 以確認它是否在 AddingMode 下。假如是,我們開始我們的加入動作。
void AddressBook::submitContact() { ... if (currentMode == AddingMode) { if (!contacts.contains(name)) { contacts.insert(name, address); QMessageBox::information(this, tr("Add Successful"), tr("\"%1\" has been added to your address book.").arg(name)); } else { QMessageBox::information(this, tr("Add Unsuccessful"), tr("Sorry, \"%1\" is already in your address book.").arg(name)); return; }
否則,我們檢查 currentMode 以確認它是否在 EditingMode 下。假如是,我們比較 oldName 與 name。假如名字被改變了,我們從 contacts 移除舊的聯絡人,並插入更新過的新聯絡人。
} else if (currentMode == EditingMode) { if (oldName != name) { if (!contacts.contains(name)) { QMessageBox::information(this, tr("Edit Successful"), tr("\"%1\" has been edited in your address book.").arg(oldName)); contacts.remove(oldName); contacts.insert(name, address); } else { QMessageBox::information(this, tr("Edit Unsuccessful"), tr("Sorry, \"%1\" is already in your address book.").arg(name)); return; } } else if (oldAddress != address) { QMessageBox::information(this, tr("Edit Successful"), tr("\"%1\" has been edited in your address book.").arg(name)); contacts[name] = address; } } updateInterface(NavigationMode); }
只有在住址被改變(換言之,oldAddress 與 address 不相同)時,我們才更新聯絡人的住址。最後,我們將 currentMode 設為 NavigationMode。這是作為重新啟動所有失效按鈕的一個重要步驟。
為了從 Address Book 中移除一個聯絡人,我們實現了 removeContact() 函式。這個函式確認聯絡人是否在 contacts 中。
void AddressBook::removeContact() { QString name = nameLine->text(); QString address = addressText->toPlainText(); if (contacts.contains(name)) { int button = QMessageBox::question(this, tr("Confirm Remove"), tr("Are you sure you want to remove \"%1\"?").arg(name), QMessageBox::Yes | QMessageBox::No); if (button == QMessageBox::Yes) { previous(); contacts.remove(name); QMessageBox::information(this, tr("Remove Successful"), tr("\"%1\" has been removed from your address book.").arg(name)); } } updateInterface(NavigationMode); }
假如存在,我們顯示一個 QMessageBox,以讓使用者確認(confirm)刪除動作。一旦使用者確認了,我們呼叫 previous() 以確保使用者介面顯示了另一個聯絡人,且利用 QMap 的 remove() 函式來移除聯絡人。基於禮貌,我們顯示了一個 QMessageBox 以告知使用者。這個函式中所使用的訊息視窗顯示如下:
Updating the User Interface
我們先前提到了 updateInterface() 函式作為使按鈕根據當前模式生效與失效的工具。函式根據傳入的 mode 引數更新當前模式,在確認它的值之前賦值(assign)給 currentMode。
這時,每個按鈕都根據當前模式生效或失效。其於 AddingMode 與 EditingMode 的程式碼顯示如下:
void AddressBook::updateInterface(Mode mode) { currentMode = mode; switch (currentMode) { case AddingMode: case EditingMode: nameLine->setReadOnly(false); nameLine->setFocus(Qt::OtherFocusReason); addressText->setReadOnly(false); addButton->setEnabled(false); editButton->setEnabled(false); removeButton->setEnabled(false); nextButton->setEnabled(false); previousButton->setEnabled(false); submitButton->show(); cancelButton->show(); break;
然而,對於 NavigationMode,我們在 QPushButton::setEnabled() 的參數中包含條件。這是為了確保在 Address Book 中至少有一個聯絡人時,能使 editButton 與 removeButton 按紐生效;只有在 Address Book 中有多於一個聯絡人時,能使 nextButton 與 previousButton 按紐生效。
case NavigationMode: if (contacts.isEmpty()) { nameLine->clear(); addressText->clear(); } nameLine->setReadOnly(true); addressText->setReadOnly(true); addButton->setEnabled(true); int number = contacts.size(); editButton->setEnabled(number >= 1); removeButton->setEnabled(number >= 1); nextButton->setEnabled(number > 1); previousButton->setEnabled(number >1 ); submitButton->hide(); cancelButton->hide(); break; } }
藉由執行設置模式的任務以及在同一函式中更新使用者介面,我們避免了使用者介面的程式內部狀態發生「不同步(out of sync)」的可能性。
來源:Address Book 4 - Editing and Removing Addresses
版本:4.4.3
0 回覆:
張貼留言