Beispiel für grundlegende Grafiklayouts
Zeigt, wie man grundlegende Grafiklayouts erstellt.
Das Beispiel "Grundlegende Grafiklayouts" zeigt, wie die Layout-Klassen in QGraphicsView: QGraphicsLinearLayout und QGraphicsGridLayout verwendet werden. Darüber hinaus wird gezeigt, wie Sie Ihr eigenes benutzerdefiniertes Layout-Element schreiben können.
Definition der Fensterklasse
Die Klasse Window
ist eine Unterklasse von QGraphicsWidget. Sie hat einen Konstruktor mit einem QGraphicsWidget parent als Parameter.
class Window : public QGraphicsWidget { Q_OBJECT public: Window(QGraphicsWidget *parent = nullptr); };
Implementierung der Fensterklasse
Der Konstruktor von Window
instanziiert ein QGraphicsLinearLayout Objekt, windowLayout
, mit vertikaler Ausrichtung. Wir instanziieren ein weiteres QGraphicsLinearLayout Objekt, linear
, dessen Elternteil windowLayout
ist. Als nächstes erstellen wir ein LayoutItem
Objekt, item
und fügen es mit der Funktion addItem() zu linear
hinzu. Wir versehen auch item
mit einem stretchFactor.
QGraphicsLinearLayout *windowLayout = new QGraphicsLinearLayout(Qt::Vertical); QGraphicsLinearLayout *linear = new QGraphicsLinearLayout(windowLayout); LayoutItem *item = new LayoutItem; linear->addItem(item); linear->setStretchFactor(item, 1);
Wir wiederholen den Vorgang:
- Erstellen Sie ein neues
LayoutItem
, - fügen Sie das Objekt
linear
hinzu, und - stellen einen Streckungsfaktor bereit.
item = new LayoutItem; linear->addItem(item); linear->setStretchFactor(item, 3); windowLayout->addItem(linear);
Dann fügen wir linear
zu windowLayout
hinzu und verschachteln zwei QGraphicsLinearLayout Objekte. Neben dem QGraphicsLinearLayout verwenden wir auch ein QGraphicsGridLayout Objekt, grid
, das ein 4x3-Gitter mit einigen Zellen ist, die sich auf andere Zeilen erstrecken.
Wir erstellen sieben LayoutItem
Objekte und fügen sie mit der Funktion addItem() in grid
ein, wie im folgenden Codeschnipsel gezeigt:
QGraphicsGridLayout *grid = new QGraphicsGridLayout(windowLayout); item = new LayoutItem; grid->addItem(item, 0, 0, 4, 1); item = new LayoutItem; item->setMaximumHeight(item->minimumHeight()); grid->addItem(item, 0, 1, 2, 1, Qt::AlignVCenter); item = new LayoutItem; item->setMaximumHeight(item->minimumHeight()); grid->addItem(item, 2, 1, 2, 1, Qt::AlignVCenter); item = new LayoutItem; grid->addItem(item, 0, 2); item = new LayoutItem; grid->addItem(item, 1, 2); item = new LayoutItem; grid->addItem(item, 2, 2); item = new LayoutItem; grid->addItem(item, 3, 2); windowLayout->addItem(grid);
Das erste Objekt, das wir zu grid
hinzufügen, wird in der linken oberen Zelle platziert und erstreckt sich über vier Zeilen. Die nächsten beiden Elemente werden in der zweiten Spalte platziert und erstrecken sich über zwei Zeilen. Die Einträge maximumHeight() und minimumHeight() sind gleich groß, so dass sie sich nicht vertikal ausdehnen. Infolgedessen passen diese Elemente nicht vertikal in ihre Zellen. Daher legen wir mit Qt::AlignVCenter fest, dass sie vertikal in der Mitte der Zelle ausgerichtet werden sollen.
Schließlich wird grid
selbst zu windowLayout
hinzugefügt. Anders als QGridLayout::addItem() benötigt QGraphicsGridLayout::addItem() eine Zeile und eine Spalte als Argument, um anzugeben, in welcher Zelle das Element positioniert werden soll. Wenn die Argumente rowSpan
und columnSpan
weggelassen werden, werden sie auf 1 gesetzt.
Beachten Sie, dass wir nicht für jedes LayoutItem
, das wir erstellen, ein übergeordnetes Element angeben, da alle diese Elemente zu windowLayout
hinzugefügt werden. Wenn wir ein Element zu einem Layout hinzufügen, wird es automatisch dem Widget zugewiesen, auf dem das Layout installiert ist.
setLayout(windowLayout);
setWindowTitle(tr("Basic Graphics Layouts Example"));
Nachdem wir nun grid
erstellt und zu windowLayout
hinzugefügt haben, installieren wir windowLayout
mit QGraphicsWidget::setLayout() auf dem Fensterobjekt und setzen den Fenstertitel.
Definition der Klasse LayoutItem
Die Klasse LayoutItem
ist eine Unterklasse von QGraphicsLayoutItem und QGraphicsItem. Sie hat einen Konstruktor, einen Destruktor und einige erforderliche Reimplementierungen. Da sie QGraphicsLayoutItem erbt, muss sie {QGraphicsLayoutItem::setGeometry()}{setGeometry()} und {QGraphicsLayoutItem::sizeHint()}{sizeHint()} reimplementieren. Außerdem erbt sie QGraphicsItem, so dass sie {QGraphicsItem::boundingRect()}{boundingRect()} und {QGraphicsItem::paint()}{paint()} neu implementieren muss.
class LayoutItem : public QGraphicsLayoutItem, public QGraphicsItem { public: LayoutItem(QGraphicsItem *parent = nullptr); // Inherited from QGraphicsLayoutItem void setGeometry(const QRectF &geom) override; QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const override; // Inherited from QGraphicsItem QRectF boundingRect() const override; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override; private: QPixmap m_pix; };
Die Klasse LayoutItem
hat auch eine private Instanz von QPixmap, m_pix
.
Implementierung der Klasse LayoutItem
Im Konstruktor von LayoutItem
wird m_pix
instanziiert und das Bild block.png
in die Klasse geladen.
LayoutItem::LayoutItem(QGraphicsItem *parent) : QGraphicsLayoutItem(), QGraphicsItem(parent), m_pix(QPixmap(QLatin1String(":/images/block.png"))) { setGraphicsItem(this); }
Wir verwenden das Makro Q_UNUSED(), um zu verhindern, dass der Compiler Warnungen über unbenutzte Parameter ausgibt.
void LayoutItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(widget); Q_UNUSED(option); QRectF frame(QPointF(0, 0), geometry().size()); const QSize pmSize = m_pix.size(); QGradientStops stops;
Die Idee hinter der Funktion paint()
ist es, das Hintergrund-Rect zu malen und dann ein Rect um die Pixmap zu malen.
// paint a background rect (with gradient) QLinearGradient gradient(frame.topLeft(), frame.topLeft() + QPointF(200,200)); stops << QGradientStop(0.0, QColor(60, 60, 60)); stops << QGradientStop(frame.height() / 2 / frame.height(), QColor(102, 176, 54)); //stops << QGradientStop(((frame.height() + h)/2 )/frame.height(), QColor(157, 195, 55)); stops << QGradientStop(1.0, QColor(215, 215, 215)); gradient.setStops(stops); painter->setBrush(QBrush(gradient)); painter->drawRoundedRect(frame, 10.0, 10.0); // paint a rect around the pixmap (with gradient) QPointF pixpos = frame.center() - (QPointF(pmSize.width(), pmSize.height()) / 2); QRectF innerFrame(pixpos, pmSize); innerFrame.adjust(-4, -4, 4, 4); gradient.setStart(innerFrame.topLeft()); gradient.setFinalStop(innerFrame.bottomRight()); stops.clear(); stops << QGradientStop(0.0, QColor(215, 255, 200)); stops << QGradientStop(0.5, QColor(102, 176, 54)); stops << QGradientStop(1.0, QColor(0, 0, 0)); gradient.setStops(stops); painter->setBrush(QBrush(gradient)); painter->drawRoundedRect(innerFrame, 10.0, 10.0); painter->drawPixmap(pixpos, m_pix); }
Die Neuimplementierung von boundingRect() setzt die linke obere Ecke auf (0,0), und die Größe des Rects entspricht der Größe der Layoutelemente geometry(). Dies ist der Bereich, in dem wir malen.
Die Neuimplementierung von setGeometry() ruft einfach ihre Basisklassenimplementierung auf. Da dies jedoch das BoundingRect ändert, müssen wir auch prepareGeometryChange() aufrufen. Schließlich verschieben wir das Element gemäß geom.topLeft()
.
void LayoutItem::setGeometry(const QRectF &geom) { prepareGeometryChange(); QGraphicsLayoutItem::setGeometry(geom); setPos(geom.topLeft()); }
Da wir nicht wollen, dass die Größe des Objekts kleiner ist als die Pixmap, müssen wir sicherstellen, dass wir einen Größenhinweis zurückgeben, der größer ist als m_pix
. Wir fügen auch etwas zusätzlichen Platz für Ränder hinzu, die wir später malen werden. Alternativ können Sie die Pixmap auch skalieren, um zu verhindern, dass das Element kleiner als die Pixmap wird. Die bevorzugte Größe entspricht dem Hinweis auf die Mindestgröße, während wir die Maximalgröße auf einen großen Wert setzen
QSizeF LayoutItem::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const { switch (which) { case Qt::MinimumSize: case Qt::PreferredSize: // Do not allow a size smaller than the pixmap with two frames around it. return m_pix.size() + QSize(12, 12); case Qt::MaximumSize: return QSizeF(1000,1000); default: break; } return constraint; }
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.