2010-03-11 23 views
15

Những gì tôi đang cố gắng làm là hiển thị qwidget trên một cửa sổ khác (bằng cách sử dụng QPainter thủ công)Qt: Làm thế nào để ép buộc một widget ẩn để tính toán bố trí của nó?

Tôi có một QWidget (w) với bố trí và một nhóm điều khiển con. w bị ẩn. Cho đến khi w được hiển thị, không có tính toán bố cục nào xảy ra, được mong đợi.

Khi tôi gọi w->render(painter, w->mapToGlobal(QPoint(0,0)), tôi nhận được một loạt các điều khiển chồng chéo nhau.
w->layout()->activate();w->layout()->update() dường như không làm gì cả.

Có cách nào để buộc bố cục xảy ra mà không hiển thị w không?

Trả lời

15

Buộc một tính toán bố trí trên một widget mà không hiển thị nó trên màn hình:

widget->setAttribute(Qt::WA_DontShowOnScreen); 
widget->show(); 

Cuộc gọi show() sẽ buộc các tính toán bố trí, và Qt::WA_DontShowOnScreen đảm bảo rằng các phụ tùng không được hiển thị một cách rõ ràng.

+2

Cảm ơn bạn quan tâm, hoạt động hoàn hảo! – Chris

+0

Lưu ý rằng một tiện ích sẽ chỉ hiển thị nếu tất cả tổ tiên của nó cũng hiển thị. Nếu đây không phải là trường hợp, gọi 'show()' có thể không giải quyết được vấn đề ở đây. Xem câu trả lời của tôi dưới đây cho một cách tiếp cận khác nhau mà nên luôn luôn làm việc. – emkey08

+1

@MathiasKunter Tuy nhiên, cần lưu ý rằng các sự kiện vẽ hoàn toàn chảy vào tiện ích "hiển thị" (nhưng không hiển thị trên màn hình), nếu bạn nói, hãy cho chuột nhấp chuột vào nó (không giống với tiện ích con không có dấu ngoặc đơn)! – mlvljr

1

Hãy thử với phương thức QWidget::sizeHint(), được cho là sẽ trả về kích thước của tiện ích khi được đặt ra.

+0

Tôi đã thử điều đó và nó đã cho tôi trở lại kích thước hợp lý .. nhưng nó không cập nhật vị trí! Vì vậy, các kích thước trông đúng, nhưng chúng vẫn nằm trên đầu trang của nhau. – Chris

0

Điều này làm việc cho tôi khi sử dụng sizeHint() cộng với dịch họa sĩ, tuy nhiên tôi làm điều này bên trong phương thức paint().

void ParentWidget::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const 
{ 
    painter->save(); 
    painter->translate(option.rect.topLeft()); 
    w->render(painter); 
    painter->restore(); 
} 

Trong trường hợp này, option.rect.topLeft() cho tôi vị trí chính xác. Bạn nên thử một tọa độ hợp lý hơn thay vì w->mapToGlobal(QPoint(0,0).

0

Tôi đã có một số succes trong một vấn đề tương tự bằng cách trước tiên gọi w->layout()->update() trước w->layout()->activate(). Điều đó dường như buộc các kích hoạt() để thực sự làm một cái gì đó hơn là nghĩ rằng nó là tốt vì cửa sổ không được hiển thị anyway.

10

Tính toán bố cục của tiện ích con có thể bị ép buộc bằng cách gọi invalidate() theo sau là activate() trên bố cục của nó, ngay cả khi tiện ích bị ẩn. Điều này cũng làm cho các hàm size()sizeHint() của tiện ích trở lại đúng giá trị được cập nhật, ngay cả khi show() chưa được gọi trên tiện ích đó.

Tuy nhiên, cần phải quan tâm đến tất cả các tiện ích và bố cục con theo cách đệ quy, vì yêu cầu tính toán lại bố cục không tự động truyền cho trẻ.

Mã sau đây cho biết cách thực hiện việc này.

/** 
* Forces the given widget to update, even if it's hidden. 
*/ 
void forceUpdate(QWidget *widget) { 
    // Update all child widgets. 
    for (int i = 0; i < widget->children().size(); i++) { 
     QObject *child = widget->children()[i]; 
     if (child->isWidgetType()) { 
      forceUpdate((QWidget *)child); 
     } 
    } 

    // Invalidate the layout of the widget. 
    if (widget->layout()) { 
     invalidateLayout(widget->layout()); 
    } 
} 

/** 
* Helper function for forceUpdate(). Not self-sufficient! 
*/ 
void invalidateLayout(QLayout *layout) { 
    // Recompute the given layout and all its child layouts. 
    for (int i = 0; i < layout->count(); i++) { 
     QLayoutItem *item = layout->itemAt(i); 
     if (item->layout()) { 
      invalidateLayout(item->layout()); 
     } else { 
      item->invalidate(); 
     } 
    } 
    layout->invalidate(); 
    layout->activate(); 
} 
+0

'layout-> invalidate(); layout-> activate(); 'đã làm việc cho tôi cho một ứng dụng hơi khác: buộc thay đổi kích thước của bố cục đã hiển thị sau khi thêm/xóa tiện ích con. – Onlyjus

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