2014-07-07 28 views
10

Tôi có một số hành động (ví dụ: sao chép, dán, hoàn tác, làm lại, hiển thị cửa sổ có thể gắn đế XYZ, thu phóng, v.v.) Tôi không muốn sao chép ở nhiều vị trí nhưng được chia sẻ bởi các phần khác nhau của GUI như menu chính, thanh công cụ và các menu chuột phải.Cách tốt nhất để chia sẻ hành động giữa các lớp GUI riêng biệt (menu, thanh công cụ, vv)

Cách tốt nhất để chia sẻ chúng là gì? Tôi đang sử dụng Qt 5.3 với C++, nhưng điều này chủ yếu là độc lập với bất kỳ khuôn khổ GUI hoặc ngôn ngữ cụ thể nào.

Một số khả năng:

  1. chỉ định một vị trí trung tâm, nói rằng cửa sổ chính, để tạo ra tất cả chúng với văn bản của họ, biểu tượng, và gọi lại. Sau đó:

    1. Chuyển các hành động đến hàm tạo khi tạo thành phần phụ của GUI. Điều này có thể làm cho danh sách các hàm tạo constructor khá dài.

    2. Bộ định tuyến cuộc gọi trên các thành phần phụ của GUI sau khi cấu phần con được xây dựng và chuyển tất cả các hành động cần thiết. Điều này làm cho các nhà xây dựng ngắn hơn nhưng không có nhiều đẹp hơn cuối cùng.

    3. Cung cấp getters từ cửa sổ chính và yêu cầu các thành phần con nhận được hành động mà họ muốn. Các thành phần con thường có một con trỏ tới cửa sổ chính. Điều này làm cho nó để cửa sổ chính là không biết gì về những người quan tâm về hành động, nhưng nó cũng cho thấy một loạt các thành viên công cộng (trừ khi tôi sử dụng Attorney-Client idiom hoặc tương tự).

    4. Thêm chúng vào một kho lưu trữ toàn cầu, riêng biệt, nơi cửa sổ chính thêm chúng và người dùng tìm kiếm chúng theo tên hoặc khóa hoặc thứ gì đó, nếu cần. Điều này tương tự như các tùy chọn khác nhưng tách các mối quan tâm tốt hơn một chút và chỉ hiển thị một trình thu thập thông số duy nhất thay vì một loạt các getters cụ thể. Nhược điểm: Điều này thêm một đối tượng toàn cầu-ish mà mọi người truy cập.

  2. Xác định hành động trong trường hợp sử dụng "chính", menu chính và sau đó có getters cho mọi người khác. Điều này đặt chúng ở một nơi và có nghĩa là cửa sổ chính sẽ cần phải cung cấp một hàm getter đơn cho menu chính thay thế. Nhưng nó vẫn cho thấy một loạt các thành viên nội bộ là công khai.

Cách tiếp cận tốt nhất là gì? Có điều gì tốt hơn mà tôi chưa liệt kê ở đây không?

Trả lời

2

Hãy để chúng tôi lùi lại một bước và xem phần mềm đang được thực hiện. Nó thường là một thực hành tốt để có giao diện người dùng tùy biến, để người dùng có thể tạo/sửa đổi các menu và thanh công cụ của ứng dụng. Điều này đòi hỏi các thanh công cụ/trình đơn được tạo bằng cách sử dụng tệp cấu hình (.xml hoặc .cfg), đơn giản chỉ liên kết các mục menu/thanh công cụ với các hành động.

Do đó, Hành động có các tên/mã hành động duy nhất sử dụng chúng có thể được giới thiệu.

Do đó, tôi khuyên bạn nên 1.4. Bạn có thể tạo hành động theo yêu cầu bằng cách sử dụng một số ActionFactory nhận tên/mã hành động làm đối số hoặc bạn có thể bắt buộc thực hiện yêu cầu Actions để tự đăng ký với số ActionRegistry (toàn cầu!) Mà từ đó chúng có thể được tra cứu.

PS: Trường hợp sử dụng khác cho Tác vụ được đặt tên là nếu phần mềm của bạn có SDK, bạn có thể dễ dàng cung cấp API tự động hóa (ví dụ: ApiExecuteAction(Actions.COPY)).

2

Chúng là tùy chọn hay lớp học của bạn yêu cầu chúng?

nếu lớp học của bạn yêu cầu họ vượt qua chúng vào nhà xây dựng, bạn nói ở đây danh sách đối số sẽ trở thành dài? sau đó tại sao không gói các hành động vào và đối tượng đầu tiên và sử dụng một phương pháp nhà máy để tạo ra đối tượng đã nói.

Nếu chúng không được truyền với bộ định vị và getters.

Something bạn có thể đọc vào và xem xét là các mô hình của dependency injection mà bạn có thể đọc thêm về ở đây:

What is dependency injection?

+0

Để trả lời cho câu hỏi của bạn, chúng được yêu cầu hiển thị ở nhiều nơi có nghĩa là nhiều lớp cần truy cập vào chúng. Đoạn thứ hai của bạn dường như đề xuất 1,1 hoặc 1,4 của tôi là tốt nhất. Cả hai đều có thể cho phép tiêm phụ thuộc. – metal

+2

@metal yeah, tôi hoàn toàn quay lại giải pháp 1.4, điều này sẽ giúp kiểm tra dễ dàng hơn, làm cho mọi thứ trở nên dễ dàng hơn, nếu bạn lo ngại mọi thứ phụ thuộc vào một đối tượng , thêm một giao diện mà đối tượng có thể lấy được từ, điều này ít nhất sẽ cho phép 'cắm và chạy' với các triển khai khác nhau của đối tượng và sẽ phá vỡ sự phụ thuộc mã nguồn giữa chúng. –

1

Vấn đề tái sử dụng QActions trong một số hộp thoại là kết nối lại của tín hiệu.

Bạn có thể tránh sự cố này khi tạo một nhóm lớp để lưu trữ một nhóm tín hiệu. Một cái gì đó như thế này:

template < class T > 
class EditionSet 
{ 
    T* parent; 

    public: 

    EditionSet(T* parent) 
     : parent(parent) 
    { 
     cutAction = new QAction("Cut", parent); 
     copyAction = new QAction("Copy", parent); 
     pasteAction = new QAction("Paste", parent); 

     QObject::connect(cutAction, SIGNAL(triggered()), 
         parent, SLOT(CutActionTriggered())); 

     QObject::connect(copyAction, SIGNAL(triggered()), 
         parent, SLOT(CopyActionTriggered())); 

     QObject::connect(pasteAction, SIGNAL(triggered()), 
         parent, SLOT(PasteActionTriggered())); 
    } 

    ~EditionSet() 
    { 
     QObject::disconnect(cutAction, SIGNAL(triggered()), 
          parent, SLOT(CutActionTriggered())); 

     QObject::disconnect(copyAction, SIGNAL(triggered()), 
          parent, SLOT(CopyActionTriggered())); 

     QObject::disconnect(pasteAction, SIGNAL(triggered()), 
          parent, SLOT(PasteActionTriggered())); 

     delete cutAction; 
     delete copyAction; 
     delete pasteAction; 
    } 

    QAction* cutAction; 
    QAction* copyAction; 
    QAction* pasteAction; 
}; 

class dialog : public QDialog 
{ 
    Q_OBJECT 

    public: 

    dialog::dialog(QWidget* parent) 
     : QDialog(parent), 
     ui(new Ui::dialog), 
     editionSet(EditionSet<dialog>(this)) 
    { 
     // ... 

     ui->mainToolBar->addAction(editionSet.cutAction); 
     ui->mainToolBar->addAction(editionSet.copyAction); 
     ui->mainToolBar->addAction(editionSet.pasteAction); 
    } 

    private: 

    EditionSet<dialog> editionSet; 
}; 

Nếu hành động sẽ luôn được chèn theo cùng thứ tự, bạn có thể cải thiện lớp này để cho phép "tự động chèn".

template < class T > 
class EditionSet 
{ 
    T* parent; 
    QAction* cutAction; 
    QAction* copyAction; 
    QAction* pasteAction; 

    public: 

    EditionSet(T* parent) 
     : parent(parent) 
    { 
     cutAction = new QAction("Cut", parent); 
     copyAction = new QAction("Copy", parent); 
     pasteAction = new QAction("Paste", parent); 

     QObject::connect(cutAction, SIGNAL(triggered()), 
         parent, SLOT(CutActionTriggered())); 

     QObject::connect(copyAction, SIGNAL(triggered()), 
         parent, SLOT(CopyActionTriggered())); 

     QObject::connect(pasteAction, SIGNAL(triggered()), 
         parent, SLOT(PasteActionTriggered())); 

    } 

    ~EditionSet() 
    { 
     QObject::disconnect(cutAction, SIGNAL(triggered()), 
          parent, SLOT(CutActionTriggered())); 

     QObject::disconnect(copyAction, SIGNAL(triggered()), 
          parent, SLOT(CopyActionTriggered())); 

     QObject::disconnect(pasteAction, SIGNAL(triggered()), 
          parent, SLOT(PasteActionTriggered())); 

     delete cutAction; 
     delete copyAction; 
     delete pasteAction; 
    } 

    void AddActionsTo(QWidget* container) 
    { 
     container->addAction(cutAction); 
     container->addAction(copyAction); 
     container->addAction(pasteAction); 
    } 
}; 

class MainWindow : public QMainWindow 
{ 
    Q_OBJECT 

    public: 
    MainWindow(QWidget *parent = 0) 
     : QMainWindow(parent), 
     ui(new Ui::MainWindow) 
     editionSet(EditionSet<MainWindow>(this)) 
    { 
     ui->setupUi(this); 

     editionSet.AddActionsTo(ui->mainToolBar); 
     editionSet.AddActionsTo(ui->menuBar); 
    } 

    private: 

    EditionSet<MainWindow> editionSet; 
}; 
1

Tôi đề xuất 1.1 hoặc 1.2 là giải pháp ít đau đớn nhất.

1.3 mở rộng giao diện công khai của lớp cửa sổ một cách rất tẻ nhạt.

1.4 giải quyết vấn đề về tính duy nhất toàn cầu đối với "không gian tên" mới - nơi lưu trữ các lệnh tồn tại.

2.0 hiển thị nhiều thông tin cá nhân, có vẻ như điều tồi tệ nhất đối với tôi.

BTW, nếu bạn chưa đọc lên mẫu Command, tôi khuyên bạn nên sử dụng.

+0

Cảm ơn. Tôi đã đọc mô hình Lệnh, và thực sự những hành động được chia sẻ này là các trường hợp của chúng. Câu hỏi đặt ra là, họ nên sống ở đâu? – metal

Các vấn đề liên quan