2015-01-09 18 views
7

Kể từ hai ngày qua, tôi đang tìm kiếm và tìm ra cách để chuyển các sự kiện chuột đến các tiện ích con sau một tiện ích được sử dụng làm vùng chứa/cấp độ gốc cho con của nó. Tôi biết có một cách để làm cho một widget trong suốt cho các sự kiện chuột như thế này:Làm thế nào để vô hiệu hóa việc cung cấp các sự kiện chuột cho widget nhưng không phải là con của nó trong Qt?

QWidget w; 
w.setAttribute(Qt::WA_TransparentForMouseEvents); 

Nhưng điều này cũng vô hiệu hóa việc cung cấp các sự kiện chuột cho con của nó! Thực ra tôi muốn con cái của tiện ích con phía trước và các tiện ích đằng sau tiện ích con phía trước để trả lời các sự kiện chuột.

Qt :: WA_TransparentForMouseEvents: Khi được bật, thuộc tính này sẽ tắt phân phối sự kiện chuột cho tiện ích và con của nó. Sự kiện chuột được gửi đến các tiện ích con khác như thể tiện ích con và các tiện ích con không có trong phân cấp tiện ích con; nhấp chuột và các sự kiện khác có hiệu quả “vượt qua” chúng. Thuộc tính này là bị tắt theo mặc định.

Nếu bạn có bất kỳ ý tưởng nào về cách tạo tiện ích trong suốt cho các sự kiện chuột nhưng không phải là con thì hãy chia sẻ!

Trả lời

8

Cuối cùng tôi tìm thấy giải pháp :) Câu trả lời này dành cho những người đang tìm kiếm giải pháp cho loại vấn đề này. chính: Mấu chốt của giải pháp là QWidget :: setMask (const QRegion & khu vực)

http://doc.qt.io/qt-5/qwidget.html#setMask-2

http://qt-project.org/doc/qt-4.8/qwidget.html#setMask

tôi đã tìm thấy các giải pháp ở đây: http://www.qtcentre.org/archive/index.php/t-3033.html

QRegion reg(frameGeometry()); 
reg -= QRegion(geometry()); 
reg += childrenRegion(); 
setMask(reg); 

Bây giờ, con của tiện ích con phía trước và phần mở rộng được phía sau widget phía trước đáp ứng với các sự kiện chuột theo yêu cầu!

Hãy nhớ rằng bạn sẽ cần phải gọi lại những dòng này bất cứ khi nào tiện ích con trước được kích thước lại để tính toán lại hình học cho mặt nạ (trong trường hợp của tôi không bắt buộc nhưng đối với những người có thể cần).

void someWidget::resizeEvent(QResizeEvent *e){ 
QWidget::resizeEvent(e); 
QRegion reg(frameGeometry()); 
reg-=QRegion(geometry()); 
reg+=childrenRegion(); 
setMask(reg); 
} 
+0

hey đây là những gì tôi đang tìm kiếm, nhưng im trong PYTHON !, im cố gắng dịch ví dụ của bạn thành pyqt4, bất kỳ ý tưởng nào? –

0

Giải pháp của OP thật tuyệt vời và rất thanh lịch. Chỉ để hoàn thành, một tùy chọn khác là bỏ qua các sự kiện chuột khi chúng đến tiện ích vùng chứa. Nó có thể được thực hiện bằng cách phân lớp hoặc thông qua một eventFilter.

Giải pháp này có thể hữu ích nếu tiện ích ẩn/hiển thị nhiều tiện ích con động và tính toán mặt nạ trở nên khó khăn.

Lưu ý: Trong trường hợp bạn muốn theo dõi các sự kiện di chuyển chuột trong tiện ích nền, bạn phải setMouseTracking(true) để nhận (và sau đó bỏ qua) QEvent::MouseMove khi không bấm nút nào.

Ví dụ theo tiểu classing

ContainerWidget::ContainerWidget(...) { 
    setMouseTracking(true); 
} 

void ContainerWidget::mouseMoveEvent(QMouseEvent* e) { 
    e->ignore(); 
} 
void ContainerWidget::mousePressEvent(QMouseEvent* e) { 
    e->ignore(); 
} 

Ví dụ sử dụng bộ lọc sự kiện

// Assume the container widget is configured in the constructor 
MainWindow::MainWindow(...) { 
    // ... 
    containerWidget->installEventFilter(this); 
    containerWidget->setMouseTracking(true); 
    // ... 
} 

bool MainWindow::eventFilter(QObject* o, QEvent* e) { 
    if (o == containerWidget && 
    (e->type() == QEvent::MouseMove || e->type() == QEvent::MouseButtonPress)) { 
    e->ignore(); 
    return false; 
    } 
    return QMainWindow::eventFilter(o, e); 
} 
Các vấn đề liên quan