原創|使用教程|編輯:龔雪|2022-05-12 10:27:17.097|閱讀 242 次
概述:本文主要為大家介紹Qt 布局系統中的布局管理功能,歡迎大家下載相關組件體驗!
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
相關鏈接:
Qt布局系統提供了一種簡單而強大的方式來自動排列小部件內的子小部件,以確保它們充分利用可用空間。
Qt技術交流群:166830288 歡迎一起進群討論
如果您正在制作獨一無二的特殊布局,還可以制作如前幾篇文章所述的自定義小部件,重新實現 ()來計算所需的尺寸分布并在每個子集上調用()。
當需要重新計算布局時,小部件將獲得 類型的事件,重新實現 () 來處理 事件。
手動布局的替代方法是通過繼承來編寫自己的布局管理器,邊框布局和流布局示例展示了如何執行此操作。
這里我們詳細介紹一個例子。CardLayout 類的靈感來自同名的 Java 布局管理器,它將項目(小部件或嵌套布局)放在彼此的頂部,每個項目由 ()偏移。
要編寫自己的布局類,您必須定義以下內容:
在大多數情況下,您還將實現 ()。
Header File (card.h)
#ifndef CARD_H #define CARD_H #include <QtWidgets> #include <QList> class CardLayout : public QLayout { public: CardLayout(int spacing): QLayout() { setSpacing(spacing); } CardLayout(int spacing, QWidget *parent): QLayout(parent) { setSpacing(spacing); } ~CardLayout(); void addItem(QLayoutItem *item) override; QSize sizeHint() const override; QSize minimumSize() const override; int count() const override; QLayoutItem *itemAt(int) const override; QLayoutItem *takeAt(int) override; void setGeometry(const QRect &rect) override; private: QList<QLayoutItem *> m_items; }; #endif
Implementation File (card.cpp)
//#include "card.h"
首先我們定義 count() 來獲取列表中的項目數。
int CardLayout::count() const { // QList::size() returns the number of QLayoutItems in m_items return m_items.size(); }
然后我們定義了兩個遍歷布局的函數:itemAt() 和 takeAt()。 布局系統內部使用這些函數來處理小部件的刪除,它們也可供應用程序程序員使用。
itemAt() 返回給定索引處的項目,takeAt() 刪除給定索引處的項目,并將其返回。 在這種情況下,我們使用列表索引作為布局索引。 在我們有更復雜的數據結構的其他情況下,可能需要花費更多的精力來定義項目的線性順序。
QLayoutItem *CardLayout::itemAt(int idx) const { // QList::value() performs index checking, and returns nullptr if we are // outside the valid range return m_items.value(idx); } QLayoutItem *CardLayout::takeAt(int idx) { // QList::take does not do index checking return idx >= 0 && idx < m_items.size() ? m_items.takeAt(idx) : 0; }
addItem() 實現布局項的默認放置策略,必須實現此功能。 它由 QLayout::add() 使用,由將布局作為父級的 構造函數使用。如果您的布局具有需要參數的高級放置選項,則必須提供額外的訪問函數,例如 ()、()和 () 的跨行和跨列重載。
void CardLayout::addItem(QLayoutItem *item) { m_items.append(item); }
布局接管添加的項目的責任,由于不繼承 ,我們必須手動刪除項目。 在析構函數中,使用 takeAt() 從列表中刪除每個項目,然后將其刪除。
CardLayout::~CardLayout() { QLayoutItem *item; while ((item = takeAt(0))) delete item; }
setGeometry() 函數實際上執行布局,作為參數提供的矩形不包括 margin()。 如果相關,請使用 spacing() 作為項目之間的距離。
void CardLayout::setGeometry(const QRect &r) { QLayout::setGeometry(r); if (m_items.size() == 0) return; int w = r.width() - (m_items.count() - 1) * spacing(); int h = r.height() - (m_items.count() - 1) * spacing(); int i = 0; while (i < m_items.size()) { QLayoutItem *o = m_items.at(i); QRect geom(r.x() + i * spacing(), r.y() + i * spacing(), w, h); o->setGeometry(geom); ++i; } }
sizeHint() 和 minimumSize() 在實現上通常非常相似,兩個函數返回的尺寸都應該包括spacing(),但不包括margin()。
QSize CardLayout::sizeHint() const { QSize s(0, 0); int n = m_items.count(); if (n > 0) s = QSize(100, 70); //start with a nice default size int i = 0; while (i < n) { QLayoutItem *o = m_items.at(i); s = s.expandedTo(o->sizeHint()); ++i; } return s + n * QSize(spacing(), spacing()); } QSize CardLayout::minimumSize() const { QSize s(0, 0); int n = m_items.count(); int i = 0; while (i < n) { QLayoutItem *o = m_items.at(i); s = s.expandedTo(o->minimumSize()); ++i; } return s + n * QSize(spacing(), spacing()); }
Qt技術交流群:166830288 歡迎一起進群討論
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉載自:慧都網