2012-02-07 47 views
5

Tôi đang tạo một ứng dụng bằng cách sử dụng Qt bao gồm một tiện ích được sử dụng làm nền của ứng dụng và giao diện điều khiển người dùng đang nổi ở trên.Làm thế nào để Layer widget độc lập trong Qt?

Ví dụ tương tự là bản đồ google, nơi bản đồ ở chế độ nền và các điều khiển nằm trên nền.

Nhưng điều này là widget nền có thể được thay đổi để một widget khác nhau (có một widget mà sẽ hiển thị một bản đồ, một widget mà hiển thị cấp dữ liệu video, ...)

Và điều tương tự sẽ xảy ra cho các nút trong giao diện điều khiển người dùng, chúng không liên quan trực tiếp đến nền hiện tại và có thể thay đổi theo chế độ ăn tối.

Tôi đã thử sử dụng QStackedLayout, sử dụng hai lớp, tiện ích nền và giao diện điều khiển người dùng. Nhưng bạn không thể tương tác với lớp nền vì tất cả các nhấp chuột đều bị chặn bởi tiện ích ở phía trước.

Mọi đề xuất?

Trả lời

1

Câu hỏi của bạn quá chung chung để cung cấp cho bạn câu trả lời đặc biệt, nhưng giải pháp rõ ràng nhất là triển khai các lớp kế thừa từ QWidget cho từng thành phần có thể có trong hệ thống của bạn. Trong ví dụ của bạn, tôi có thể hình dung 2 thành phần riêng biệt: Nền và Điều khiển. Nền sẽ lưu trữ tất cả dữ liệu hình ảnh, như bản đồ và video, trong khi các Điều khiển sẽ có các nút để tương tác với hệ thống. Bạn thậm chí có thể phá vỡ Background thành các lớp khác nhau để quản lý hình ảnh hoặc video. Tôi khuyên bạn nên sử dụng một lớp GUIController trung tâm kế thừa từ QObject để quản lý tất cả các tương tác giao diện, như kết nối các tín hiệu/khe hoặc thực hiện bất kỳ hoạt ảnh nào, bằng cách này bạn có thể thêm/quản lý nhiều tiện ích mà không đi qua các tệp .cpp khác nhau.

EDIT: Với nhận xét của bạn, có vẻ vấn đề chính của bạn là sự kiện chuột của bạn không được truyền tới tiện ích như bạn mong đợi. Có lẽ lý do cho điều này là bạn không thiết lập mối quan hệ cha/con giữa các thành phần. Đảm bảo rằng bạn đang gọi hàm tạo QWidget mặc định trong các lớp tiện ích tùy chỉnh của bạn như trên:

Khi tạo lớp Bộ điều khiển, đặt mối quan hệ đúng giữa các thành phần. Trong bối cảnh hệ thống của bạn, seens với tôi rằng tất cả các thành phần này sẽ được thêm vào như con Bối cảnh, vì vậy nó sẽ trông giống như dưới đây:

class Controller : public QObject 
{ 
public: 
    Controller(QObject *parent = 0, Qt::WFlags flags = 0) : QObject(parent, flags) 
    { 
    wdg_back_= new BackWidget(this); 
    wdg_control_ = new Controls(wdg_back); 
    wdg_1_ = new GenericWidget(wdg_back); 

    //connect your signals/slots, etc 
    } 

private: 
    BackWidget *wdg_back_; 
    Controls *wdg_control_; 
    GenericWidget *wdg_1_; 
} 
+1

Đó là cách tiếp cận tôi đã theo dõi, tôi đã nhóm tất cả các điều khiển thành một tiện ích duy nhất, trong đó chứa chúng với bố cục thích hợp. Nhưng vấn đề là, ngay cả khi có một vài vật dụng nằm rải rác trên màn hình, Widget điều khiển này chiếm toàn bộ màn hình và chặn các sự kiện nhấp chuột. Một điều tôi tin rằng có thể giải quyết vấn đề này, là để thêm các điều khiển từng người một như các lớp riêng biệt trên các widget xếp chồng lên nhau. Bằng cách này, họ sẽ chỉ chặn các nhấp chuột trên đó. – Victor

+0

Bạn có chắc chắn rằng bạn đang thêm tất cả các tiện ích của mình làm trẻ em của tiện ích con nền/kiểm soát này không? Hãy chắc chắn rằng các nhà xây dựng widget tùy chỉnh của bạn đang gọi hàm tạo mặc định QWidget và bạn đang thiết lập tiện ích con (có thể là nền) làm cha của tất cả các tiện ích con của bạn trong quá trình khởi tạo GUI. –

+0

Vấn đề dường như là một trong những thảo luận ở đây: http://www.qtcentre.org/threads/45844-Mouse-events-with-StackAll-QStackedLayout Vì tôi đang sử dụng một stackedLayout với hai widget (nền và widget điều khiển), tiện ích điều khiển nằm ở trên cùng, đang chặn tất cả các sự kiện nhấp chuột. Tôi sẽ thử đặt tiện ích điều khiển làm trẻ em ở chế độ nền, thay vì chúng là anh chị em. – Victor

2

Bạn có thể đặt một bộ lọc trên dòng sự kiện vào widget giao diện của bạn bằng cách sử dụng QObject::installEventFilter() và chặn tất cả các sự kiện nhấp chuột đến. Khi bạn đã nắm bắt các sự kiện này, hãy sử dụng chức năng lọc để ủy quyền chúng cho tiện ích nền hoặc phân phối chúng tới các nút giao diện phía trước. Bạn rất có thể sẽ phải sử dụng các tọa độ (x, y) của nhấp chuột để xác định xem sự kiện có nên chuyển đến tiện ích nền hay một trong các tiện ích nút nền trước.

Một lựa chọn khác là tạo ra một lớp có nguồn gốc từ QAbstractButton (hoặc bất kỳ QWidget bạn đang sử dụng cho các nút bấm của bạn), và tái thực hiện các chức năng sự kiện cho chuột-nhấp chuột vào widget đó (ví dụ: QAbstractButton::mousePressEvent(), vv). Khi nhấp chuột đến, hãy kiểm tra xem con chuột đã qua nút chưa, và nếu không, hãy gửi sự kiện đến tiện ích nền thông qua tín hiệu hoặc QCoreApplication::sendEvent().

+0

Đây là một cách tiếp cận tốt đẹp mà tôi đã không nghĩ đến, Tôi chắc chắn sẽ thực hiện điều này nếu tôi không thể tìm cách khác để loại bỏ chúng mà không chặn các sự kiện nhấp chuột. – Victor

+0

Tôi đã thử triển khai thực hiện điều này, hiện tại tôi đang cố gắng chuyển tiếp tất cả mousePressEvents tới tiện ích nền với: QCoreApplication :: sendEvent (_bgWidget, ev); bên trong trình xử lý mousePressEvent, nhưng chúng được nhận trong phụ huynh của tiện ích nền thay vì trong chính tiện ích nền. – Victor

+1

Đối tượng nền của bạn cũng phải thực hiện lại 'mousePressEvent()' hoặc 'event()' để có thể xử lý đúng các sự kiện bạn đang gửi ... nếu không thì việc triển khai mặc định các hàm này trong lớp cơ sở bạn đã có nguồn gốc từ đơn giản sẽ trả về 'false', và cha mẹ sẽ là người nhận của sự kiện. – Jason

0

Ok cuối cùng tôi đã tìm được giải pháp cho vấn đề của mình.

Cách tiếp cận của tôi về việc sử dụng QStackedWidget là sai, tiện ích trên nền không có nghĩa là có thể nhấp và mặc dù nó có thể được thực hiện, nó không phải là những gì tôi đang tìm kiếm.

Cuối cùng, đây là những gì tôi đã thực hiện:

QWidget *centralWidget = new QWidget(this); 
setCentralWidget(centralWidget); 

MapView *backgroundWidget = new MapView(centralWidget); 
backgroundWidget->setMinimumSize(1024,600); 

QGridLayout *controlsLayout = new QGridLayout(centralWidget); 
MyControlWidget *control1 = new MyControlWidget(centralWidget); 
control1->setMinimumSize(140,140); 
control1->show(); 

controlsLayout->addWidget(control1,2,0); 

Vì vậy, tôi tạo ra một QWidget, centralWidget đó sẽ là mẹ của các nền và foreground. Đặt nền thành toàn màn hình và tổ chức các điều khiển trong QGridLayout, điều này không ảnh hưởng đến backgroundWidget.

Nếu tôi nhấp vào điều khiển, sự kiện được xử lý bởi điều khiển này, nhưng việc nhấp vào khoảng trống sẽ kích hoạt sự kiện chuột trên backgroundWidget, đó là những gì tôi cần.

Tôi sẽ kiểm tra điều này một thời gian và nếu hoạt động tốt, tôi sẽ đóng câu hỏi.

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