qt 6.5.1 original
14
examples/widgets/graphicsview/CMakeLists.txt
Normal 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()
|
9
examples/widgets/graphicsview/README
Normal 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.
|
@ -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}"
|
||||
)
|
@ -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
|
@ -0,0 +1,5 @@
|
||||
<RCC>
|
||||
<qresource>
|
||||
<file>images/block.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
After Width: | Height: | Size: 2.1 KiB |
@ -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]
|
@ -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
|
22
examples/widgets/graphicsview/basicgraphicslayouts/main.cpp
Normal 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();
|
||||
}
|
@ -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]
|
||||
|
||||
}
|
20
examples/widgets/graphicsview/basicgraphicslayouts/window.h
Normal 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
|
||||
|
63
examples/widgets/graphicsview/chip/CMakeLists.txt
Normal 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}"
|
||||
)
|
147
examples/widgets/graphicsview/chip/chip.cpp
Normal 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();
|
||||
}
|
31
examples/widgets/graphicsview/chip/chip.h
Normal 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
|
18
examples/widgets/graphicsview/chip/chip.pro
Normal 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
|
||||
|
BIN
examples/widgets/graphicsview/chip/fileprint.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
10
examples/widgets/graphicsview/chip/images.qrc
Normal 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>
|
19
examples/widgets/graphicsview/chip/main.cpp
Normal 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();
|
||||
}
|
65
examples/widgets/graphicsview/chip/mainwindow.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
29
examples/widgets/graphicsview/chip/mainwindow.h
Normal 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
|
BIN
examples/widgets/graphicsview/chip/qt4logo.png
Normal file
After Width: | Height: | Size: 47 KiB |
BIN
examples/widgets/graphicsview/chip/rotateleft.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
examples/widgets/graphicsview/chip/rotateright.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
237
examples/widgets/graphicsview/chip/view.cpp
Normal 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);
|
||||
}
|
70
examples/widgets/graphicsview/chip/view.h
Normal 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
|
BIN
examples/widgets/graphicsview/chip/zoomin.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
examples/widgets/graphicsview/chip/zoomout.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
49
examples/widgets/graphicsview/collidingmice/CMakeLists.txt
Normal 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}"
|
||||
)
|
@ -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
|
BIN
examples/widgets/graphicsview/collidingmice/images/cheese.jpg
Normal file
After Width: | Height: | Size: 3.0 KiB |
52
examples/widgets/graphicsview/collidingmice/main.cpp
Normal 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]
|
5
examples/widgets/graphicsview/collidingmice/mice.qrc
Normal file
@ -0,0 +1,5 @@
|
||||
<RCC>
|
||||
<qresource prefix="/" >
|
||||
<file>images/cheese.jpg</file>
|
||||
</qresource>
|
||||
</RCC>
|
160
examples/widgets/graphicsview/collidingmice/mouse.cpp
Normal 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]
|
31
examples/widgets/graphicsview/collidingmice/mouse.h
Normal 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
|
67
examples/widgets/graphicsview/diagramscene/CMakeLists.txt
Normal 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}"
|
||||
)
|
102
examples/widgets/graphicsview/diagramscene/arrow.cpp
Normal 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]
|
41
examples/widgets/graphicsview/diagramscene/arrow.h
Normal 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
|
114
examples/widgets/graphicsview/diagramscene/diagramitem.cpp
Normal 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]
|
48
examples/widgets/graphicsview/diagramscene/diagramitem.h
Normal 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
|
196
examples/widgets/graphicsview/diagramscene/diagramscene.cpp
Normal 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]
|
72
examples/widgets/graphicsview/diagramscene/diagramscene.h
Normal 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
|
20
examples/widgets/graphicsview/diagramscene/diagramscene.pro
Normal 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
|
20
examples/widgets/graphicsview/diagramscene/diagramscene.qrc
Normal 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>
|
||||
|
@ -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]
|
36
examples/widgets/graphicsview/diagramscene/diagramtextitem.h
Normal 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
|
After Width: | Height: | Size: 112 B |
After Width: | Height: | Size: 114 B |
After Width: | Height: | Size: 116 B |
After Width: | Height: | Size: 96 B |
BIN
examples/widgets/graphicsview/diagramscene/images/bold.png
Normal file
After Width: | Height: | Size: 353 B |
After Width: | Height: | Size: 293 B |
BIN
examples/widgets/graphicsview/diagramscene/images/delete.png
Normal file
After Width: | Height: | Size: 831 B |
BIN
examples/widgets/graphicsview/diagramscene/images/floodfill.png
Normal file
After Width: | Height: | Size: 282 B |
BIN
examples/widgets/graphicsview/diagramscene/images/italic.png
Normal file
After Width: | Height: | Size: 299 B |
BIN
examples/widgets/graphicsview/diagramscene/images/linecolor.png
Normal file
After Width: | Height: | Size: 145 B |
After Width: | Height: | Size: 141 B |
BIN
examples/widgets/graphicsview/diagramscene/images/pointer.png
Normal file
After Width: | Height: | Size: 230 B |
BIN
examples/widgets/graphicsview/diagramscene/images/sendtoback.png
Normal file
After Width: | Height: | Size: 318 B |
After Width: | Height: | Size: 893 B |
BIN
examples/widgets/graphicsview/diagramscene/images/underline.png
Normal file
After Width: | Height: | Size: 307 B |
18
examples/widgets/graphicsview/diagramscene/main.cpp
Normal 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();
|
||||
}
|
599
examples/widgets/graphicsview/diagramscene/mainwindow.cpp
Normal 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]
|
113
examples/widgets/graphicsview/diagramscene/mainwindow.h
Normal 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
|
50
examples/widgets/graphicsview/dragdroprobot/CMakeLists.txt
Normal 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}"
|
||||
)
|
113
examples/widgets/graphicsview/dragdroprobot/coloritem.cpp
Normal 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]
|
28
examples/widgets/graphicsview/dragdroprobot/coloritem.h
Normal 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
|
@ -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
|
BIN
examples/widgets/graphicsview/dragdroprobot/images/head.png
Normal file
After Width: | Height: | Size: 15 KiB |
57
examples/widgets/graphicsview/dragdroprobot/main.cpp
Normal 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]
|
269
examples/widgets/graphicsview/dragdroprobot/robot.cpp
Normal 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]
|
81
examples/widgets/graphicsview/dragdroprobot/robot.h
Normal 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
|
5
examples/widgets/graphicsview/dragdroprobot/robot.qrc
Normal file
@ -0,0 +1,5 @@
|
||||
<RCC>
|
||||
<qresource prefix="/" >
|
||||
<file>images/head.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
39
examples/widgets/graphicsview/elasticnodes/CMakeLists.txt
Normal 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}"
|
||||
)
|
104
examples/widgets/graphicsview/elasticnodes/edge.cpp
Normal 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]
|
38
examples/widgets/graphicsview/elasticnodes/edge.h
Normal 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
|
16
examples/widgets/graphicsview/elasticnodes/elasticnodes.pro
Normal 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
|
218
examples/widgets/graphicsview/elasticnodes/graphwidget.cpp
Normal 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));
|
||||
}
|
42
examples/widgets/graphicsview/elasticnodes/graphwidget.h
Normal 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
|
21
examples/widgets/graphicsview/elasticnodes/main.cpp
Normal 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();
|
||||
}
|
175
examples/widgets/graphicsview/elasticnodes/node.cpp
Normal 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]
|
45
examples/widgets/graphicsview/elasticnodes/node.h
Normal 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
|
50
examples/widgets/graphicsview/embeddeddialogs/CMakeLists.txt
Normal 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}"
|
||||
)
|
After Width: | Height: | Size: 30 KiB |
133
examples/widgets/graphicsview/embeddeddialogs/customproxy.cpp
Normal 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();
|
||||
}
|
39
examples/widgets/graphicsview/embeddeddialogs/customproxy.h
Normal 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
|
@ -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);
|
||||
}
|
@ -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
|
@ -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>
|
@ -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
|
@ -0,0 +1,5 @@
|
||||
<RCC>
|
||||
<qresource>
|
||||
<file>No-Ones-Laughing-3.jpg</file>
|
||||
</qresource>
|
||||
</RCC>
|
43
examples/widgets/graphicsview/embeddeddialogs/main.cpp
Normal 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();
|
||||
}
|
38
examples/widgets/graphicsview/flowlayout/CMakeLists.txt
Normal 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}"
|
||||
)
|
170
examples/widgets/graphicsview/flowlayout/flowlayout.cpp
Normal 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;
|
||||
}
|
44
examples/widgets/graphicsview/flowlayout/flowlayout.h
Normal 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
|
10
examples/widgets/graphicsview/flowlayout/flowlayout.pro
Normal 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
|
24
examples/widgets/graphicsview/flowlayout/main.cpp
Normal 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]
|
24
examples/widgets/graphicsview/flowlayout/window.cpp
Normal 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);
|
||||
}
|
16
examples/widgets/graphicsview/flowlayout/window.h
Normal 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
|
13
examples/widgets/graphicsview/graphicsview.pro
Normal 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
|
@ -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}"
|
||||
)
|