qt 6.5.1 original

This commit is contained in:
kleuter
2023-10-29 23:33:08 +01:00
parent 71d22ab6b0
commit 85d238dfda
21202 changed files with 5499099 additions and 0 deletions

View File

@ -0,0 +1,14 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
qt_internal_add_example(chip)
qt_internal_add_example(elasticnodes)
qt_internal_add_example(embeddeddialogs)
qt_internal_add_example(collidingmice)
qt_internal_add_example(basicgraphicslayouts)
qt_internal_add_example(diagramscene)
qt_internal_add_example(flowlayout)
qt_internal_add_example(simpleanchorlayout)
if(QT_FEATURE_cursor AND QT_FEATURE_draganddrop)
qt_internal_add_example(dragdroprobot)
endif()

View File

@ -0,0 +1,9 @@
Qt is provided with a comprehensive canvas through the GraphicsView
classes.
These examples demonstrate the fundamental aspects of canvas programming
with Qt.
Documentation for these examples can be found via the Examples
link in the main Qt documentation.

View File

@ -0,0 +1,50 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(basicgraphicslayouts LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/graphicsview/basicgraphicslayouts")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
qt_standard_project_setup()
qt_add_executable(basicgraphicslayouts
layoutitem.cpp layoutitem.h
main.cpp
window.cpp window.h
)
set_target_properties(basicgraphicslayouts PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(basicgraphicslayouts PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
# Resources:
set(basicgraphicslayouts_resource_files
"images/block.png"
)
qt_add_resources(basicgraphicslayouts "basicgraphicslayouts"
PREFIX
"/"
FILES
${basicgraphicslayouts_resource_files}
)
install(TARGETS basicgraphicslayouts
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -0,0 +1,12 @@
QT += widgets
HEADERS = layoutitem.h \
window.h
SOURCES = layoutitem.cpp \
main.cpp \
window.cpp
RESOURCES = basicgraphicslayouts.qrc
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/graphicsview/basicgraphicslayouts
INSTALLS += target

View File

@ -0,0 +1,5 @@
<RCC>
<qresource>
<file>images/block.png</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,90 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "layoutitem.h"
#include <QGradient>
#include <QPainter>
//! [0]
LayoutItem::LayoutItem(QGraphicsItem *parent)
: QGraphicsLayoutItem(), QGraphicsItem(parent),
m_pix(QPixmap(QLatin1String(":/images/block.png")))
{
setGraphicsItem(this);
}
//! [0]
//! [1]
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;
//! [1]
//! [2]
// 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);
}
//! [2]
//! [3]
QRectF LayoutItem::boundingRect() const
{
return QRectF(QPointF(0, 0), geometry().size());
}
//! [3]
//! [4]
void LayoutItem::setGeometry(const QRectF &geom)
{
prepareGeometryChange();
QGraphicsLayoutItem::setGeometry(geom);
setPos(geom.topLeft());
}
//! [4]
//! [5]
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;
}
//! [5]

View File

@ -0,0 +1,30 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef LAYOUTITEM_H
#define LAYOUTITEM_H
#include <QGraphicsLayoutItem>
#include <QGraphicsItem>
#include <QPixmap>
//! [0]
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;
};
//! [0]
#endif // LAYOUTITEM_H

View File

@ -0,0 +1,22 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "window.h"
#include <QApplication>
#include <QGraphicsView>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QGraphicsScene scene;
Window *window = new Window;
scene.addItem(window);
QGraphicsView view(&scene);
view.resize(600, 600);
view.show();
return app.exec();
}

View File

@ -0,0 +1,53 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "window.h"
#include "layoutitem.h"
#include <QGraphicsLinearLayout>
#include <QGraphicsGridLayout>
Window::Window(QGraphicsWidget *parent) : QGraphicsWidget(parent, Qt::Window)
{
//! [0]
QGraphicsLinearLayout *windowLayout = new QGraphicsLinearLayout(Qt::Vertical);
QGraphicsLinearLayout *linear = new QGraphicsLinearLayout(windowLayout);
LayoutItem *item = new LayoutItem;
linear->addItem(item);
linear->setStretchFactor(item, 1);
//! [0]
//! [1]
item = new LayoutItem;
linear->addItem(item);
linear->setStretchFactor(item, 3);
windowLayout->addItem(linear);
//! [1]
//! [2]
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);
//! [2]
//! [3]
setLayout(windowLayout);
setWindowTitle(tr("Basic Graphics Layouts Example"));
//! [3]
}

View File

@ -0,0 +1,20 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef WINDOW_H
#define WINDOW_H
#include <QGraphicsWidget>
//! [0]
class Window : public QGraphicsWidget
{
Q_OBJECT
public:
Window(QGraphicsWidget *parent = nullptr);
};
//! [0]
#endif //WINDOW_H

View File

@ -0,0 +1,63 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(chip LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/graphicsview/chip")
find_package(Qt6
REQUIRED COMPONENTS Core Gui Widgets
OPTIONAL_COMPONENTS PrintSupport
)
qt_standard_project_setup()
qt_add_executable(chip
chip.cpp chip.h
main.cpp
mainwindow.cpp mainwindow.h
view.cpp view.h
)
set_target_properties(chip PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(chip PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
# Resources:
set(images_resource_files
"fileprint.png"
"qt4logo.png"
"rotateleft.png"
"rotateright.png"
"zoomin.png"
"zoomout.png"
)
qt_add_resources(chip "images"
PREFIX
"/"
FILES
${images_resource_files}
)
if(TARGET Qt6::PrintSupport)
target_link_libraries(chip PRIVATE Qt6::PrintSupport)
endif()
install(TARGETS chip
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -0,0 +1,147 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "chip.h"
#include <QGraphicsSceneMouseEvent>
#include <QPainter>
#include <QStyleOptionGraphicsItem>
Chip::Chip(const QColor &color, int x, int y)
{
this->x = x;
this->y = y;
this->color = color;
setZValue((x + y) % 2);
setFlags(ItemIsSelectable | ItemIsMovable);
setAcceptHoverEvents(true);
}
QRectF Chip::boundingRect() const
{
return QRectF(0, 0, 110, 70);
}
QPainterPath Chip::shape() const
{
QPainterPath path;
path.addRect(14, 14, 82, 42);
return path;
}
void Chip::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(widget);
QColor fillColor = (option->state & QStyle::State_Selected) ? color.darker(150) : color;
if (option->state & QStyle::State_MouseOver)
fillColor = fillColor.lighter(125);
const qreal lod = option->levelOfDetailFromTransform(painter->worldTransform());
if (lod < 0.2) {
if (lod < 0.125) {
painter->fillRect(QRectF(0, 0, 110, 70), fillColor);
return;
}
QBrush b = painter->brush();
painter->setBrush(fillColor);
painter->drawRect(13, 13, 97, 57);
painter->setBrush(b);
return;
}
QPen oldPen = painter->pen();
QPen pen = oldPen;
int width = 0;
if (option->state & QStyle::State_Selected)
width += 2;
pen.setWidth(width);
QBrush b = painter->brush();
painter->setBrush(QBrush(fillColor.darker(option->state & QStyle::State_Sunken ? 120 : 100)));
painter->drawRect(QRect(14, 14, 79, 39));
painter->setBrush(b);
if (lod >= 1) {
painter->setPen(QPen(Qt::gray, 1));
painter->drawLine(15, 54, 94, 54);
painter->drawLine(94, 53, 94, 15);
painter->setPen(QPen(Qt::black, 0));
}
// Draw text
if (lod >= 2) {
QFont font("Times", 10);
font.setStyleStrategy(QFont::ForceOutline);
painter->setFont(font);
painter->save();
painter->scale(0.1, 0.1);
painter->drawText(170, 180, QString("Model: VSC-2000 (Very Small Chip) at %1x%2").arg(x).arg(y));
painter->drawText(170, 200, QString("Serial number: DLWR-WEER-123L-ZZ33-SDSJ"));
painter->drawText(170, 220, QString("Manufacturer: Chip Manufacturer"));
painter->restore();
}
// Draw lines
QVarLengthArray<QLineF, 36> lines;
if (lod >= 0.5) {
for (int i = 0; i <= 10; i += (lod > 0.5 ? 1 : 2)) {
lines.append(QLineF(18 + 7 * i, 13, 18 + 7 * i, 5));
lines.append(QLineF(18 + 7 * i, 54, 18 + 7 * i, 62));
}
for (int i = 0; i <= 6; i += (lod > 0.5 ? 1 : 2)) {
lines.append(QLineF(5, 18 + i * 5, 13, 18 + i * 5));
lines.append(QLineF(94, 18 + i * 5, 102, 18 + i * 5));
}
}
if (lod >= 0.4) {
const QLineF lineData[] = {
QLineF(25, 35, 35, 35),
QLineF(35, 30, 35, 40),
QLineF(35, 30, 45, 35),
QLineF(35, 40, 45, 35),
QLineF(45, 30, 45, 40),
QLineF(45, 35, 55, 35)
};
lines.append(lineData, 6);
}
painter->drawLines(lines.data(), lines.size());
// Draw red ink
if (stuff.size() > 1) {
QPen p = painter->pen();
painter->setPen(QPen(Qt::red, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter->setBrush(Qt::NoBrush);
QPainterPath path;
path.moveTo(stuff.first());
for (int i = 1; i < stuff.size(); ++i)
path.lineTo(stuff.at(i));
painter->drawPath(path);
painter->setPen(p);
}
}
void Chip::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
QGraphicsItem::mousePressEvent(event);
update();
}
void Chip::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if (event->modifiers() & Qt::ShiftModifier) {
stuff << event->pos();
update();
return;
}
QGraphicsItem::mouseMoveEvent(event);
}
void Chip::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
QGraphicsItem::mouseReleaseEvent(event);
update();
}

View File

@ -0,0 +1,31 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef CHIP_H
#define CHIP_H
#include <QColor>
#include <QGraphicsItem>
class Chip : public QGraphicsItem
{
public:
Chip(const QColor &color, int x, int y);
QRectF boundingRect() const override;
QPainterPath shape() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget) override;
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
private:
int x;
int y;
QColor color;
QList<QPointF> stuff;
};
#endif // CHIP_H

View File

@ -0,0 +1,18 @@
RESOURCES += images.qrc
HEADERS += mainwindow.h view.h chip.h
SOURCES += main.cpp
SOURCES += mainwindow.cpp view.cpp chip.cpp
QT += widgets
qtHaveModule(printsupport): QT += printsupport
build_all:!build_pass {
CONFIG -= build_all
CONFIG += release
}
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/graphicsview/chip
INSTALLS += target

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,10 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>qt4logo.png</file>
<file>zoomin.png</file>
<file>zoomout.png</file>
<file>rotateleft.png</file>
<file>rotateright.png</file>
<file>fileprint.png</file>
</qresource>
</RCC>

View File

@ -0,0 +1,19 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
Q_INIT_RESOURCE(images);
QApplication app(argc, argv);
app.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
MainWindow window;
window.show();
return app.exec();
}

View File

@ -0,0 +1,65 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "chip.h"
#include "mainwindow.h"
#include "view.h"
#include <QHBoxLayout>
#include <QSplitter>
MainWindow::MainWindow(QWidget *parent)
: QWidget(parent), scene(new QGraphicsScene(this))
, h1Splitter(new QSplitter(this)), h2Splitter(new QSplitter(this))
{
populateScene();
QSplitter *vSplitter = new QSplitter;
vSplitter->setOrientation(Qt::Vertical);
vSplitter->addWidget(h1Splitter);
vSplitter->addWidget(h2Splitter);
View *view = new View("Top left view");
view->view()->setScene(scene);
h1Splitter->addWidget(view);
view = new View("Top right view");
view->view()->setScene(scene);
h1Splitter->addWidget(view);
view = new View("Bottom left view");
view->view()->setScene(scene);
h2Splitter->addWidget(view);
view = new View("Bottom right view");
view->view()->setScene(scene);
h2Splitter->addWidget(view);
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(vSplitter);
setLayout(layout);
setWindowTitle(tr("Chip Example"));
}
void MainWindow::populateScene()
{
QImage image(":/qt4logo.png");
// Populate scene
int xx = 0;
for (int i = -11000; i < 11000; i += 110) {
++xx;
int yy = 0;
for (int j = -7000; j < 7000; j += 70) {
++yy;
qreal x = (i + 11000) / 22000.0;
qreal y = (j + 7000) / 14000.0;
QColor color(image.pixel(int(image.width() * x), int(image.height() * y)));
QGraphicsItem *item = new Chip(color, xx, yy);
item->setPos(QPointF(i, j));
scene->addItem(item);
}
}
}

View File

@ -0,0 +1,29 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QWidget>
QT_BEGIN_NAMESPACE
class QGraphicsScene;
class QSplitter;
QT_END_NAMESPACE
class MainWindow : public QWidget
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
private:
void setupMatrix();
void populateScene();
QGraphicsScene *scene;
QSplitter *h1Splitter;
QSplitter *h2Splitter;
};
#endif // MAINWINDOW_H

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1,237 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "view.h"
#if defined(QT_PRINTSUPPORT_LIB)
#include <QtPrintSupport/qtprintsupportglobal.h>
#if QT_CONFIG(printdialog)
#include <QPrinter>
#include <QPrintDialog>
#endif
#endif
#include <QtWidgets>
#include <QtMath>
#if QT_CONFIG(wheelevent)
void GraphicsView::wheelEvent(QWheelEvent *e)
{
if (e->modifiers() & Qt::ControlModifier) {
if (e->angleDelta().y() > 0)
view->zoomInBy(6);
else
view->zoomOutBy(6);
e->accept();
} else {
QGraphicsView::wheelEvent(e);
}
}
#endif
View::View(const QString &name, QWidget *parent)
: QFrame(parent)
{
setFrameStyle(Sunken | StyledPanel);
graphicsView = new GraphicsView(this);
graphicsView->setRenderHint(QPainter::Antialiasing, false);
graphicsView->setDragMode(QGraphicsView::RubberBandDrag);
graphicsView->setOptimizationFlags(QGraphicsView::DontSavePainterState);
graphicsView->setViewportUpdateMode(QGraphicsView::SmartViewportUpdate);
graphicsView->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
int size = style()->pixelMetric(QStyle::PM_ToolBarIconSize);
QSize iconSize(size, size);
QToolButton *zoomInIcon = new QToolButton;
zoomInIcon->setAutoRepeat(true);
zoomInIcon->setAutoRepeatInterval(33);
zoomInIcon->setAutoRepeatDelay(0);
zoomInIcon->setIcon(QPixmap(":/zoomin.png"));
zoomInIcon->setIconSize(iconSize);
QToolButton *zoomOutIcon = new QToolButton;
zoomOutIcon->setAutoRepeat(true);
zoomOutIcon->setAutoRepeatInterval(33);
zoomOutIcon->setAutoRepeatDelay(0);
zoomOutIcon->setIcon(QPixmap(":/zoomout.png"));
zoomOutIcon->setIconSize(iconSize);
zoomSlider = new QSlider;
zoomSlider->setMinimum(0);
zoomSlider->setMaximum(500);
zoomSlider->setValue(250);
zoomSlider->setTickPosition(QSlider::TicksRight);
// Zoom slider layout
QVBoxLayout *zoomSliderLayout = new QVBoxLayout;
zoomSliderLayout->addWidget(zoomInIcon);
zoomSliderLayout->addWidget(zoomSlider);
zoomSliderLayout->addWidget(zoomOutIcon);
QToolButton *rotateLeftIcon = new QToolButton;
rotateLeftIcon->setIcon(QPixmap(":/rotateleft.png"));
rotateLeftIcon->setIconSize(iconSize);
QToolButton *rotateRightIcon = new QToolButton;
rotateRightIcon->setIcon(QPixmap(":/rotateright.png"));
rotateRightIcon->setIconSize(iconSize);
rotateSlider = new QSlider;
rotateSlider->setOrientation(Qt::Horizontal);
rotateSlider->setMinimum(-360);
rotateSlider->setMaximum(360);
rotateSlider->setValue(0);
rotateSlider->setTickPosition(QSlider::TicksBelow);
// Rotate slider layout
QHBoxLayout *rotateSliderLayout = new QHBoxLayout;
rotateSliderLayout->addWidget(rotateLeftIcon);
rotateSliderLayout->addWidget(rotateSlider);
rotateSliderLayout->addWidget(rotateRightIcon);
resetButton = new QToolButton;
resetButton->setText(tr("0"));
resetButton->setEnabled(false);
// Label layout
QHBoxLayout *labelLayout = new QHBoxLayout;
label = new QLabel(name);
label2 = new QLabel(tr("Pointer Mode"));
selectModeButton = new QToolButton;
selectModeButton->setText(tr("Select"));
selectModeButton->setCheckable(true);
selectModeButton->setChecked(true);
dragModeButton = new QToolButton;
dragModeButton->setText(tr("Drag"));
dragModeButton->setCheckable(true);
dragModeButton->setChecked(false);
antialiasButton = new QToolButton;
antialiasButton->setText(tr("Antialiasing"));
antialiasButton->setCheckable(true);
antialiasButton->setChecked(false);
printButton = new QToolButton;
printButton->setIcon(QIcon(QPixmap(":/fileprint.png")));
QButtonGroup *pointerModeGroup = new QButtonGroup(this);
pointerModeGroup->setExclusive(true);
pointerModeGroup->addButton(selectModeButton);
pointerModeGroup->addButton(dragModeButton);
labelLayout->addWidget(label);
labelLayout->addStretch();
labelLayout->addWidget(label2);
labelLayout->addWidget(selectModeButton);
labelLayout->addWidget(dragModeButton);
labelLayout->addStretch();
labelLayout->addWidget(antialiasButton);
labelLayout->addWidget(printButton);
QGridLayout *topLayout = new QGridLayout;
topLayout->addLayout(labelLayout, 0, 0);
topLayout->addWidget(graphicsView, 1, 0);
topLayout->addLayout(zoomSliderLayout, 1, 1);
topLayout->addLayout(rotateSliderLayout, 2, 0);
topLayout->addWidget(resetButton, 2, 1);
setLayout(topLayout);
connect(resetButton, &QAbstractButton::clicked, this, &View::resetView);
connect(zoomSlider, &QAbstractSlider::valueChanged, this, &View::setupMatrix);
connect(rotateSlider, &QAbstractSlider::valueChanged, this, &View::setupMatrix);
connect(graphicsView->verticalScrollBar(), &QAbstractSlider::valueChanged,
this, &View::setResetButtonEnabled);
connect(graphicsView->horizontalScrollBar(), &QAbstractSlider::valueChanged,
this, &View::setResetButtonEnabled);
connect(selectModeButton, &QAbstractButton::toggled, this, &View::togglePointerMode);
connect(dragModeButton, &QAbstractButton::toggled, this, &View::togglePointerMode);
connect(antialiasButton, &QAbstractButton::toggled, this, &View::toggleAntialiasing);
connect(rotateLeftIcon, &QAbstractButton::clicked, this, &View::rotateLeft);
connect(rotateRightIcon, &QAbstractButton::clicked, this, &View::rotateRight);
connect(zoomInIcon, &QAbstractButton::clicked, this, &View::zoomIn);
connect(zoomOutIcon, &QAbstractButton::clicked, this, &View::zoomOut);
connect(printButton, &QAbstractButton::clicked, this, &View::print);
setupMatrix();
}
QGraphicsView *View::view() const
{
return static_cast<QGraphicsView *>(graphicsView);
}
void View::resetView()
{
zoomSlider->setValue(250);
rotateSlider->setValue(0);
setupMatrix();
graphicsView->ensureVisible(QRectF(0, 0, 0, 0));
resetButton->setEnabled(false);
}
void View::setResetButtonEnabled()
{
resetButton->setEnabled(true);
}
void View::setupMatrix()
{
qreal scale = qPow(qreal(2), (zoomSlider->value() - 250) / qreal(50));
QTransform matrix;
matrix.scale(scale, scale);
matrix.rotate(rotateSlider->value());
graphicsView->setTransform(matrix);
setResetButtonEnabled();
}
void View::togglePointerMode()
{
graphicsView->setDragMode(selectModeButton->isChecked()
? QGraphicsView::RubberBandDrag
: QGraphicsView::ScrollHandDrag);
graphicsView->setInteractive(selectModeButton->isChecked());
}
void View::toggleAntialiasing()
{
graphicsView->setRenderHint(QPainter::Antialiasing, antialiasButton->isChecked());
}
void View::print()
{
#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printdialog)
QPrinter printer;
QPrintDialog dialog(&printer, this);
if (dialog.exec() == QDialog::Accepted) {
QPainter painter(&printer);
graphicsView->render(&painter);
}
#endif
}
void View::zoomIn()
{
zoomSlider->setValue(zoomSlider->value() + 1);
}
void View::zoomOut()
{
zoomSlider->setValue(zoomSlider->value() - 1);
}
void View::zoomInBy(int level)
{
zoomSlider->setValue(zoomSlider->value() + level);
}
void View::zoomOutBy(int level)
{
zoomSlider->setValue(zoomSlider->value() - level);
}
void View::rotateLeft()
{
rotateSlider->setValue(rotateSlider->value() - 10);
}
void View::rotateRight()
{
rotateSlider->setValue(rotateSlider->value() + 10);
}

View File

@ -0,0 +1,70 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef VIEW_H
#define VIEW_H
#include <QFrame>
#include <QGraphicsView>
QT_BEGIN_NAMESPACE
class QLabel;
class QSlider;
class QToolButton;
QT_END_NAMESPACE
class View;
class GraphicsView : public QGraphicsView
{
Q_OBJECT
public:
GraphicsView(View *v) : QGraphicsView(), view(v) { }
protected:
#if QT_CONFIG(wheelevent)
void wheelEvent(QWheelEvent *) override;
#endif
private:
View *view;
};
class View : public QFrame
{
Q_OBJECT
public:
explicit View(const QString &name, QWidget *parent = nullptr);
QGraphicsView *view() const;
public slots:
void zoomIn();
void zoomOut();
void zoomInBy(int level);
void zoomOutBy(int level);
private slots:
void resetView();
void setResetButtonEnabled();
void setupMatrix();
void togglePointerMode();
void toggleAntialiasing();
void print();
void rotateLeft();
void rotateRight();
private:
GraphicsView *graphicsView;
QLabel *label;
QLabel *label2;
QToolButton *selectModeButton;
QToolButton *dragModeButton;
QToolButton *antialiasButton;
QToolButton *printButton;
QToolButton *resetButton;
QSlider *zoomSlider;
QSlider *rotateSlider;
};
#endif // VIEW_H

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,49 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(collidingmice LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/graphicsview/collidingmice")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
qt_standard_project_setup()
qt_add_executable(collidingmice
main.cpp
mouse.cpp mouse.h
)
set_target_properties(collidingmice PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(collidingmice PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
# Resources:
set(mice_resource_files
"images/cheese.jpg"
)
qt_add_resources(collidingmice "mice"
PREFIX
"/"
FILES
${mice_resource_files}
)
install(TARGETS collidingmice
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -0,0 +1,14 @@
QT += widgets
HEADERS += \
mouse.h
SOURCES += \
main.cpp \
mouse.cpp
RESOURCES += \
mice.qrc
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/graphicsview/collidingmice
INSTALLS += target

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -0,0 +1,52 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtMath>
#include <QtWidgets>
#include "mouse.h"
static constexpr int MouseCount = 7;
//! [0]
int main(int argc, char **argv)
{
QApplication app(argc, argv);
//! [0]
//! [1]
QGraphicsScene scene;
scene.setSceneRect(-300, -300, 600, 600);
//! [1] //! [2]
scene.setItemIndexMethod(QGraphicsScene::NoIndex);
//! [2]
//! [3]
for (int i = 0; i < MouseCount; ++i) {
Mouse *mouse = new Mouse;
mouse->setPos(::sin((i * 6.28) / MouseCount) * 200,
::cos((i * 6.28) / MouseCount) * 200);
scene.addItem(mouse);
}
//! [3]
//! [4]
QGraphicsView view(&scene);
view.setRenderHint(QPainter::Antialiasing);
view.setBackgroundBrush(QPixmap(":/images/cheese.jpg"));
//! [4] //! [5]
view.setCacheMode(QGraphicsView::CacheBackground);
view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
view.setDragMode(QGraphicsView::ScrollHandDrag);
//! [5] //! [6]
view.setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Colliding Mice"));
view.resize(400, 300);
view.show();
QTimer timer;
QObject::connect(&timer, &QTimer::timeout, &scene, &QGraphicsScene::advance);
timer.start(1000 / 33);
return app.exec();
}
//! [6]

View File

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/" >
<file>images/cheese.jpg</file>
</qresource>
</RCC>

View File

@ -0,0 +1,160 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "mouse.h"
#include <QGraphicsScene>
#include <QPainter>
#include <QRandomGenerator>
#include <QStyleOption>
#include <QtMath>
constexpr qreal Pi = M_PI;
constexpr qreal TwoPi = 2 * M_PI;
static qreal normalizeAngle(qreal angle)
{
while (angle < 0)
angle += TwoPi;
while (angle > TwoPi)
angle -= TwoPi;
return angle;
}
//! [0]
Mouse::Mouse() : color(QRandomGenerator::global()->bounded(256),
QRandomGenerator::global()->bounded(256),
QRandomGenerator::global()->bounded(256))
{
setRotation(QRandomGenerator::global()->bounded(360 * 16));
}
//! [0]
//! [1]
QRectF Mouse::boundingRect() const
{
qreal adjust = 0.5;
return QRectF(-18 - adjust, -22 - adjust,
36 + adjust, 60 + adjust);
}
//! [1]
//! [2]
QPainterPath Mouse::shape() const
{
QPainterPath path;
path.addRect(-10, -20, 20, 40);
return path;
}
//! [2]
//! [3]
void Mouse::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
{
// Body
painter->setBrush(color);
painter->drawEllipse(-10, -20, 20, 40);
// Eyes
painter->setBrush(Qt::white);
painter->drawEllipse(-10, -17, 8, 8);
painter->drawEllipse(2, -17, 8, 8);
// Nose
painter->setBrush(Qt::black);
painter->drawEllipse(QRectF(-2, -22, 4, 4));
// Pupils
painter->drawEllipse(QRectF(-8.0 + mouseEyeDirection, -17, 4, 4));
painter->drawEllipse(QRectF(4.0 + mouseEyeDirection, -17, 4, 4));
// Ears
painter->setBrush(scene()->collidingItems(this).isEmpty() ? Qt::darkYellow : Qt::red);
painter->drawEllipse(-17, -12, 16, 16);
painter->drawEllipse(1, -12, 16, 16);
// Tail
QPainterPath path(QPointF(0, 20));
path.cubicTo(-5, 22, -5, 22, 0, 25);
path.cubicTo(5, 27, 5, 32, 0, 30);
path.cubicTo(-5, 32, -5, 42, 0, 35);
painter->setBrush(Qt::NoBrush);
painter->drawPath(path);
}
//! [3]
//! [4]
void Mouse::advance(int step)
{
if (!step)
return;
//! [4]
// Don't move too far away
//! [5]
QLineF lineToCenter(QPointF(0, 0), mapFromScene(0, 0));
if (lineToCenter.length() > 150) {
qreal angleToCenter = std::atan2(lineToCenter.dy(), lineToCenter.dx());
angleToCenter = normalizeAngle((Pi - angleToCenter) + Pi / 2);
if (angleToCenter < Pi && angleToCenter > Pi / 4) {
// Rotate left
angle += (angle < -Pi / 2) ? 0.25 : -0.25;
} else if (angleToCenter >= Pi && angleToCenter < (Pi + Pi / 2 + Pi / 4)) {
// Rotate right
angle += (angle < Pi / 2) ? 0.25 : -0.25;
}
} else if (::sin(angle) < 0) {
angle += 0.25;
} else if (::sin(angle) > 0) {
angle -= 0.25;
//! [5] //! [6]
}
//! [6]
// Try not to crash with any other mice
//! [7]
const QList<QGraphicsItem *> dangerMice = scene()->items(QPolygonF()
<< mapToScene(0, 0)
<< mapToScene(-30, -50)
<< mapToScene(30, -50));
for (const QGraphicsItem *item : dangerMice) {
if (item == this)
continue;
QLineF lineToMouse(QPointF(0, 0), mapFromItem(item, 0, 0));
qreal angleToMouse = std::atan2(lineToMouse.dy(), lineToMouse.dx());
angleToMouse = normalizeAngle((Pi - angleToMouse) + Pi / 2);
if (angleToMouse >= 0 && angleToMouse < Pi / 2) {
// Rotate right
angle += 0.5;
} else if (angleToMouse <= TwoPi && angleToMouse > (TwoPi - Pi / 2)) {
// Rotate left
angle -= 0.5;
//! [7] //! [8]
}
//! [8] //! [9]
}
//! [9]
// Add some random movement
//! [10]
if (dangerMice.size() > 1 && QRandomGenerator::global()->bounded(10) == 0) {
if (QRandomGenerator::global()->bounded(1))
angle += QRandomGenerator::global()->bounded(1 / 500.0);
else
angle -= QRandomGenerator::global()->bounded(1 / 500.0);
}
//! [10]
//! [11]
speed += (-50 + QRandomGenerator::global()->bounded(100)) / 100.0;
qreal dx = ::sin(angle) * 10;
mouseEyeDirection = (qAbs(dx / 5) < 1) ? 0 : dx / 5;
setRotation(rotation() + dx);
setPos(mapToParent(0, -(3 + sin(speed) * 3)));
}
//! [11]

View File

@ -0,0 +1,31 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef MOUSE_H
#define MOUSE_H
#include <QGraphicsItem>
//! [0]
class Mouse : public QGraphicsItem
{
public:
Mouse();
QRectF boundingRect() const override;
QPainterPath shape() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget) override;
protected:
void advance(int step) override;
private:
qreal angle = 0;
qreal speed = 0;
qreal mouseEyeDirection = 0;
QColor color;
};
//! [0]
#endif

View File

@ -0,0 +1,67 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(diagramscene LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/graphicsview/diagramscene")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
qt_standard_project_setup()
qt_add_executable(diagramscene
arrow.cpp arrow.h
diagramitem.cpp diagramitem.h
diagramscene.cpp diagramscene.h
diagramtextitem.cpp diagramtextitem.h
main.cpp
mainwindow.cpp mainwindow.h
)
set_target_properties(diagramscene PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(diagramscene PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
# Resources:
set(diagramscene_resource_files
"images/background1.png"
"images/background2.png"
"images/background3.png"
"images/background4.png"
"images/bold.png"
"images/bringtofront.png"
"images/delete.png"
"images/floodfill.png"
"images/italic.png"
"images/linecolor.png"
"images/linepointer.png"
"images/pointer.png"
"images/sendtoback.png"
"images/textpointer.png"
"images/underline.png"
)
qt_add_resources(diagramscene "diagramscene"
PREFIX
"/"
FILES
${diagramscene_resource_files}
)
install(TARGETS diagramscene
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -0,0 +1,102 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "arrow.h"
#include "diagramitem.h"
#include <QPainter>
#include <QPen>
#include <QtMath>
//! [0]
Arrow::Arrow(DiagramItem *startItem, DiagramItem *endItem, QGraphicsItem *parent)
: QGraphicsLineItem(parent), myStartItem(startItem), myEndItem(endItem)
{
setFlag(QGraphicsItem::ItemIsSelectable, true);
setPen(QPen(myColor, 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
}
//! [0]
//! [1]
QRectF Arrow::boundingRect() const
{
qreal extra = (pen().width() + 20) / 2.0;
return QRectF(line().p1(), QSizeF(line().p2().x() - line().p1().x(),
line().p2().y() - line().p1().y()))
.normalized()
.adjusted(-extra, -extra, extra, extra);
}
//! [1]
//! [2]
QPainterPath Arrow::shape() const
{
QPainterPath path = QGraphicsLineItem::shape();
path.addPolygon(arrowHead);
return path;
}
//! [2]
//! [3]
void Arrow::updatePosition()
{
QLineF line(mapFromItem(myStartItem, 0, 0), mapFromItem(myEndItem, 0, 0));
setLine(line);
}
//! [3]
//! [4]
void Arrow::paint(QPainter *painter, const QStyleOptionGraphicsItem *,
QWidget *)
{
if (myStartItem->collidesWithItem(myEndItem))
return;
QPen myPen = pen();
myPen.setColor(myColor);
qreal arrowSize = 20;
painter->setPen(myPen);
painter->setBrush(myColor);
//! [4] //! [5]
QLineF centerLine(myStartItem->pos(), myEndItem->pos());
QPolygonF endPolygon = myEndItem->polygon();
QPointF p1 = endPolygon.first() + myEndItem->pos();
QPointF intersectPoint;
for (int i = 1; i < endPolygon.count(); ++i) {
QPointF p2 = endPolygon.at(i) + myEndItem->pos();
QLineF polyLine = QLineF(p1, p2);
QLineF::IntersectionType intersectionType =
polyLine.intersects(centerLine, &intersectPoint);
if (intersectionType == QLineF::BoundedIntersection)
break;
p1 = p2;
}
setLine(QLineF(intersectPoint, myStartItem->pos()));
//! [5] //! [6]
double angle = std::atan2(-line().dy(), line().dx());
QPointF arrowP1 = line().p1() + QPointF(sin(angle + M_PI / 3) * arrowSize,
cos(angle + M_PI / 3) * arrowSize);
QPointF arrowP2 = line().p1() + QPointF(sin(angle + M_PI - M_PI / 3) * arrowSize,
cos(angle + M_PI - M_PI / 3) * arrowSize);
arrowHead.clear();
arrowHead << line().p1() << arrowP1 << arrowP2;
//! [6] //! [7]
painter->drawLine(line());
painter->drawPolygon(arrowHead);
if (isSelected()) {
painter->setPen(QPen(myColor, 1, Qt::DashLine));
QLineF myLine = line();
myLine.translate(0, 4.0);
painter->drawLine(myLine);
myLine.translate(0,-8.0);
painter->drawLine(myLine);
}
}
//! [7]

View File

@ -0,0 +1,41 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef ARROW_H
#define ARROW_H
#include <QGraphicsLineItem>
class DiagramItem;
//! [0]
class Arrow : public QGraphicsLineItem
{
public:
enum { Type = UserType + 4 };
Arrow(DiagramItem *startItem, DiagramItem *endItem,
QGraphicsItem *parent = nullptr);
int type() const override { return Type; }
QRectF boundingRect() const override;
QPainterPath shape() const override;
void setColor(const QColor &color) { myColor = color; }
DiagramItem *startItem() const { return myStartItem; }
DiagramItem *endItem() const { return myEndItem; }
void updatePosition();
protected:
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget = nullptr) override;
private:
DiagramItem *myStartItem;
DiagramItem *myEndItem;
QPolygonF arrowHead;
QColor myColor = Qt::black;
};
//! [0]
#endif // ARROW_H

View File

@ -0,0 +1,114 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "diagramitem.h"
#include "arrow.h"
#include <QGraphicsScene>
#include <QGraphicsSceneContextMenuEvent>
#include <QMenu>
#include <QPainter>
//! [0]
DiagramItem::DiagramItem(DiagramType diagramType, QMenu *contextMenu,
QGraphicsItem *parent)
: QGraphicsPolygonItem(parent), myDiagramType(diagramType)
, myContextMenu(contextMenu)
{
QPainterPath path;
switch (myDiagramType) {
case StartEnd:
path.moveTo(200, 50);
path.arcTo(150, 0, 50, 50, 0, 90);
path.arcTo(50, 0, 50, 50, 90, 90);
path.arcTo(50, 50, 50, 50, 180, 90);
path.arcTo(150, 50, 50, 50, 270, 90);
path.lineTo(200, 25);
myPolygon = path.toFillPolygon();
break;
case Conditional:
myPolygon << QPointF(-100, 0) << QPointF(0, 100)
<< QPointF(100, 0) << QPointF(0, -100)
<< QPointF(-100, 0);
break;
case Step:
myPolygon << QPointF(-100, -100) << QPointF(100, -100)
<< QPointF(100, 100) << QPointF(-100, 100)
<< QPointF(-100, -100);
break;
default:
myPolygon << QPointF(-120, -80) << QPointF(-70, 80)
<< QPointF(120, 80) << QPointF(70, -80)
<< QPointF(-120, -80);
break;
}
setPolygon(myPolygon);
setFlag(QGraphicsItem::ItemIsMovable, true);
setFlag(QGraphicsItem::ItemIsSelectable, true);
setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
}
//! [0]
//! [1]
void DiagramItem::removeArrow(Arrow *arrow)
{
arrows.removeAll(arrow);
}
//! [1]
//! [2]
void DiagramItem::removeArrows()
{
// need a copy here since removeArrow() will
// modify the arrows container
const auto arrowsCopy = arrows;
for (Arrow *arrow : arrowsCopy) {
arrow->startItem()->removeArrow(arrow);
arrow->endItem()->removeArrow(arrow);
scene()->removeItem(arrow);
delete arrow;
}
}
//! [2]
//! [3]
void DiagramItem::addArrow(Arrow *arrow)
{
arrows.append(arrow);
}
//! [3]
//! [4]
QPixmap DiagramItem::image() const
{
QPixmap pixmap(250, 250);
pixmap.fill(Qt::transparent);
QPainter painter(&pixmap);
painter.setPen(QPen(Qt::black, 8));
painter.translate(125, 125);
painter.drawPolyline(myPolygon);
return pixmap;
}
//! [4]
//! [5]
void DiagramItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
{
scene()->clearSelection();
setSelected(true);
myContextMenu->popup(event->screenPos());
}
//! [5]
//! [6]
QVariant DiagramItem::itemChange(GraphicsItemChange change, const QVariant &value)
{
if (change == QGraphicsItem::ItemPositionChange) {
for (Arrow *arrow : std::as_const(arrows))
arrow->updatePosition();
}
return value;
}
//! [6]

View File

@ -0,0 +1,48 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef DIAGRAMITEM_H
#define DIAGRAMITEM_H
#include <QGraphicsPixmapItem>
#include <QList>
QT_BEGIN_NAMESPACE
class QPixmap;
class QGraphicsSceneContextMenuEvent;
class QMenu;
class QPolygonF;
QT_END_NAMESPACE
class Arrow;
//! [0]
class DiagramItem : public QGraphicsPolygonItem
{
public:
enum { Type = UserType + 15 };
enum DiagramType { Step, Conditional, StartEnd, Io };
DiagramItem(DiagramType diagramType, QMenu *contextMenu, QGraphicsItem *parent = nullptr);
void removeArrow(Arrow *arrow);
void removeArrows();
DiagramType diagramType() const { return myDiagramType; }
QPolygonF polygon() const { return myPolygon; }
void addArrow(Arrow *arrow);
QPixmap image() const;
int type() const override { return Type; }
protected:
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
private:
DiagramType myDiagramType;
QPolygonF myPolygon;
QMenu *myContextMenu;
QList<Arrow *> arrows;
};
//! [0]
#endif // DIAGRAMITEM_H

View File

@ -0,0 +1,196 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "diagramscene.h"
#include "arrow.h"
#include <QGraphicsSceneMouseEvent>
#include <QTextCursor>
//! [0]
DiagramScene::DiagramScene(QMenu *itemMenu, QObject *parent)
: QGraphicsScene(parent)
{
myItemMenu = itemMenu;
myMode = MoveItem;
myItemType = DiagramItem::Step;
line = nullptr;
textItem = nullptr;
myItemColor = Qt::white;
myTextColor = Qt::black;
myLineColor = Qt::black;
}
//! [0]
//! [1]
void DiagramScene::setLineColor(const QColor &color)
{
myLineColor = color;
if (isItemChange(Arrow::Type)) {
Arrow *item = qgraphicsitem_cast<Arrow *>(selectedItems().first());
item->setColor(myLineColor);
update();
}
}
//! [1]
//! [2]
void DiagramScene::setTextColor(const QColor &color)
{
myTextColor = color;
if (isItemChange(DiagramTextItem::Type)) {
DiagramTextItem *item = qgraphicsitem_cast<DiagramTextItem *>(selectedItems().first());
item->setDefaultTextColor(myTextColor);
}
}
//! [2]
//! [3]
void DiagramScene::setItemColor(const QColor &color)
{
myItemColor = color;
if (isItemChange(DiagramItem::Type)) {
DiagramItem *item = qgraphicsitem_cast<DiagramItem *>(selectedItems().first());
item->setBrush(myItemColor);
}
}
//! [3]
//! [4]
void DiagramScene::setFont(const QFont &font)
{
myFont = font;
if (isItemChange(DiagramTextItem::Type)) {
QGraphicsTextItem *item = qgraphicsitem_cast<DiagramTextItem *>(selectedItems().first());
//At this point the selection can change so the first selected item might not be a DiagramTextItem
if (item)
item->setFont(myFont);
}
}
//! [4]
void DiagramScene::setMode(Mode mode)
{
myMode = mode;
}
void DiagramScene::setItemType(DiagramItem::DiagramType type)
{
myItemType = type;
}
//! [5]
void DiagramScene::editorLostFocus(DiagramTextItem *item)
{
QTextCursor cursor = item->textCursor();
cursor.clearSelection();
item->setTextCursor(cursor);
if (item->toPlainText().isEmpty()) {
removeItem(item);
item->deleteLater();
}
}
//! [5]
//! [6]
void DiagramScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
if (mouseEvent->button() != Qt::LeftButton)
return;
DiagramItem *item;
switch (myMode) {
case InsertItem:
item = new DiagramItem(myItemType, myItemMenu);
item->setBrush(myItemColor);
addItem(item);
item->setPos(mouseEvent->scenePos());
emit itemInserted(item);
break;
//! [6] //! [7]
case InsertLine:
line = new QGraphicsLineItem(QLineF(mouseEvent->scenePos(),
mouseEvent->scenePos()));
line->setPen(QPen(myLineColor, 2));
addItem(line);
break;
//! [7] //! [8]
case InsertText:
textItem = new DiagramTextItem();
textItem->setFont(myFont);
textItem->setTextInteractionFlags(Qt::TextEditorInteraction);
textItem->setZValue(1000.0);
connect(textItem, &DiagramTextItem::lostFocus,
this, &DiagramScene::editorLostFocus);
connect(textItem, &DiagramTextItem::selectedChange,
this, &DiagramScene::itemSelected);
addItem(textItem);
textItem->setDefaultTextColor(myTextColor);
textItem->setPos(mouseEvent->scenePos());
emit textInserted(textItem);
//! [8] //! [9]
default:
;
}
QGraphicsScene::mousePressEvent(mouseEvent);
}
//! [9]
//! [10]
void DiagramScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
if (myMode == InsertLine && line != nullptr) {
QLineF newLine(line->line().p1(), mouseEvent->scenePos());
line->setLine(newLine);
} else if (myMode == MoveItem) {
QGraphicsScene::mouseMoveEvent(mouseEvent);
}
}
//! [10]
//! [11]
void DiagramScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
if (line != nullptr && myMode == InsertLine) {
QList<QGraphicsItem *> startItems = items(line->line().p1());
if (startItems.count() && startItems.first() == line)
startItems.removeFirst();
QList<QGraphicsItem *> endItems = items(line->line().p2());
if (endItems.count() && endItems.first() == line)
endItems.removeFirst();
removeItem(line);
delete line;
//! [11] //! [12]
if (startItems.count() > 0 && endItems.count() > 0 &&
startItems.first()->type() == DiagramItem::Type &&
endItems.first()->type() == DiagramItem::Type &&
startItems.first() != endItems.first()) {
DiagramItem *startItem = qgraphicsitem_cast<DiagramItem *>(startItems.first());
DiagramItem *endItem = qgraphicsitem_cast<DiagramItem *>(endItems.first());
Arrow *arrow = new Arrow(startItem, endItem);
arrow->setColor(myLineColor);
startItem->addArrow(arrow);
endItem->addArrow(arrow);
arrow->setZValue(-1000.0);
addItem(arrow);
arrow->updatePosition();
}
}
//! [12] //! [13]
line = nullptr;
QGraphicsScene::mouseReleaseEvent(mouseEvent);
}
//! [13]
//! [14]
bool DiagramScene::isItemChange(int type) const
{
const QList<QGraphicsItem *> items = selectedItems();
const auto cb = [type](const QGraphicsItem *item) { return item->type() == type; };
return std::find_if(items.begin(), items.end(), cb) != items.end();
}
//! [14]

View File

@ -0,0 +1,72 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef DIAGRAMSCENE_H
#define DIAGRAMSCENE_H
#include "diagramitem.h"
#include "diagramtextitem.h"
#include <QGraphicsScene>
QT_BEGIN_NAMESPACE
class QGraphicsSceneMouseEvent;
class QMenu;
class QPointF;
class QGraphicsLineItem;
class QFont;
class QGraphicsTextItem;
class QColor;
QT_END_NAMESPACE
//! [0]
class DiagramScene : public QGraphicsScene
{
Q_OBJECT
public:
enum Mode { InsertItem, InsertLine, InsertText, MoveItem };
explicit DiagramScene(QMenu *itemMenu, QObject *parent = nullptr);
QFont font() const { return myFont; }
QColor textColor() const { return myTextColor; }
QColor itemColor() const { return myItemColor; }
QColor lineColor() const { return myLineColor; }
void setLineColor(const QColor &color);
void setTextColor(const QColor &color);
void setItemColor(const QColor &color);
void setFont(const QFont &font);
public slots:
void setMode(Mode mode);
void setItemType(DiagramItem::DiagramType type);
void editorLostFocus(DiagramTextItem *item);
signals:
void itemInserted(DiagramItem *item);
void textInserted(QGraphicsTextItem *item);
void itemSelected(QGraphicsItem *item);
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent) override;
private:
bool isItemChange(int type) const;
DiagramItem::DiagramType myItemType;
QMenu *myItemMenu;
Mode myMode;
bool leftButtonDown;
QPointF startPoint;
QGraphicsLineItem *line;
QFont myFont;
DiagramTextItem *textItem;
QColor myTextColor;
QColor myItemColor;
QColor myLineColor;
};
//! [0]
#endif // DIAGRAMSCENE_H

View File

@ -0,0 +1,20 @@
QT += widgets
requires(qtConfig(fontcombobox))
HEADERS = mainwindow.h \
diagramitem.h \
diagramscene.h \
arrow.h \
diagramtextitem.h
SOURCES = mainwindow.cpp \
diagramitem.cpp \
main.cpp \
arrow.cpp \
diagramtextitem.cpp \
diagramscene.cpp
RESOURCES = diagramscene.qrc
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/graphicsview/diagramscene
INSTALLS += target

View File

@ -0,0 +1,20 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>images/pointer.png</file>
<file>images/linepointer.png</file>
<file>images/textpointer.png</file>
<file>images/bold.png</file>
<file>images/italic.png</file>
<file>images/underline.png</file>
<file>images/floodfill.png</file>
<file>images/bringtofront.png</file>
<file>images/delete.png</file>
<file>images/sendtoback.png</file>
<file>images/linecolor.png</file>
<file>images/background1.png</file>
<file>images/background2.png</file>
<file>images/background3.png</file>
<file>images/background4.png</file>
</qresource>
</RCC>

View File

@ -0,0 +1,42 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "diagramtextitem.h"
#include "diagramscene.h"
//! [0]
DiagramTextItem::DiagramTextItem(QGraphicsItem *parent)
: QGraphicsTextItem(parent)
{
setFlag(QGraphicsItem::ItemIsMovable);
setFlag(QGraphicsItem::ItemIsSelectable);
}
//! [0]
//! [1]
QVariant DiagramTextItem::itemChange(GraphicsItemChange change,
const QVariant &value)
{
if (change == QGraphicsItem::ItemSelectedHasChanged)
emit selectedChange(this);
return value;
}
//! [1]
//! [2]
void DiagramTextItem::focusOutEvent(QFocusEvent *event)
{
setTextInteractionFlags(Qt::NoTextInteraction);
emit lostFocus(this);
QGraphicsTextItem::focusOutEvent(event);
}
//! [2]
//! [5]
void DiagramTextItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
{
if (textInteractionFlags() == Qt::NoTextInteraction)
setTextInteractionFlags(Qt::TextEditorInteraction);
QGraphicsTextItem::mouseDoubleClickEvent(event);
}
//! [5]

View File

@ -0,0 +1,36 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef DIAGRAMTEXTITEM_H
#define DIAGRAMTEXTITEM_H
#include <QGraphicsTextItem>
QT_BEGIN_NAMESPACE
class QGraphicsSceneMouseEvent;
QT_END_NAMESPACE
//! [0]
class DiagramTextItem : public QGraphicsTextItem
{
Q_OBJECT
public:
enum { Type = UserType + 3 };
DiagramTextItem(QGraphicsItem *parent = nullptr);
int type() const override { return Type; }
signals:
void lostFocus(DiagramTextItem *item);
void selectedChange(QGraphicsItem *item);
protected:
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
void focusOutEvent(QFocusEvent *event) override;
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override;
};
//! [0]
#endif // DIAGRAMTEXTITEM_H

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 831 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 893 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 B

View File

@ -0,0 +1,18 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "mainwindow.h"
#include <QApplication>
int main(int argv, char *args[])
{
Q_INIT_RESOURCE(diagramscene);
QApplication app(argv, args);
MainWindow mainWindow;
mainWindow.setGeometry(100, 100, 800, 500);
mainWindow.show();
return app.exec();
}

View File

@ -0,0 +1,599 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "arrow.h"
#include "diagramitem.h"
#include "diagramscene.h"
#include "diagramtextitem.h"
#include "mainwindow.h"
#include <QtWidgets>
const int InsertTextButton = 10;
//! [0]
MainWindow::MainWindow()
{
createActions();
createToolBox();
createMenus();
scene = new DiagramScene(itemMenu, this);
scene->setSceneRect(QRectF(0, 0, 5000, 5000));
connect(scene, &DiagramScene::itemInserted,
this, &MainWindow::itemInserted);
connect(scene, &DiagramScene::textInserted,
this, &MainWindow::textInserted);
connect(scene, &DiagramScene::itemSelected,
this, &MainWindow::itemSelected);
createToolbars();
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(toolBox);
view = new QGraphicsView(scene);
layout->addWidget(view);
QWidget *widget = new QWidget;
widget->setLayout(layout);
setCentralWidget(widget);
setWindowTitle(tr("Diagramscene"));
setUnifiedTitleAndToolBarOnMac(true);
}
//! [0]
//! [1]
void MainWindow::backgroundButtonGroupClicked(QAbstractButton *button)
{
const QList<QAbstractButton *> buttons = backgroundButtonGroup->buttons();
for (QAbstractButton *myButton : buttons) {
if (myButton != button)
button->setChecked(false);
}
QString text = button->text();
if (text == tr("Blue Grid"))
scene->setBackgroundBrush(QPixmap(":/images/background1.png"));
else if (text == tr("White Grid"))
scene->setBackgroundBrush(QPixmap(":/images/background2.png"));
else if (text == tr("Gray Grid"))
scene->setBackgroundBrush(QPixmap(":/images/background3.png"));
else
scene->setBackgroundBrush(QPixmap(":/images/background4.png"));
scene->update();
view->update();
}
//! [1]
//! [2]
void MainWindow::buttonGroupClicked(QAbstractButton *button)
{
const QList<QAbstractButton *> buttons = buttonGroup->buttons();
for (QAbstractButton *myButton : buttons) {
if (myButton != button)
button->setChecked(false);
}
const int id = buttonGroup->id(button);
if (id == InsertTextButton) {
scene->setMode(DiagramScene::InsertText);
} else {
scene->setItemType(DiagramItem::DiagramType(id));
scene->setMode(DiagramScene::InsertItem);
}
}
//! [2]
//! [3]
void MainWindow::deleteItem()
{
QList<QGraphicsItem *> selectedItems = scene->selectedItems();
for (QGraphicsItem *item : std::as_const(selectedItems)) {
if (item->type() == Arrow::Type) {
scene->removeItem(item);
Arrow *arrow = qgraphicsitem_cast<Arrow *>(item);
arrow->startItem()->removeArrow(arrow);
arrow->endItem()->removeArrow(arrow);
delete item;
}
}
selectedItems = scene->selectedItems();
for (QGraphicsItem *item : std::as_const(selectedItems)) {
if (item->type() == DiagramItem::Type)
qgraphicsitem_cast<DiagramItem *>(item)->removeArrows();
scene->removeItem(item);
delete item;
}
}
//! [3]
//! [4]
void MainWindow::pointerGroupClicked()
{
scene->setMode(DiagramScene::Mode(pointerTypeGroup->checkedId()));
}
//! [4]
//! [5]
void MainWindow::bringToFront()
{
if (scene->selectedItems().isEmpty())
return;
QGraphicsItem *selectedItem = scene->selectedItems().first();
const QList<QGraphicsItem *> overlapItems = selectedItem->collidingItems();
qreal zValue = 0;
for (const QGraphicsItem *item : overlapItems) {
if (item->zValue() >= zValue && item->type() == DiagramItem::Type)
zValue = item->zValue() + 0.1;
}
selectedItem->setZValue(zValue);
}
//! [5]
//! [6]
void MainWindow::sendToBack()
{
if (scene->selectedItems().isEmpty())
return;
QGraphicsItem *selectedItem = scene->selectedItems().first();
const QList<QGraphicsItem *> overlapItems = selectedItem->collidingItems();
qreal zValue = 0;
for (const QGraphicsItem *item : overlapItems) {
if (item->zValue() <= zValue && item->type() == DiagramItem::Type)
zValue = item->zValue() - 0.1;
}
selectedItem->setZValue(zValue);
}
//! [6]
//! [7]
void MainWindow::itemInserted(DiagramItem *item)
{
pointerTypeGroup->button(int(DiagramScene::MoveItem))->setChecked(true);
scene->setMode(DiagramScene::Mode(pointerTypeGroup->checkedId()));
buttonGroup->button(int(item->diagramType()))->setChecked(false);
}
//! [7]
//! [8]
void MainWindow::textInserted(QGraphicsTextItem *)
{
buttonGroup->button(InsertTextButton)->setChecked(false);
scene->setMode(DiagramScene::Mode(pointerTypeGroup->checkedId()));
}
//! [8]
//! [9]
void MainWindow::currentFontChanged(const QFont &)
{
handleFontChange();
}
//! [9]
//! [10]
void MainWindow::fontSizeChanged(const QString &)
{
handleFontChange();
}
//! [10]
//! [11]
void MainWindow::sceneScaleChanged(const QString &scale)
{
double newScale = scale.left(scale.indexOf(tr("%"))).toDouble() / 100.0;
QTransform oldMatrix = view->transform();
view->resetTransform();
view->translate(oldMatrix.dx(), oldMatrix.dy());
view->scale(newScale, newScale);
}
//! [11]
//! [12]
void MainWindow::textColorChanged()
{
textAction = qobject_cast<QAction *>(sender());
fontColorToolButton->setIcon(createColorToolButtonIcon(
":/images/textpointer.png",
qvariant_cast<QColor>(textAction->data())));
textButtonTriggered();
}
//! [12]
//! [13]
void MainWindow::itemColorChanged()
{
fillAction = qobject_cast<QAction *>(sender());
fillColorToolButton->setIcon(createColorToolButtonIcon(
":/images/floodfill.png",
qvariant_cast<QColor>(fillAction->data())));
fillButtonTriggered();
}
//! [13]
//! [14]
void MainWindow::lineColorChanged()
{
lineAction = qobject_cast<QAction *>(sender());
lineColorToolButton->setIcon(createColorToolButtonIcon(
":/images/linecolor.png",
qvariant_cast<QColor>(lineAction->data())));
lineButtonTriggered();
}
//! [14]
//! [15]
void MainWindow::textButtonTriggered()
{
scene->setTextColor(qvariant_cast<QColor>(textAction->data()));
}
//! [15]
//! [16]
void MainWindow::fillButtonTriggered()
{
scene->setItemColor(qvariant_cast<QColor>(fillAction->data()));
}
//! [16]
//! [17]
void MainWindow::lineButtonTriggered()
{
scene->setLineColor(qvariant_cast<QColor>(lineAction->data()));
}
//! [17]
//! [18]
void MainWindow::handleFontChange()
{
QFont font = fontCombo->currentFont();
font.setPointSize(fontSizeCombo->currentText().toInt());
font.setWeight(boldAction->isChecked() ? QFont::Bold : QFont::Normal);
font.setItalic(italicAction->isChecked());
font.setUnderline(underlineAction->isChecked());
scene->setFont(font);
}
//! [18]
//! [19]
void MainWindow::itemSelected(QGraphicsItem *item)
{
DiagramTextItem *textItem =
qgraphicsitem_cast<DiagramTextItem *>(item);
QFont font = textItem->font();
fontCombo->setCurrentFont(font);
fontSizeCombo->setEditText(QString().setNum(font.pointSize()));
boldAction->setChecked(font.weight() == QFont::Bold);
italicAction->setChecked(font.italic());
underlineAction->setChecked(font.underline());
}
//! [19]
//! [20]
void MainWindow::about()
{
QMessageBox::about(this, tr("About Diagram Scene"),
tr("The <b>Diagram Scene</b> example shows "
"use of the graphics framework."));
}
//! [20]
//! [21]
void MainWindow::createToolBox()
{
buttonGroup = new QButtonGroup(this);
buttonGroup->setExclusive(false);
connect(buttonGroup, QOverload<QAbstractButton *>::of(&QButtonGroup::buttonClicked),
this, &MainWindow::buttonGroupClicked);
QGridLayout *layout = new QGridLayout;
layout->addWidget(createCellWidget(tr("Conditional"), DiagramItem::Conditional), 0, 0);
layout->addWidget(createCellWidget(tr("Process"), DiagramItem::Step),0, 1);
layout->addWidget(createCellWidget(tr("Input/Output"), DiagramItem::Io), 1, 0);
//! [21]
QToolButton *textButton = new QToolButton;
textButton->setCheckable(true);
buttonGroup->addButton(textButton, InsertTextButton);
textButton->setIcon(QIcon(QPixmap(":/images/textpointer.png")));
textButton->setIconSize(QSize(50, 50));
QGridLayout *textLayout = new QGridLayout;
textLayout->addWidget(textButton, 0, 0, Qt::AlignHCenter);
textLayout->addWidget(new QLabel(tr("Text")), 1, 0, Qt::AlignCenter);
QWidget *textWidget = new QWidget;
textWidget->setLayout(textLayout);
layout->addWidget(textWidget, 1, 1);
layout->setRowStretch(3, 10);
layout->setColumnStretch(2, 10);
QWidget *itemWidget = new QWidget;
itemWidget->setLayout(layout);
backgroundButtonGroup = new QButtonGroup(this);
connect(backgroundButtonGroup, QOverload<QAbstractButton *>::of(&QButtonGroup::buttonClicked),
this, &MainWindow::backgroundButtonGroupClicked);
QGridLayout *backgroundLayout = new QGridLayout;
backgroundLayout->addWidget(createBackgroundCellWidget(tr("Blue Grid"),
":/images/background1.png"), 0, 0);
backgroundLayout->addWidget(createBackgroundCellWidget(tr("White Grid"),
":/images/background2.png"), 0, 1);
backgroundLayout->addWidget(createBackgroundCellWidget(tr("Gray Grid"),
":/images/background3.png"), 1, 0);
backgroundLayout->addWidget(createBackgroundCellWidget(tr("No Grid"),
":/images/background4.png"), 1, 1);
backgroundLayout->setRowStretch(2, 10);
backgroundLayout->setColumnStretch(2, 10);
QWidget *backgroundWidget = new QWidget;
backgroundWidget->setLayout(backgroundLayout);
//! [22]
toolBox = new QToolBox;
toolBox->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Ignored));
toolBox->setMinimumWidth(itemWidget->sizeHint().width());
toolBox->addItem(itemWidget, tr("Basic Flowchart Shapes"));
toolBox->addItem(backgroundWidget, tr("Backgrounds"));
}
//! [22]
//! [23]
void MainWindow::createActions()
{
toFrontAction = new QAction(QIcon(":/images/bringtofront.png"),
tr("Bring to &Front"), this);
toFrontAction->setShortcut(tr("Ctrl+F"));
toFrontAction->setStatusTip(tr("Bring item to front"));
connect(toFrontAction, &QAction::triggered, this, &MainWindow::bringToFront);
//! [23]
sendBackAction = new QAction(QIcon(":/images/sendtoback.png"), tr("Send to &Back"), this);
sendBackAction->setShortcut(tr("Ctrl+T"));
sendBackAction->setStatusTip(tr("Send item to back"));
connect(sendBackAction, &QAction::triggered, this, &MainWindow::sendToBack);
deleteAction = new QAction(QIcon(":/images/delete.png"), tr("&Delete"), this);
deleteAction->setShortcut(tr("Delete"));
deleteAction->setStatusTip(tr("Delete item from diagram"));
connect(deleteAction, &QAction::triggered, this, &MainWindow::deleteItem);
exitAction = new QAction(tr("E&xit"), this);
exitAction->setShortcuts(QKeySequence::Quit);
exitAction->setStatusTip(tr("Quit Scenediagram example"));
connect(exitAction, &QAction::triggered, this, &QWidget::close);
boldAction = new QAction(tr("Bold"), this);
boldAction->setCheckable(true);
QPixmap pixmap(":/images/bold.png");
boldAction->setIcon(QIcon(pixmap));
boldAction->setShortcut(tr("Ctrl+B"));
connect(boldAction, &QAction::triggered, this, &MainWindow::handleFontChange);
italicAction = new QAction(QIcon(":/images/italic.png"), tr("Italic"), this);
italicAction->setCheckable(true);
italicAction->setShortcut(tr("Ctrl+I"));
connect(italicAction, &QAction::triggered, this, &MainWindow::handleFontChange);
underlineAction = new QAction(QIcon(":/images/underline.png"), tr("Underline"), this);
underlineAction->setCheckable(true);
underlineAction->setShortcut(tr("Ctrl+U"));
connect(underlineAction, &QAction::triggered, this, &MainWindow::handleFontChange);
aboutAction = new QAction(tr("A&bout"), this);
aboutAction->setShortcut(tr("F1"));
connect(aboutAction, &QAction::triggered, this, &MainWindow::about);
}
//! [24]
void MainWindow::createMenus()
{
fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(exitAction);
itemMenu = menuBar()->addMenu(tr("&Item"));
itemMenu->addAction(deleteAction);
itemMenu->addSeparator();
itemMenu->addAction(toFrontAction);
itemMenu->addAction(sendBackAction);
aboutMenu = menuBar()->addMenu(tr("&Help"));
aboutMenu->addAction(aboutAction);
}
//! [24]
//! [25]
void MainWindow::createToolbars()
{
//! [25]
editToolBar = addToolBar(tr("Edit"));
editToolBar->addAction(deleteAction);
editToolBar->addAction(toFrontAction);
editToolBar->addAction(sendBackAction);
fontCombo = new QFontComboBox();
connect(fontCombo, &QFontComboBox::currentFontChanged,
this, &MainWindow::currentFontChanged);
fontSizeCombo = new QComboBox;
fontSizeCombo->setEditable(true);
for (int i = 8; i < 30; i = i + 2)
fontSizeCombo->addItem(QString().setNum(i));
QIntValidator *validator = new QIntValidator(2, 64, this);
fontSizeCombo->setValidator(validator);
connect(fontSizeCombo, &QComboBox::currentTextChanged,
this, &MainWindow::fontSizeChanged);
fontColorToolButton = new QToolButton;
fontColorToolButton->setPopupMode(QToolButton::MenuButtonPopup);
fontColorToolButton->setMenu(createColorMenu(SLOT(textColorChanged()), Qt::black));
textAction = fontColorToolButton->menu()->defaultAction();
fontColorToolButton->setIcon(createColorToolButtonIcon(":/images/textpointer.png", Qt::black));
fontColorToolButton->setAutoFillBackground(true);
connect(fontColorToolButton, &QAbstractButton::clicked,
this, &MainWindow::textButtonTriggered);
//! [26]
fillColorToolButton = new QToolButton;
fillColorToolButton->setPopupMode(QToolButton::MenuButtonPopup);
fillColorToolButton->setMenu(createColorMenu(SLOT(itemColorChanged()), Qt::white));
fillAction = fillColorToolButton->menu()->defaultAction();
fillColorToolButton->setIcon(createColorToolButtonIcon(
":/images/floodfill.png", Qt::white));
connect(fillColorToolButton, &QAbstractButton::clicked,
this, &MainWindow::fillButtonTriggered);
//! [26]
lineColorToolButton = new QToolButton;
lineColorToolButton->setPopupMode(QToolButton::MenuButtonPopup);
lineColorToolButton->setMenu(createColorMenu(SLOT(lineColorChanged()), Qt::black));
lineAction = lineColorToolButton->menu()->defaultAction();
lineColorToolButton->setIcon(createColorToolButtonIcon(
":/images/linecolor.png", Qt::black));
connect(lineColorToolButton, &QAbstractButton::clicked,
this, &MainWindow::lineButtonTriggered);
textToolBar = addToolBar(tr("Font"));
textToolBar->addWidget(fontCombo);
textToolBar->addWidget(fontSizeCombo);
textToolBar->addAction(boldAction);
textToolBar->addAction(italicAction);
textToolBar->addAction(underlineAction);
colorToolBar = addToolBar(tr("Color"));
colorToolBar->addWidget(fontColorToolButton);
colorToolBar->addWidget(fillColorToolButton);
colorToolBar->addWidget(lineColorToolButton);
QToolButton *pointerButton = new QToolButton;
pointerButton->setCheckable(true);
pointerButton->setChecked(true);
pointerButton->setIcon(QIcon(":/images/pointer.png"));
QToolButton *linePointerButton = new QToolButton;
linePointerButton->setCheckable(true);
linePointerButton->setIcon(QIcon(":/images/linepointer.png"));
pointerTypeGroup = new QButtonGroup(this);
pointerTypeGroup->addButton(pointerButton, int(DiagramScene::MoveItem));
pointerTypeGroup->addButton(linePointerButton, int(DiagramScene::InsertLine));
connect(pointerTypeGroup, QOverload<QAbstractButton *>::of(&QButtonGroup::buttonClicked),
this, &MainWindow::pointerGroupClicked);
sceneScaleCombo = new QComboBox;
QStringList scales;
scales << tr("50%") << tr("75%") << tr("100%") << tr("125%") << tr("150%");
sceneScaleCombo->addItems(scales);
sceneScaleCombo->setCurrentIndex(2);
connect(sceneScaleCombo, &QComboBox::currentTextChanged,
this, &MainWindow::sceneScaleChanged);
pointerToolbar = addToolBar(tr("Pointer type"));
pointerToolbar->addWidget(pointerButton);
pointerToolbar->addWidget(linePointerButton);
pointerToolbar->addWidget(sceneScaleCombo);
//! [27]
}
//! [27]
//! [28]
QWidget *MainWindow::createBackgroundCellWidget(const QString &text, const QString &image)
{
QToolButton *button = new QToolButton;
button->setText(text);
button->setIcon(QIcon(image));
button->setIconSize(QSize(50, 50));
button->setCheckable(true);
backgroundButtonGroup->addButton(button);
QGridLayout *layout = new QGridLayout;
layout->addWidget(button, 0, 0, Qt::AlignHCenter);
layout->addWidget(new QLabel(text), 1, 0, Qt::AlignCenter);
QWidget *widget = new QWidget;
widget->setLayout(layout);
return widget;
}
//! [28]
//! [29]
QWidget *MainWindow::createCellWidget(const QString &text, DiagramItem::DiagramType type)
{
DiagramItem item(type, itemMenu);
QIcon icon(item.image());
QToolButton *button = new QToolButton;
button->setIcon(icon);
button->setIconSize(QSize(50, 50));
button->setCheckable(true);
buttonGroup->addButton(button, int(type));
QGridLayout *layout = new QGridLayout;
layout->addWidget(button, 0, 0, Qt::AlignHCenter);
layout->addWidget(new QLabel(text), 1, 0, Qt::AlignCenter);
QWidget *widget = new QWidget;
widget->setLayout(layout);
return widget;
}
//! [29]
//! [30]
QMenu *MainWindow::createColorMenu(const char *slot, QColor defaultColor)
{
QList<QColor> colors;
colors << Qt::black << Qt::white << Qt::red << Qt::blue << Qt::yellow;
QStringList names;
names << tr("black") << tr("white") << tr("red") << tr("blue")
<< tr("yellow");
QMenu *colorMenu = new QMenu(this);
for (int i = 0; i < colors.count(); ++i) {
QAction *action = new QAction(names.at(i), this);
action->setData(colors.at(i));
action->setIcon(createColorIcon(colors.at(i)));
connect(action, SIGNAL(triggered()), this, slot);
colorMenu->addAction(action);
if (colors.at(i) == defaultColor)
colorMenu->setDefaultAction(action);
}
return colorMenu;
}
//! [30]
//! [31]
QIcon MainWindow::createColorToolButtonIcon(const QString &imageFile, QColor color)
{
QPixmap pixmap(50, 80);
pixmap.fill(Qt::transparent);
QPainter painter(&pixmap);
QPixmap image(imageFile);
// Draw icon centred horizontally on button.
QRect target(4, 0, 42, 43);
QRect source(0, 0, 42, 43);
painter.fillRect(QRect(0, 60, 50, 80), color);
painter.drawPixmap(target, image, source);
return QIcon(pixmap);
}
//! [31]
//! [32]
QIcon MainWindow::createColorIcon(QColor color)
{
QPixmap pixmap(20, 20);
QPainter painter(&pixmap);
painter.setPen(Qt::NoPen);
painter.fillRect(QRect(0, 0, 20, 20), color);
return QIcon(pixmap);
}
//! [32]

View File

@ -0,0 +1,113 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "diagramitem.h"
#include <QMainWindow>
class DiagramScene;
QT_BEGIN_NAMESPACE
class QAction;
class QToolBox;
class QSpinBox;
class QComboBox;
class QFontComboBox;
class QButtonGroup;
class QLineEdit;
class QGraphicsTextItem;
class QFont;
class QToolButton;
class QAbstractButton;
class QGraphicsView;
QT_END_NAMESPACE
//! [0]
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow();
private slots:
void backgroundButtonGroupClicked(QAbstractButton *button);
void buttonGroupClicked(QAbstractButton *button);
void deleteItem();
void pointerGroupClicked();
void bringToFront();
void sendToBack();
void itemInserted(DiagramItem *item);
void textInserted(QGraphicsTextItem *item);
void currentFontChanged(const QFont &font);
void fontSizeChanged(const QString &size);
void sceneScaleChanged(const QString &scale);
void textColorChanged();
void itemColorChanged();
void lineColorChanged();
void textButtonTriggered();
void fillButtonTriggered();
void lineButtonTriggered();
void handleFontChange();
void itemSelected(QGraphicsItem *item);
void about();
private:
void createToolBox();
void createActions();
void createMenus();
void createToolbars();
QWidget *createBackgroundCellWidget(const QString &text,
const QString &image);
QWidget *createCellWidget(const QString &text,
DiagramItem::DiagramType type);
QMenu *createColorMenu(const char *slot, QColor defaultColor);
QIcon createColorToolButtonIcon(const QString &image, QColor color);
QIcon createColorIcon(QColor color);
DiagramScene *scene;
QGraphicsView *view;
QAction *exitAction;
QAction *addAction;
QAction *deleteAction;
QAction *toFrontAction;
QAction *sendBackAction;
QAction *aboutAction;
QMenu *fileMenu;
QMenu *itemMenu;
QMenu *aboutMenu;
QToolBar *textToolBar;
QToolBar *editToolBar;
QToolBar *colorToolBar;
QToolBar *pointerToolbar;
QComboBox *sceneScaleCombo;
QComboBox *itemColorCombo;
QComboBox *textColorCombo;
QComboBox *fontSizeCombo;
QFontComboBox *fontCombo;
QToolBox *toolBox;
QButtonGroup *buttonGroup;
QButtonGroup *pointerTypeGroup;
QButtonGroup *backgroundButtonGroup;
QToolButton *fontColorToolButton;
QToolButton *fillColorToolButton;
QToolButton *lineColorToolButton;
QAction *boldAction;
QAction *underlineAction;
QAction *italicAction;
QAction *textAction;
QAction *fillAction;
QAction *lineAction;
};
//! [0]
#endif // MAINWINDOW_H

View File

@ -0,0 +1,50 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(dragdroprobot LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/graphicsview/dragdroprobot")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
qt_standard_project_setup()
qt_add_executable(dragdroprobot
coloritem.cpp coloritem.h
main.cpp
robot.cpp robot.h
)
set_target_properties(dragdroprobot PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(dragdroprobot PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
# Resources:
set(robot_resource_files
"images/head.png"
)
qt_add_resources(dragdroprobot "robot"
PREFIX
"/"
FILES
${robot_resource_files}
)
install(TARGETS dragdroprobot
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -0,0 +1,113 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "coloritem.h"
#include <QApplication>
#include <QBitmap>
#include <QCursor>
#include <QDrag>
#include <QGraphicsSceneMouseEvent>
#include <QMimeData>
#include <QPainter>
#include <QRandomGenerator>
#include <QWidget>
//! [0]
ColorItem::ColorItem()
: color(QRandomGenerator::global()->bounded(256), QRandomGenerator::global()->bounded(256), QRandomGenerator::global()->bounded(256))
{
setToolTip(QString("QColor(%1, %2, %3)\n%4")
.arg(color.red()).arg(color.green()).arg(color.blue())
.arg("Click and drag this color onto the robot!"));
setCursor(Qt::OpenHandCursor);
setAcceptedMouseButtons(Qt::LeftButton);
}
//! [0]
//! [1]
QRectF ColorItem::boundingRect() const
{
return QRectF(-15.5, -15.5, 34, 34);
}
//! [1]
//! [2]
void ColorItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(option);
Q_UNUSED(widget);
painter->setPen(Qt::NoPen);
painter->setBrush(Qt::darkGray);
painter->drawEllipse(-12, -12, 30, 30);
painter->setPen(QPen(Qt::black, 1));
painter->setBrush(QBrush(color));
painter->drawEllipse(-15, -15, 30, 30);
}
//! [2]
//! [3]
void ColorItem::mousePressEvent(QGraphicsSceneMouseEvent *)
{
setCursor(Qt::ClosedHandCursor);
}
//! [3]
//! [5]
void ColorItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if (QLineF(event->screenPos(), event->buttonDownScreenPos(Qt::LeftButton))
.length() < QApplication::startDragDistance()) {
return;
}
QDrag *drag = new QDrag(event->widget());
QMimeData *mime = new QMimeData;
drag->setMimeData(mime);
//! [5]
//! [6]
static int n = 0;
if (n++ > 2 && QRandomGenerator::global()->bounded(3) == 0) {
QImage image(":/images/head.png");
mime->setImageData(image);
drag->setPixmap(QPixmap::fromImage(image).scaled(30, 40));
drag->setHotSpot(QPoint(15, 30));
//! [6]
//! [7]
} else {
mime->setColorData(color);
mime->setText(QString("#%1%2%3")
.arg(color.red(), 2, 16, QLatin1Char('0'))
.arg(color.green(), 2, 16, QLatin1Char('0'))
.arg(color.blue(), 2, 16, QLatin1Char('0')));
QPixmap pixmap(34, 34);
pixmap.fill(Qt::white);
QPainter painter(&pixmap);
painter.translate(15, 15);
painter.setRenderHint(QPainter::Antialiasing);
paint(&painter, nullptr, nullptr);
painter.end();
pixmap.setMask(pixmap.createHeuristicMask());
drag->setPixmap(pixmap);
drag->setHotSpot(QPoint(15, 20));
}
//! [7]
//! [8]
drag->exec();
setCursor(Qt::OpenHandCursor);
}
//! [8]
//! [4]
void ColorItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *)
{
setCursor(Qt::OpenHandCursor);
}
//! [4]

View File

@ -0,0 +1,28 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef COLORITEM_H
#define COLORITEM_H
#include <QGraphicsItem>
//! [0]
class ColorItem : public QGraphicsItem
{
public:
ColorItem();
QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
private:
QColor color;
};
//! [0]
#endif

View File

@ -0,0 +1,18 @@
QT += widgets
HEADERS += \
coloritem.h \
robot.h
SOURCES += \
coloritem.cpp \
main.cpp \
robot.cpp
RESOURCES += \
robot.qrc
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/graphicsview/dragdroprobot
INSTALLS += target

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,57 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include "coloritem.h"
#include "robot.h"
#include <cmath>
class GraphicsView : public QGraphicsView
{
public:
using QGraphicsView::QGraphicsView;
protected:
void resizeEvent(QResizeEvent *) override
{
}
};
//! [0]
int main(int argc, char **argv)
{
QApplication app(argc, argv);
//! [0]
//! [1]
QGraphicsScene scene(-200, -200, 400, 400);
for (int i = 0; i < 10; ++i) {
ColorItem *item = new ColorItem;
item->setPos(::sin((i * 6.28) / 10.0) * 150,
::cos((i * 6.28) / 10.0) * 150);
scene.addItem(item);
}
Robot *robot = new Robot;
robot->setTransform(QTransform::fromScale(1.2, 1.2), true);
robot->setPos(0, -20);
scene.addItem(robot);
//! [1]
//! [2]
GraphicsView view(&scene);
view.setRenderHint(QPainter::Antialiasing);
view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
view.setBackgroundBrush(QColor(230, 200, 167));
view.setWindowTitle("Drag and Drop Robot");
view.show();
return app.exec();
}
//! [2]

View File

@ -0,0 +1,269 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "robot.h"
#include <QGraphicsSceneDragDropEvent>
#include <QMimeData>
#include <QPainter>
#include <QParallelAnimationGroup>
#include <QPropertyAnimation>
//! [0]
RobotPart::RobotPart(QGraphicsItem *parent)
: QGraphicsObject(parent), color(Qt::lightGray)
{
setAcceptDrops(true);
}
//! [0]
//! [1]
void RobotPart::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
{
if (event->mimeData()->hasColor()) {
event->setAccepted(true);
dragOver = true;
update();
} else {
event->setAccepted(false);
}
}
//! [1]
//! [2]
void RobotPart::dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
{
Q_UNUSED(event);
dragOver = false;
update();
}
//! [2]
//! [3]
void RobotPart::dropEvent(QGraphicsSceneDragDropEvent *event)
{
dragOver = false;
if (event->mimeData()->hasColor())
color = qvariant_cast<QColor>(event->mimeData()->colorData());
update();
}
//! [3]
//! [4]
RobotHead::RobotHead(QGraphicsItem *parent)
: RobotPart(parent)
{
}
//! [4]
//! [5]
QRectF RobotHead::boundingRect() const
{
return QRectF(-15, -50, 30, 50);
}
//! [5]
//! [6]
void RobotHead::paint(QPainter *painter,
const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(option);
Q_UNUSED(widget);
if (pixmap.isNull()) {
painter->setBrush(dragOver ? color.lighter(130) : color);
painter->drawRoundedRect(-10, -30, 20, 30, 25, 25, Qt::RelativeSize);
painter->setBrush(Qt::white);
painter->drawEllipse(-7, -3 - 20, 7, 7);
painter->drawEllipse(0, -3 - 20, 7, 7);
painter->setBrush(Qt::black);
painter->drawEllipse(-5, -1 - 20, 2, 2);
painter->drawEllipse(2, -1 - 20, 2, 2);
painter->setPen(QPen(Qt::black, 2));
painter->setBrush(Qt::NoBrush);
painter->drawArc(-6, -2 - 20, 12, 15, 190 * 16, 160 * 16);
} else {
painter->scale(.2272, .2824);
painter->drawPixmap(QPointF(-15 * 4.4, -50 * 3.54), pixmap);
}
}
//! [6]
//! [7]
void RobotHead::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
{
if (event->mimeData()->hasImage()) {
event->setAccepted(true);
dragOver = true;
update();
} else {
RobotPart::dragEnterEvent(event);
}
}
//! [7]
//! [8]
void RobotHead::dropEvent(QGraphicsSceneDragDropEvent *event)
{
if (event->mimeData()->hasImage()) {
dragOver = false;
pixmap = qvariant_cast<QPixmap>(event->mimeData()->imageData());
update();
} else {
RobotPart::dropEvent(event);
}
}
//! [8]
QRectF RobotTorso::boundingRect() const
{
return QRectF(-30, -20, 60, 60);
}
void RobotTorso::paint(QPainter *painter,
const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(option);
Q_UNUSED(widget);
painter->setBrush(dragOver ? color.lighter(130) : color);
painter->drawRoundedRect(-20, -20, 40, 60, 25, 25, Qt::RelativeSize);
painter->drawEllipse(-25, -20, 20, 20);
painter->drawEllipse(5, -20, 20, 20);
painter->drawEllipse(-20, 22, 20, 20);
painter->drawEllipse(0, 22, 20, 20);
}
RobotLimb::RobotLimb(QGraphicsItem *parent)
: RobotPart(parent)
{
}
QRectF RobotLimb::boundingRect() const
{
return QRectF(-5, -5, 40, 10);
}
void RobotLimb::paint(QPainter *painter,
const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(option);
Q_UNUSED(widget);
painter->setBrush(dragOver ? color.lighter(130) : color);
painter->drawRoundedRect(boundingRect(), 50, 50, Qt::RelativeSize);
painter->drawEllipse(-5, -5, 10, 10);
}
//! [10]
Robot::Robot(QGraphicsItem *parent)
: RobotPart(parent)
{
setFlag(ItemHasNoContents);
QGraphicsObject *torsoItem = new RobotTorso(this);
QGraphicsObject *headItem = new RobotHead(torsoItem);
QGraphicsObject *upperLeftArmItem = new RobotLimb(torsoItem);
QGraphicsObject *lowerLeftArmItem = new RobotLimb(upperLeftArmItem);
QGraphicsObject *upperRightArmItem = new RobotLimb(torsoItem);
QGraphicsObject *lowerRightArmItem = new RobotLimb(upperRightArmItem);
QGraphicsObject *upperRightLegItem = new RobotLimb(torsoItem);
QGraphicsObject *lowerRightLegItem = new RobotLimb(upperRightLegItem);
QGraphicsObject *upperLeftLegItem = new RobotLimb(torsoItem);
QGraphicsObject *lowerLeftLegItem = new RobotLimb(upperLeftLegItem);
//! [10]
//! [11]
headItem->setPos(0, -18);
upperLeftArmItem->setPos(-15, -10);
lowerLeftArmItem->setPos(30, 0);
upperRightArmItem->setPos(15, -10);
lowerRightArmItem->setPos(30, 0);
upperRightLegItem->setPos(10, 32);
lowerRightLegItem->setPos(30, 0);
upperLeftLegItem->setPos(-10, 32);
lowerLeftLegItem->setPos(30, 0);
//! [11]
//! [12]
QParallelAnimationGroup *animation = new QParallelAnimationGroup(this);
QPropertyAnimation *headAnimation = new QPropertyAnimation(headItem, "rotation");
headAnimation->setStartValue(20);
headAnimation->setEndValue(-20);
QPropertyAnimation *headScaleAnimation = new QPropertyAnimation(headItem, "scale");
headScaleAnimation->setEndValue(1.1);
animation->addAnimation(headAnimation);
animation->addAnimation(headScaleAnimation);
//! [12]
QPropertyAnimation *upperLeftArmAnimation = new QPropertyAnimation(upperLeftArmItem, "rotation");
upperLeftArmAnimation->setStartValue(190);
upperLeftArmAnimation->setEndValue(180);
animation->addAnimation(upperLeftArmAnimation);
QPropertyAnimation *lowerLeftArmAnimation = new QPropertyAnimation(lowerLeftArmItem, "rotation");
lowerLeftArmAnimation->setStartValue(50);
lowerLeftArmAnimation->setEndValue(10);
animation->addAnimation(lowerLeftArmAnimation);
QPropertyAnimation *upperRightArmAnimation = new QPropertyAnimation(upperRightArmItem, "rotation");
upperRightArmAnimation->setStartValue(300);
upperRightArmAnimation->setEndValue(310);
animation->addAnimation(upperRightArmAnimation);
QPropertyAnimation *lowerRightArmAnimation = new QPropertyAnimation(lowerRightArmItem, "rotation");
lowerRightArmAnimation->setStartValue(0);
lowerRightArmAnimation->setEndValue(-70);
animation->addAnimation(lowerRightArmAnimation);
QPropertyAnimation *upperLeftLegAnimation = new QPropertyAnimation(upperLeftLegItem, "rotation");
upperLeftLegAnimation->setStartValue(150);
upperLeftLegAnimation->setEndValue(80);
animation->addAnimation(upperLeftLegAnimation);
QPropertyAnimation *lowerLeftLegAnimation = new QPropertyAnimation(lowerLeftLegItem, "rotation");
lowerLeftLegAnimation->setStartValue(70);
lowerLeftLegAnimation->setEndValue(10);
animation->addAnimation(lowerLeftLegAnimation);
QPropertyAnimation *upperRightLegAnimation = new QPropertyAnimation(upperRightLegItem, "rotation");
upperRightLegAnimation->setStartValue(40);
upperRightLegAnimation->setEndValue(120);
animation->addAnimation(upperRightLegAnimation);
QPropertyAnimation *lowerRightLegAnimation = new QPropertyAnimation(lowerRightLegItem, "rotation");
lowerRightLegAnimation->setStartValue(10);
lowerRightLegAnimation->setEndValue(50);
animation->addAnimation(lowerRightLegAnimation);
QPropertyAnimation *torsoAnimation = new QPropertyAnimation(torsoItem, "rotation");
torsoAnimation->setStartValue(5);
torsoAnimation->setEndValue(-20);
animation->addAnimation(torsoAnimation);
//! [13]
for (int i = 0; i < animation->animationCount(); ++i) {
QPropertyAnimation *anim = qobject_cast<QPropertyAnimation *>(animation->animationAt(i));
anim->setEasingCurve(QEasingCurve::SineCurve);
anim->setDuration(2000);
}
animation->setLoopCount(-1);
animation->start();
//! [13]
}
//! [9]
QRectF Robot::boundingRect() const
{
return QRectF();
}
void Robot::paint(QPainter *painter,
const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(painter);
Q_UNUSED(option);
Q_UNUSED(widget);
}
//! [9]

View File

@ -0,0 +1,81 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef ROBOT_H
#define ROBOT_H
#include <QGraphicsItem>
QT_BEGIN_NAMESPACE
class QGraphicsSceneMouseEvent;
class QParallelAnimationGroup;
QT_END_NAMESPACE
//! [0]
class RobotPart : public QGraphicsObject
{
public:
RobotPart(QGraphicsItem *parent = nullptr);
protected:
void dragEnterEvent(QGraphicsSceneDragDropEvent *event) override;
void dragLeaveEvent(QGraphicsSceneDragDropEvent *event) override;
void dropEvent(QGraphicsSceneDragDropEvent *event) override;
QColor color = Qt::lightGray;
bool dragOver = false;
};
//! [0]
//! [1]
class RobotHead : public RobotPart
{
public:
RobotHead(QGraphicsItem *parent = nullptr);
QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
protected:
void dragEnterEvent(QGraphicsSceneDragDropEvent *event) override;
void dropEvent(QGraphicsSceneDragDropEvent *event) override;
private:
QPixmap pixmap;
};
//! [1]
//! [2]
class RobotTorso : public RobotPart
{
public:
using RobotPart::RobotPart;
QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
};
//! [2]
//! [3]
class RobotLimb : public RobotPart
{
public:
RobotLimb(QGraphicsItem *parent = nullptr);
QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
};
//! [3]
//! [4]
class Robot : public RobotPart
{
public:
Robot(QGraphicsItem *parent = nullptr);
QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
};
//! [4]
#endif

View File

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/" >
<file>images/head.png</file>
</qresource>
</RCC>

View File

@ -0,0 +1,39 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(elasticnodes LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/graphicsview/elasticnodes")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
qt_standard_project_setup()
qt_add_executable(elasticnodes
edge.cpp edge.h
graphwidget.cpp graphwidget.h
main.cpp
node.cpp node.h
)
set_target_properties(elasticnodes PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(elasticnodes PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
install(TARGETS elasticnodes
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -0,0 +1,104 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "edge.h"
#include "node.h"
#include <QPainter>
#include <QtMath>
//! [0]
Edge::Edge(Node *sourceNode, Node *destNode)
: source(sourceNode), dest(destNode)
{
setAcceptedMouseButtons(Qt::NoButton);
source->addEdge(this);
dest->addEdge(this);
adjust();
}
//! [0]
//! [1]
Node *Edge::sourceNode() const
{
return source;
}
Node *Edge::destNode() const
{
return dest;
}
//! [1]
//! [2]
void Edge::adjust()
{
if (!source || !dest)
return;
QLineF line(mapFromItem(source, 0, 0), mapFromItem(dest, 0, 0));
qreal length = line.length();
prepareGeometryChange();
if (length > qreal(20.)) {
QPointF edgeOffset((line.dx() * 10) / length, (line.dy() * 10) / length);
sourcePoint = line.p1() + edgeOffset;
destPoint = line.p2() - edgeOffset;
} else {
sourcePoint = destPoint = line.p1();
}
}
//! [2]
//! [3]
QRectF Edge::boundingRect() const
{
if (!source || !dest)
return QRectF();
qreal penWidth = 1;
qreal extra = (penWidth + arrowSize) / 2.0;
return QRectF(sourcePoint, QSizeF(destPoint.x() - sourcePoint.x(),
destPoint.y() - sourcePoint.y()))
.normalized()
.adjusted(-extra, -extra, extra, extra);
}
//! [3]
//! [4]
void Edge::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
{
if (!source || !dest)
return;
QLineF line(sourcePoint, destPoint);
if (qFuzzyCompare(line.length(), qreal(0.)))
return;
//! [4]
//! [5]
// Draw the line itself
painter->setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter->drawLine(line);
//! [5]
//! [6]
// Draw the arrows
double angle = std::atan2(-line.dy(), line.dx());
QPointF sourceArrowP1 = sourcePoint + QPointF(sin(angle + M_PI / 3) * arrowSize,
cos(angle + M_PI / 3) * arrowSize);
QPointF sourceArrowP2 = sourcePoint + QPointF(sin(angle + M_PI - M_PI / 3) * arrowSize,
cos(angle + M_PI - M_PI / 3) * arrowSize);
QPointF destArrowP1 = destPoint + QPointF(sin(angle - M_PI / 3) * arrowSize,
cos(angle - M_PI / 3) * arrowSize);
QPointF destArrowP2 = destPoint + QPointF(sin(angle - M_PI + M_PI / 3) * arrowSize,
cos(angle - M_PI + M_PI / 3) * arrowSize);
painter->setBrush(Qt::black);
painter->drawPolygon(QPolygonF() << line.p1() << sourceArrowP1 << sourceArrowP2);
painter->drawPolygon(QPolygonF() << line.p2() << destArrowP1 << destArrowP2);
}
//! [6]

View File

@ -0,0 +1,38 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef EDGE_H
#define EDGE_H
#include <QGraphicsItem>
class Node;
//! [0]
class Edge : public QGraphicsItem
{
public:
Edge(Node *sourceNode, Node *destNode);
Node *sourceNode() const;
Node *destNode() const;
void adjust();
enum { Type = UserType + 2 };
int type() const override { return Type; }
protected:
QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
private:
Node *source, *dest;
QPointF sourcePoint;
QPointF destPoint;
qreal arrowSize = 10;
};
//! [0]
#endif // EDGE_H

View File

@ -0,0 +1,16 @@
QT += widgets
HEADERS += \
edge.h \
node.h \
graphwidget.h
SOURCES += \
edge.cpp \
main.cpp \
node.cpp \
graphwidget.cpp
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/graphicsview/elasticnodes
INSTALLS += target

View File

@ -0,0 +1,218 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "graphwidget.h"
#include "edge.h"
#include "node.h"
#include <math.h>
#include <QKeyEvent>
#include <QRandomGenerator>
//! [0]
GraphWidget::GraphWidget(QWidget *parent)
: QGraphicsView(parent)
{
QGraphicsScene *scene = new QGraphicsScene(this);
scene->setItemIndexMethod(QGraphicsScene::NoIndex);
scene->setSceneRect(-200, -200, 400, 400);
setScene(scene);
setCacheMode(CacheBackground);
setViewportUpdateMode(BoundingRectViewportUpdate);
setRenderHint(QPainter::Antialiasing);
setTransformationAnchor(AnchorUnderMouse);
scale(qreal(0.8), qreal(0.8));
setMinimumSize(400, 400);
setWindowTitle(tr("Elastic Nodes"));
//! [0]
//! [1]
Node *node1 = new Node(this);
Node *node2 = new Node(this);
Node *node3 = new Node(this);
Node *node4 = new Node(this);
centerNode = new Node(this);
Node *node6 = new Node(this);
Node *node7 = new Node(this);
Node *node8 = new Node(this);
Node *node9 = new Node(this);
scene->addItem(node1);
scene->addItem(node2);
scene->addItem(node3);
scene->addItem(node4);
scene->addItem(centerNode);
scene->addItem(node6);
scene->addItem(node7);
scene->addItem(node8);
scene->addItem(node9);
scene->addItem(new Edge(node1, node2));
scene->addItem(new Edge(node2, node3));
scene->addItem(new Edge(node2, centerNode));
scene->addItem(new Edge(node3, node6));
scene->addItem(new Edge(node4, node1));
scene->addItem(new Edge(node4, centerNode));
scene->addItem(new Edge(centerNode, node6));
scene->addItem(new Edge(centerNode, node8));
scene->addItem(new Edge(node6, node9));
scene->addItem(new Edge(node7, node4));
scene->addItem(new Edge(node8, node7));
scene->addItem(new Edge(node9, node8));
node1->setPos(-50, -50);
node2->setPos(0, -50);
node3->setPos(50, -50);
node4->setPos(-50, 0);
centerNode->setPos(0, 0);
node6->setPos(50, 0);
node7->setPos(-50, 50);
node8->setPos(0, 50);
node9->setPos(50, 50);
}
//! [1]
//! [2]
void GraphWidget::itemMoved()
{
if (!timerId)
timerId = startTimer(1000 / 25);
}
//! [2]
//! [3]
void GraphWidget::keyPressEvent(QKeyEvent *event)
{
switch (event->key()) {
case Qt::Key_Up:
centerNode->moveBy(0, -20);
break;
case Qt::Key_Down:
centerNode->moveBy(0, 20);
break;
case Qt::Key_Left:
centerNode->moveBy(-20, 0);
break;
case Qt::Key_Right:
centerNode->moveBy(20, 0);
break;
case Qt::Key_Plus:
zoomIn();
break;
case Qt::Key_Minus:
zoomOut();
break;
case Qt::Key_Space:
case Qt::Key_Enter:
shuffle();
break;
default:
QGraphicsView::keyPressEvent(event);
}
}
//! [3]
//! [4]
void GraphWidget::timerEvent(QTimerEvent *event)
{
Q_UNUSED(event);
QList<Node *> nodes;
const QList<QGraphicsItem *> items = scene()->items();
for (QGraphicsItem *item : items) {
if (Node *node = qgraphicsitem_cast<Node *>(item))
nodes << node;
}
for (Node *node : std::as_const(nodes))
node->calculateForces();
bool itemsMoved = false;
for (Node *node : std::as_const(nodes)) {
if (node->advancePosition())
itemsMoved = true;
}
if (!itemsMoved) {
killTimer(timerId);
timerId = 0;
}
}
//! [4]
#if QT_CONFIG(wheelevent)
//! [5]
void GraphWidget::wheelEvent(QWheelEvent *event)
{
scaleView(pow(2., -event->angleDelta().y() / 240.0));
}
//! [5]
#endif
//! [6]
void GraphWidget::drawBackground(QPainter *painter, const QRectF &rect)
{
Q_UNUSED(rect);
// Shadow
QRectF sceneRect = this->sceneRect();
QRectF rightShadow(sceneRect.right(), sceneRect.top() + 5, 5, sceneRect.height());
QRectF bottomShadow(sceneRect.left() + 5, sceneRect.bottom(), sceneRect.width(), 5);
if (rightShadow.intersects(rect) || rightShadow.contains(rect))
painter->fillRect(rightShadow, Qt::darkGray);
if (bottomShadow.intersects(rect) || bottomShadow.contains(rect))
painter->fillRect(bottomShadow, Qt::darkGray);
// Fill
QLinearGradient gradient(sceneRect.topLeft(), sceneRect.bottomRight());
gradient.setColorAt(0, Qt::white);
gradient.setColorAt(1, Qt::lightGray);
painter->fillRect(rect.intersected(sceneRect), gradient);
painter->setBrush(Qt::NoBrush);
painter->drawRect(sceneRect);
// Text
QRectF textRect(sceneRect.left() + 4, sceneRect.top() + 4,
sceneRect.width() - 4, sceneRect.height() - 4);
QString message(tr("Click and drag the nodes around, and zoom with the mouse "
"wheel or the '+' and '-' keys"));
QFont font = painter->font();
font.setBold(true);
font.setPointSize(14);
painter->setFont(font);
painter->setPen(Qt::lightGray);
painter->drawText(textRect.translated(2, 2), message);
painter->setPen(Qt::black);
painter->drawText(textRect, message);
}
//! [6]
//! [7]
void GraphWidget::scaleView(qreal scaleFactor)
{
qreal factor = transform().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width();
if (factor < 0.07 || factor > 100)
return;
scale(scaleFactor, scaleFactor);
}
//! [7]
void GraphWidget::shuffle()
{
const QList<QGraphicsItem *> items = scene()->items();
for (QGraphicsItem *item : items) {
if (qgraphicsitem_cast<Node *>(item))
item->setPos(-150 + QRandomGenerator::global()->bounded(300), -150 + QRandomGenerator::global()->bounded(300));
}
}
void GraphWidget::zoomIn()
{
scaleView(qreal(1.2));
}
void GraphWidget::zoomOut()
{
scaleView(1 / qreal(1.2));
}

View File

@ -0,0 +1,42 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef GRAPHWIDGET_H
#define GRAPHWIDGET_H
#include <QGraphicsView>
class Node;
//! [0]
class GraphWidget : public QGraphicsView
{
Q_OBJECT
public:
GraphWidget(QWidget *parent = nullptr);
void itemMoved();
public slots:
void shuffle();
void zoomIn();
void zoomOut();
protected:
void keyPressEvent(QKeyEvent *event) override;
void timerEvent(QTimerEvent *event) override;
#if QT_CONFIG(wheelevent)
void wheelEvent(QWheelEvent *event) override;
#endif
void drawBackground(QPainter *painter, const QRectF &rect) override;
void scaleView(qreal scaleFactor);
private:
int timerId = 0;
Node *centerNode;
};
//! [0]
#endif // GRAPHWIDGET_H

View File

@ -0,0 +1,21 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "graphwidget.h"
#include <QApplication>
#include <QTime>
#include <QMainWindow>
int main(int argc, char **argv)
{
QApplication app(argc, argv);
GraphWidget *widget = new GraphWidget;
QMainWindow mainWindow;
mainWindow.setCentralWidget(widget);
mainWindow.show();
return app.exec();
}

View File

@ -0,0 +1,175 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "edge.h"
#include "node.h"
#include "graphwidget.h"
#include <QGraphicsScene>
#include <QGraphicsSceneMouseEvent>
#include <QPainter>
#include <QStyleOption>
//! [0]
Node::Node(GraphWidget *graphWidget)
: graph(graphWidget)
{
setFlag(ItemIsMovable);
setFlag(ItemSendsGeometryChanges);
setCacheMode(DeviceCoordinateCache);
setZValue(-1);
}
//! [0]
//! [1]
void Node::addEdge(Edge *edge)
{
edgeList << edge;
edge->adjust();
}
QList<Edge *> Node::edges() const
{
return edgeList;
}
//! [1]
//! [2]
void Node::calculateForces()
{
if (!scene() || scene()->mouseGrabberItem() == this) {
newPos = pos();
return;
}
//! [2]
//! [3]
// Sum up all forces pushing this item away
qreal xvel = 0;
qreal yvel = 0;
const QList<QGraphicsItem *> items = scene()->items();
for (QGraphicsItem *item : items) {
Node *node = qgraphicsitem_cast<Node *>(item);
if (!node)
continue;
QPointF vec = mapToItem(node, 0, 0);
qreal dx = vec.x();
qreal dy = vec.y();
double l = 2.0 * (dx * dx + dy * dy);
if (l > 0) {
xvel += (dx * 150.0) / l;
yvel += (dy * 150.0) / l;
}
}
//! [3]
//! [4]
// Now subtract all forces pulling items together
double weight = (edgeList.size() + 1) * 10;
for (const Edge *edge : std::as_const(edgeList)) {
QPointF vec;
if (edge->sourceNode() == this)
vec = mapToItem(edge->destNode(), 0, 0);
else
vec = mapToItem(edge->sourceNode(), 0, 0);
xvel -= vec.x() / weight;
yvel -= vec.y() / weight;
}
//! [4]
//! [5]
if (qAbs(xvel) < 0.1 && qAbs(yvel) < 0.1)
xvel = yvel = 0;
//! [5]
//! [6]
QRectF sceneRect = scene()->sceneRect();
newPos = pos() + QPointF(xvel, yvel);
newPos.setX(qMin(qMax(newPos.x(), sceneRect.left() + 10), sceneRect.right() - 10));
newPos.setY(qMin(qMax(newPos.y(), sceneRect.top() + 10), sceneRect.bottom() - 10));
}
//! [6]
//! [7]
bool Node::advancePosition()
{
if (newPos == pos())
return false;
setPos(newPos);
return true;
}
//! [7]
//! [8]
QRectF Node::boundingRect() const
{
qreal adjust = 2;
return QRectF( -10 - adjust, -10 - adjust, 23 + adjust, 23 + adjust);
}
//! [8]
//! [9]
QPainterPath Node::shape() const
{
QPainterPath path;
path.addEllipse(-10, -10, 20, 20);
return path;
}
//! [9]
//! [10]
void Node::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
{
painter->setPen(Qt::NoPen);
painter->setBrush(Qt::darkGray);
painter->drawEllipse(-7, -7, 20, 20);
QRadialGradient gradient(-3, -3, 10);
if (option->state & QStyle::State_Sunken) {
gradient.setCenter(3, 3);
gradient.setFocalPoint(3, 3);
gradient.setColorAt(1, QColor(Qt::yellow).lighter(120));
gradient.setColorAt(0, QColor(Qt::darkYellow).lighter(120));
} else {
gradient.setColorAt(0, Qt::yellow);
gradient.setColorAt(1, Qt::darkYellow);
}
painter->setBrush(gradient);
painter->setPen(QPen(Qt::black, 0));
painter->drawEllipse(-10, -10, 20, 20);
}
//! [10]
//! [11]
QVariant Node::itemChange(GraphicsItemChange change, const QVariant &value)
{
switch (change) {
case ItemPositionHasChanged:
for (Edge *edge : std::as_const(edgeList))
edge->adjust();
graph->itemMoved();
break;
default:
break;
};
return QGraphicsItem::itemChange(change, value);
}
//! [11]
//! [12]
void Node::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
update();
QGraphicsItem::mousePressEvent(event);
}
void Node::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
update();
QGraphicsItem::mouseReleaseEvent(event);
}
//! [12]

View File

@ -0,0 +1,45 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef NODE_H
#define NODE_H
#include <QGraphicsItem>
#include <QList>
class Edge;
class GraphWidget;
//! [0]
class Node : public QGraphicsItem
{
public:
Node(GraphWidget *graphWidget);
void addEdge(Edge *edge);
QList<Edge *> edges() const;
enum { Type = UserType + 1 };
int type() const override { return Type; }
void calculateForces();
bool advancePosition();
QRectF boundingRect() const override;
QPainterPath shape() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
protected:
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
private:
QList<Edge *> edgeList;
QPointF newPos;
GraphWidget *graph;
};
//! [0]
#endif // NODE_H

View File

@ -0,0 +1,50 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(embeddeddialogs LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/graphicsview/embeddeddialogs")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
qt_standard_project_setup()
qt_add_executable(embeddeddialogs
customproxy.cpp customproxy.h
embeddeddialog.cpp embeddeddialog.h embeddeddialog.ui
main.cpp
)
set_target_properties(embeddeddialogs PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(embeddeddialogs PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
# Resources:
set(embeddeddialogs_resource_files
"No-Ones-Laughing-3.jpg"
)
qt_add_resources(embeddeddialogs "embeddeddialogs"
PREFIX
"/"
FILES
${embeddeddialogs_resource_files}
)
install(TARGETS embeddeddialogs
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -0,0 +1,133 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "customproxy.h"
#include <QGraphicsScene>
#include <QPainter>
#include <QStyleOptionGraphicsItem>
CustomProxy::CustomProxy(QGraphicsItem *parent, Qt::WindowFlags wFlags)
: QGraphicsProxyWidget(parent, wFlags), timeLine(new QTimeLine(250, this))
{
connect(timeLine, &QTimeLine::valueChanged,
this, &CustomProxy::updateStep);
connect(timeLine, &QTimeLine::stateChanged,
this, &CustomProxy::stateChanged);
}
QRectF CustomProxy::boundingRect() const
{
return QGraphicsProxyWidget::boundingRect().adjusted(0, 0, 10, 10);
}
void CustomProxy::paintWindowFrame(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget)
{
const QColor color(0, 0, 0, 64);
QRectF r = windowFrameRect();
QRectF right(r.right(), r.top() + 10, 10, r.height() - 10);
QRectF bottom(r.left() + 10, r.bottom(), r.width(), 10);
bool intersectsRight = right.intersects(option->exposedRect);
bool intersectsBottom = bottom.intersects(option->exposedRect);
if (intersectsRight && intersectsBottom) {
QPainterPath path;
path.addRect(right);
path.addRect(bottom);
painter->setPen(Qt::NoPen);
painter->setBrush(color);
painter->drawPath(path);
} else if (intersectsBottom) {
painter->fillRect(bottom, color);
} else if (intersectsRight) {
painter->fillRect(right, color);
}
QGraphicsProxyWidget::paintWindowFrame(painter, option, widget);
}
void CustomProxy::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
QGraphicsProxyWidget::hoverEnterEvent(event);
scene()->setActiveWindow(this);
if (qFuzzyCompare(timeLine->currentValue(), 1))
zoomIn();
}
void CustomProxy::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
QGraphicsProxyWidget::hoverLeaveEvent(event);
if (!popupShown
&& (timeLine->direction() != QTimeLine::Backward || qFuzzyIsNull(timeLine->currentValue()))) {
zoomOut();
}
}
bool CustomProxy::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
{
if (watched->isWindow()
&& (event->type() == QEvent::UngrabMouse || event->type() == QEvent::GrabMouse)) {
popupShown = watched->isVisible();
if (!popupShown && !isUnderMouse())
zoomOut();
}
return QGraphicsProxyWidget::sceneEventFilter(watched, event);
}
QVariant CustomProxy::itemChange(GraphicsItemChange change, const QVariant &value)
{
if (change == ItemChildAddedChange || change == ItemChildRemovedChange) {
if (change == ItemChildAddedChange) {
currentPopup = qvariant_cast<QGraphicsItem *>(value);
currentPopup->setCacheMode(ItemCoordinateCache);
if (scene())
currentPopup->installSceneEventFilter(this);
} else if (scene()) {
currentPopup->removeSceneEventFilter(this);
currentPopup = nullptr;
}
} else if (currentPopup && change == ItemSceneHasChanged) {
currentPopup->installSceneEventFilter(this);
}
return QGraphicsProxyWidget::itemChange(change, value);
}
void CustomProxy::updateStep(qreal step)
{
QRectF r = boundingRect();
setTransform(QTransform()
.translate(r.width() / 2, r.height() / 2)
.rotate(step * 30, Qt::XAxis)
.rotate(step * 10, Qt::YAxis)
.rotate(step * 5, Qt::ZAxis)
.scale(1 + 1.5 * step, 1 + 1.5 * step)
.translate(-r.width() / 2, -r.height() / 2));
}
void CustomProxy::stateChanged(QTimeLine::State state)
{
if (state == QTimeLine::Running) {
if (timeLine->direction() == QTimeLine::Forward)
setCacheMode(ItemCoordinateCache);
} else if (state == QTimeLine::NotRunning) {
if (timeLine->direction() == QTimeLine::Backward)
setCacheMode(DeviceCoordinateCache);
}
}
void CustomProxy::zoomIn()
{
if (timeLine->direction() != QTimeLine::Forward)
timeLine->setDirection(QTimeLine::Forward);
if (timeLine->state() == QTimeLine::NotRunning)
timeLine->start();
}
void CustomProxy::zoomOut()
{
if (timeLine->direction() != QTimeLine::Backward)
timeLine->setDirection(QTimeLine::Backward);
if (timeLine->state() == QTimeLine::NotRunning)
timeLine->start();
}

View File

@ -0,0 +1,39 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef CUSTOMPROXY_H
#define CUSTOMPROXY_H
#include <QTimeLine>
#include <QGraphicsProxyWidget>
class CustomProxy : public QGraphicsProxyWidget
{
Q_OBJECT
public:
explicit CustomProxy(QGraphicsItem *parent = nullptr, Qt::WindowFlags wFlags = { });
QRectF boundingRect() const override;
void paintWindowFrame(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget) override;
protected:
void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override;
bool sceneEventFilter(QGraphicsItem *watched, QEvent *event) override;
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
private slots:
void updateStep(qreal step);
void stateChanged(QTimeLine::State);
void zoomIn();
void zoomOut();
private:
QTimeLine *timeLine;
QGraphicsItem *currentPopup = nullptr;
bool popupShown = false;
};
#endif // CUSTOMPROXY_H

View File

@ -0,0 +1,70 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "embeddeddialog.h"
#include "ui_embeddeddialog.h"
#include <QStyleFactory>
EmbeddedDialog::EmbeddedDialog(QWidget *parent)
: QDialog(parent)
, ui(new Ui::EmbeddedDialog)
{
ui->setupUi(this);
ui->layoutDirection->setCurrentIndex(layoutDirection() != Qt::LeftToRight);
const QStringList styleKeys = QStyleFactory::keys();
for (const QString &styleName : styleKeys) {
ui->style->addItem(styleName);
if (style()->objectName().toLower() == styleName.toLower())
ui->style->setCurrentIndex(ui->style->count() - 1);
}
connect(ui->layoutDirection, &QComboBox::activated,
this, &EmbeddedDialog::layoutDirectionChanged);
connect(ui->spacing, &QSlider::valueChanged,
this, &EmbeddedDialog::spacingChanged);
connect(ui->fontComboBox, &QFontComboBox::currentFontChanged,
this, &EmbeddedDialog::fontChanged);
connect(ui->style, &QComboBox::textActivated,
this, &EmbeddedDialog::styleChanged);
}
EmbeddedDialog::~EmbeddedDialog()
{
delete ui;
}
void EmbeddedDialog::layoutDirectionChanged(int index)
{
setLayoutDirection(index == 0 ? Qt::LeftToRight : Qt::RightToLeft);
}
void EmbeddedDialog::spacingChanged(int spacing)
{
layout()->setSpacing(spacing);
adjustSize();
}
void EmbeddedDialog::fontChanged(const QFont &font)
{
setFont(font);
}
static void setStyleHelper(QWidget *widget, QStyle *style)
{
widget->setStyle(style);
widget->setPalette(style->standardPalette());
const QObjectList children = widget->children();
for (QObject *child : children) {
if (QWidget *childWidget = qobject_cast<QWidget *>(child))
setStyleHelper(childWidget, style);
}
}
void EmbeddedDialog::styleChanged(const QString &styleName)
{
QStyle *style = QStyleFactory::create(styleName);
if (style)
setStyleHelper(this, style);
}

View File

@ -0,0 +1,33 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef EMBEDDEDDIALOG_H
#define EMBEDDEDDIALOG_H
#include <QDialog>
QT_BEGIN_NAMESPACE
namespace Ui {
class EmbeddedDialog;
}
QT_END_NAMESPACE
class EmbeddedDialog : public QDialog
{
Q_OBJECT
public:
EmbeddedDialog(QWidget *parent = nullptr);
~EmbeddedDialog();
private slots:
void layoutDirectionChanged(int index);
void spacingChanged(int spacing);
void fontChanged(const QFont &font);
void styleChanged(const QString &styleName);
private:
Ui::EmbeddedDialog *ui;
};
#endif // EMBEDDEDDIALOG_H

View File

@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>EmbeddedDialog</class>
<widget class="QDialog" name="EmbeddedDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>407</width>
<height>134</height>
</rect>
</property>
<property name="windowTitle">
<string>Embedded Dialog</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Layout Direction:</string>
</property>
<property name="buddy">
<cstring>layoutDirection</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="layoutDirection">
<item>
<property name="text">
<string>Left to Right</string>
</property>
</item>
<item>
<property name="text">
<string>Right to Left</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Select Font:</string>
</property>
<property name="buddy">
<cstring>fontComboBox</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QFontComboBox" name="fontComboBox"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Style:</string>
</property>
<property name="buddy">
<cstring>style</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="style"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Layout spacing:</string>
</property>
<property name="buddy">
<cstring>spacing</cstring>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSlider" name="spacing">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,18 @@
QT += widgets
requires(qtConfig(fontcombobox))
SOURCES += main.cpp
SOURCES += customproxy.cpp embeddeddialog.cpp
HEADERS += customproxy.h embeddeddialog.h
FORMS += embeddeddialog.ui
RESOURCES += embeddeddialogs.qrc
build_all:!build_pass {
CONFIG -= build_all
CONFIG += release
}
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/graphicsview/embeddeddialogs
INSTALLS += target

View File

@ -0,0 +1,5 @@
<RCC>
<qresource>
<file>No-Ones-Laughing-3.jpg</file>
</qresource>
</RCC>

View File

@ -0,0 +1,43 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "customproxy.h"
#include "embeddeddialog.h"
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
int main(int argc, char *argv[])
{
Q_INIT_RESOURCE(embeddeddialogs);
QApplication app(argc, argv);
QGraphicsScene scene;
scene.setStickyFocus(true);
const int gridSize = 10;
for (int y = 0; y < gridSize; ++y) {
for (int x = 0; x < gridSize; ++x) {
CustomProxy *proxy = new CustomProxy(nullptr, Qt::Window);
proxy->setWidget(new EmbeddedDialog);
QRectF rect = proxy->boundingRect();
proxy->setPos(x * rect.width() * 1.05, y * rect.height() * 1.05);
proxy->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
scene.addItem(proxy);
}
}
scene.setSceneRect(scene.itemsBoundingRect());
QGraphicsView view(&scene);
view.scale(0.5, 0.5);
view.setRenderHints(view.renderHints() | QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
view.setBackgroundBrush(QPixmap(":/No-Ones-Laughing-3.jpg"));
view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
view.show();
view.setWindowTitle("Embedded Dialogs Example");
return app.exec();
}

View File

@ -0,0 +1,38 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(flowlayout LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/graphicsview_flowlayout")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
qt_standard_project_setup()
qt_add_executable(graphicsview_flowlayout
flowlayout.cpp flowlayout.h
main.cpp
window.cpp window.h
)
set_target_properties(graphicsview_flowlayout PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(graphicsview_flowlayout PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
install(TARGETS graphicsview_flowlayout
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -0,0 +1,170 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "flowlayout.h"
#include <QtMath>
FlowLayout::FlowLayout(QGraphicsLayoutItem *parent) : QGraphicsLayout(parent)
{
QSizePolicy sp = sizePolicy();
sp.setHeightForWidth(true);
setSizePolicy(sp);
}
void FlowLayout::insertItem(int index, QGraphicsLayoutItem *item)
{
item->setParentLayoutItem(this);
if (index > m_items.count() || index < 0)
index = m_items.count();
m_items.insert(index, item);
invalidate();
}
int FlowLayout::count() const
{
return m_items.count();
}
QGraphicsLayoutItem *FlowLayout::itemAt(int index) const
{
return m_items.value(index);
}
void FlowLayout::removeAt(int index)
{
m_items.removeAt(index);
invalidate();
}
qreal FlowLayout::spacing(Qt::Orientation o) const
{
return m_spacing[int(o) - 1];
}
void FlowLayout::setSpacing(Qt::Orientations o, qreal spacing)
{
if (o & Qt::Horizontal)
m_spacing[0] = spacing;
if (o & Qt::Vertical)
m_spacing[1] = spacing;
}
void FlowLayout::setGeometry(const QRectF &geom)
{
QGraphicsLayout::setGeometry(geom);
doLayout(geom, true);
}
qreal FlowLayout::doLayout(const QRectF &geom, bool applyNewGeometry) const
{
qreal left, top, right, bottom;
getContentsMargins(&left, &top, &right, &bottom);
const qreal maxw = geom.width() - left - right;
qreal x = 0;
qreal y = 0;
qreal maxRowHeight = 0;
QSizeF pref;
for (QGraphicsLayoutItem *item : m_items) {
pref = item->effectiveSizeHint(Qt::PreferredSize);
maxRowHeight = qMax(maxRowHeight, pref.height());
qreal next_x;
next_x = x + pref.width();
if (next_x > maxw) {
if (qFuzzyIsNull(x)) {
pref.setWidth(maxw);
} else {
x = 0;
next_x = pref.width();
}
y += maxRowHeight + spacing(Qt::Vertical);
maxRowHeight = 0;
}
if (applyNewGeometry)
item->setGeometry(QRectF(QPointF(left + x, top + y), pref));
x = next_x + spacing(Qt::Horizontal);
}
maxRowHeight = qMax(maxRowHeight, pref.height());
return top + y + maxRowHeight + bottom;
}
QSizeF FlowLayout::minSize(const QSizeF &constraint) const
{
QSizeF size(0, 0);
qreal left, top, right, bottom;
getContentsMargins(&left, &top, &right, &bottom);
if (constraint.width() >= 0) { // height for width
const qreal height = doLayout(QRectF(QPointF(0,0), constraint), false);
size = QSizeF(constraint.width(), height);
} else if (constraint.height() >= 0) { // width for height?
// not supported
} else {
for (const QGraphicsLayoutItem *item : std::as_const(m_items))
size = size.expandedTo(item->effectiveSizeHint(Qt::MinimumSize));
size += QSizeF(left + right, top + bottom);
}
return size;
}
QSizeF FlowLayout::prefSize() const
{
qreal left, right;
getContentsMargins(&left, nullptr, &right, nullptr);
qreal maxh = 0;
qreal totalWidth = 0;
for (const QGraphicsLayoutItem *item : std::as_const(m_items)) {
if (totalWidth > 0)
totalWidth += spacing(Qt::Horizontal);
QSizeF pref = item->effectiveSizeHint(Qt::PreferredSize);
totalWidth += pref.width();
maxh = qMax(maxh, pref.height());
}
maxh += spacing(Qt::Vertical);
const qreal goldenAspectRatio = 1.61803399;
qreal w = qSqrt(totalWidth * maxh * goldenAspectRatio) + left + right;
return minSize(QSizeF(w, -1));
}
QSizeF FlowLayout::maxSize() const
{
qreal totalWidth = 0;
qreal totalHeight = 0;
for (const QGraphicsLayoutItem *item : std::as_const(m_items)) {
if (totalWidth > 0)
totalWidth += spacing(Qt::Horizontal);
if (totalHeight > 0)
totalHeight += spacing(Qt::Vertical);
QSizeF pref = item->effectiveSizeHint(Qt::PreferredSize);
totalWidth += pref.width();
totalHeight += pref.height();
}
qreal left, top, right, bottom;
getContentsMargins(&left, &top, &right, &bottom);
return QSizeF(left + totalWidth + right, top + totalHeight + bottom);
}
QSizeF FlowLayout::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
{
QSizeF sh = constraint;
switch (which) {
case Qt::PreferredSize:
sh = prefSize();
break;
case Qt::MinimumSize:
sh = minSize(constraint);
break;
case Qt::MaximumSize:
sh = maxSize();
break;
default:
break;
}
return sh;
}

View File

@ -0,0 +1,44 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef FLOWLAYOUT_H
#define FLOWLAYOUT_H
#include <QGraphicsLayout>
class FlowLayout : public QGraphicsLayout
{
public:
FlowLayout(QGraphicsLayoutItem *parent = nullptr);
inline void addItem(QGraphicsLayoutItem *item);
void insertItem(int index, QGraphicsLayoutItem *item);
void setSpacing(Qt::Orientations o, qreal spacing);
qreal spacing(Qt::Orientation o) const;
// inherited functions
void setGeometry(const QRectF &geom) override;
int count() const override;
QGraphicsLayoutItem *itemAt(int index) const override;
void removeAt(int index) override;
protected:
QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const override;
private:
qreal doLayout(const QRectF &geom, bool applyNewGeometry) const;
QSizeF minSize(const QSizeF &constraint) const;
QSizeF prefSize() const;
QSizeF maxSize() const;
QList<QGraphicsLayoutItem *> m_items;
qreal m_spacing[2] = {6, 6};
};
inline void FlowLayout::addItem(QGraphicsLayoutItem *item)
{
insertItem(-1, item);
}
#endif // FLOWLAYOUT_H

View File

@ -0,0 +1,10 @@
QT += widgets
QMAKE_PROJECT_NAME = flowlayout_graphicsview
HEADERS += flowlayout.h window.h
SOURCES += flowlayout.cpp main.cpp window.cpp
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/graphicsview/flowlayout
INSTALLS += target

View File

@ -0,0 +1,24 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [1]
#include "window.h"
#include <QApplication>
#include <QGraphicsView>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QGraphicsScene scene;
QGraphicsView view(&scene);
Window *w = new Window;
scene.addItem(w);
view.resize(400, 300);
view.show();
return app.exec();
}
//! [1]

View File

@ -0,0 +1,24 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "window.h"
#include "flowlayout.h"
#include <QGraphicsProxyWidget>
#include <QLabel>
Window::Window(QGraphicsItem *parent) : QGraphicsWidget(parent, Qt::Window)
{
FlowLayout *lay = new FlowLayout;
const QString sentence(QLatin1String("I am not bothered by the fact that I am unknown."
" I am bothered when I do not know others. (Confucius)"));
const QList<QStringView> words = QStringView{ sentence }.split(QLatin1Char(' '), Qt::SkipEmptyParts);
for (const QStringView &word : words) {
QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget(this);
QLabel *label = new QLabel(word.toString());
label->setFrameStyle(QFrame::Box | QFrame::Plain);
proxy->setWidget(label);
lay->addItem(proxy);
}
setLayout(lay);
}

View File

@ -0,0 +1,16 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef WINDOW_H
#define WINDOW_H
#include <QGraphicsWidget>
class Window : public QGraphicsWidget
{
Q_OBJECT
public:
Window(QGraphicsItem *parent = nullptr);
};
#endif // WINDOW_H

View File

@ -0,0 +1,13 @@
TEMPLATE = subdirs
SUBDIRS = \
chip \
elasticnodes \
embeddeddialogs \
collidingmice \
basicgraphicslayouts \
diagramscene \
dragdroprobot \
flowlayout \
simpleanchorlayout
contains(DEFINES, QT_NO_CURSOR)|!qtConfig(draganddrop): SUBDIRS -= dragdroprobot

View File

@ -0,0 +1,36 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(simpleanchorlayout LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/graphicsview/simpleanchorlayout")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
qt_standard_project_setup()
qt_add_executable(simpleanchorlayout
main.cpp
)
set_target_properties(simpleanchorlayout PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(simpleanchorlayout PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
install(TARGETS simpleanchorlayout
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

Some files were not shown because too many files have changed in this diff Show More