From 91c22c8dc08888d0d545086d0eaaae757ef27553 Mon Sep 17 00:00:00 2001 From: Tomi Korpipaa Date: Tue, 14 Feb 2023 09:31:41 +0200 Subject: Combine 2 more widget examples into graph gallery MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Combine the 2 scatter graph examples into graph gallery example. Note: surface examples will be combined into graph gallery in other commits, to avoid making one gigantic commit. Task-number: QTBUG-110698 Change-Id: I8c50d07a31a8b1ee84596f4e216e629d88c7846a Reviewed-by: Tomi Korpipää (cherry picked from commit cbaa2eaaf73ffa0d2b4ba999c993199fc22110ea) Reviewed-by: Qt Cherry-pick Bot --- examples/datavisualization/CMakeLists.txt | 2 - examples/datavisualization/datavisualization.pro | 3 +- .../datavisualization/draggableaxes/CMakeLists.txt | 44 ----- .../draggableaxes/axesinputhandler.cpp | 122 ------------- .../draggableaxes/axesinputhandler.h | 54 ------ examples/datavisualization/draggableaxes/data.cpp | 147 --------------- examples/datavisualization/draggableaxes/data.h | 31 ---- .../doc/images/draggableaxes-example.png | Bin 90050 -> 0 bytes .../draggableaxes/doc/src/draggableaxes.qdoc | 111 ------------ .../draggableaxes/draggableaxes.pro | 18 -- examples/datavisualization/draggableaxes/main.cpp | 52 ------ .../datavisualization/graphgallery/CMakeLists.txt | 3 + .../graphgallery/axesinputhandler.cpp | 116 ++++++++++++ .../graphgallery/axesinputhandler.h | 54 ++++++ .../datavisualization/graphgallery/bargraph.cpp | 5 +- .../graphgallery/doc/src/graphgallery.qdoc | 144 ++++++++++++++- .../graphgallery/graphgallery.pro | 11 +- examples/datavisualization/graphgallery/main.cpp | 10 +- .../graphgallery/rainfalldata.cpp | 2 +- .../graphgallery/scatterdatamodifier.cpp | 198 +++++++++++++++++++++ .../graphgallery/scatterdatamodifier.h | 50 ++++++ .../graphgallery/scattergraph.cpp | 149 ++++++++++++++++ .../datavisualization/graphgallery/scattergraph.h | 26 +++ examples/datavisualization/scatter/CMakeLists.txt | 43 ----- .../scatter/doc/images/scatter-example.png | Bin 142496 -> 0 bytes .../datavisualization/scatter/doc/src/scatter.qdoc | 135 -------------- examples/datavisualization/scatter/main.cpp | 170 ------------------ examples/datavisualization/scatter/scatter.pro | 17 -- .../scatter/scatterdatamodifier.cpp | 190 -------------------- .../scatter/scatterdatamodifier.h | 52 ------ .../doc/src/qtdatavisualization.qdoc | 10 +- src/datavisualization/engine/qabstract3dgraph.cpp | 2 +- 32 files changed, 765 insertions(+), 1206 deletions(-) delete mode 100644 examples/datavisualization/draggableaxes/CMakeLists.txt delete mode 100644 examples/datavisualization/draggableaxes/axesinputhandler.cpp delete mode 100644 examples/datavisualization/draggableaxes/axesinputhandler.h delete mode 100644 examples/datavisualization/draggableaxes/data.cpp delete mode 100644 examples/datavisualization/draggableaxes/data.h delete mode 100644 examples/datavisualization/draggableaxes/doc/images/draggableaxes-example.png delete mode 100644 examples/datavisualization/draggableaxes/doc/src/draggableaxes.qdoc delete mode 100644 examples/datavisualization/draggableaxes/draggableaxes.pro delete mode 100644 examples/datavisualization/draggableaxes/main.cpp create mode 100644 examples/datavisualization/graphgallery/axesinputhandler.cpp create mode 100644 examples/datavisualization/graphgallery/axesinputhandler.h create mode 100644 examples/datavisualization/graphgallery/scatterdatamodifier.cpp create mode 100644 examples/datavisualization/graphgallery/scatterdatamodifier.h create mode 100644 examples/datavisualization/graphgallery/scattergraph.cpp create mode 100644 examples/datavisualization/graphgallery/scattergraph.h delete mode 100644 examples/datavisualization/scatter/CMakeLists.txt delete mode 100644 examples/datavisualization/scatter/doc/images/scatter-example.png delete mode 100644 examples/datavisualization/scatter/doc/src/scatter.qdoc delete mode 100644 examples/datavisualization/scatter/main.cpp delete mode 100644 examples/datavisualization/scatter/scatter.pro delete mode 100644 examples/datavisualization/scatter/scatterdatamodifier.cpp delete mode 100644 examples/datavisualization/scatter/scatterdatamodifier.h diff --git a/examples/datavisualization/CMakeLists.txt b/examples/datavisualization/CMakeLists.txt index b4c0bb46..c7be4a7a 100644 --- a/examples/datavisualization/CMakeLists.txt +++ b/examples/datavisualization/CMakeLists.txt @@ -9,9 +9,7 @@ if(TARGET Qt::Quick) endif() if(NOT ANDROID AND NOT IOS AND NOT WINRT) qt_internal_add_example(graphgallery) - qt_internal_add_example(scatter) qt_internal_add_example(surface) - qt_internal_add_example(draggableaxes) qt_internal_add_example(customitems) qt_internal_add_example(texturesurface) qt_internal_add_example(volumetric) diff --git a/examples/datavisualization/datavisualization.pro b/examples/datavisualization/datavisualization.pro index 1cf117f3..8fbaa375 100644 --- a/examples/datavisualization/datavisualization.pro +++ b/examples/datavisualization/datavisualization.pro @@ -7,9 +7,8 @@ qtHaveModule(quick) { } !android:!ios:!winrt { - SUBDIRS += scatter \ + SUBDIRS += graphgallery \ surface \ - draggableaxes \ customitems \ texturesurface \ volumetric diff --git a/examples/datavisualization/draggableaxes/CMakeLists.txt b/examples/datavisualization/draggableaxes/CMakeLists.txt deleted file mode 100644 index f1c5907f..00000000 --- a/examples/datavisualization/draggableaxes/CMakeLists.txt +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -cmake_minimum_required(VERSION 3.16) -project(draggableaxes LANGUAGES CXX) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(CMAKE_AUTOMOC ON) -set(CMAKE_AUTORCC ON) -set(CMAKE_AUTOUIC ON) - -if(NOT DEFINED INSTALL_EXAMPLESDIR) - set(INSTALL_EXAMPLESDIR "examples") -endif() - -set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}") - -find_package(Qt6 COMPONENTS Core) -find_package(Qt6 COMPONENTS Gui) -find_package(Qt6 COMPONENTS Widgets) -find_package(Qt6 COMPONENTS DataVisualization) - -qt_add_executable(draggableaxes - axesinputhandler.cpp axesinputhandler.h - data.cpp data.h - main.cpp -) -set_target_properties(draggableaxes PROPERTIES - WIN32_EXECUTABLE TRUE - MACOSX_BUNDLE TRUE -) -target_link_libraries(draggableaxes PUBLIC - Qt::Core - Qt::Gui - Qt::Widgets - Qt::DataVisualization -) - -install(TARGETS draggableaxes - RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" - BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" - LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" -) diff --git a/examples/datavisualization/draggableaxes/axesinputhandler.cpp b/examples/datavisualization/draggableaxes/axesinputhandler.cpp deleted file mode 100644 index 8b4191a4..00000000 --- a/examples/datavisualization/draggableaxes/axesinputhandler.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only - -#include "axesinputhandler.h" -#include - -AxesInputHandler::AxesInputHandler(QAbstract3DGraph *graph, QObject *parent) : - Q3DInputHandler(parent), - m_mousePressed(false), - m_state(StateNormal), - m_axisX(0), - m_axisZ(0), - m_axisY(0), - m_speedModifier(15.0f) -{ - //! [3] - // Connect to the item selection signal from graph - connect(graph, &QAbstract3DGraph::selectedElementChanged, this, - &AxesInputHandler::handleElementSelected); - //! [3] -} - -//! [0] -void AxesInputHandler::mousePressEvent(QMouseEvent *event, const QPoint &mousePos) -{ - Q3DInputHandler::mousePressEvent(event, mousePos); - if (Qt::LeftButton == event->button()) - m_mousePressed = true; -} -//! [0] - -//! [2] -void AxesInputHandler::mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos) -{ - //! [5] - // Check if we're trying to drag axis label - if (m_mousePressed && m_state != StateNormal) { - //! [5] - setPreviousInputPos(inputPosition()); - setInputPosition(mousePos); - handleAxisDragging(); - } else { - Q3DInputHandler::mouseMoveEvent(event, mousePos); - } -} -//! [2] - -//! [1] -void AxesInputHandler::mouseReleaseEvent(QMouseEvent *event, const QPoint &mousePos) -{ - Q3DInputHandler::mouseReleaseEvent(event, mousePos); - m_mousePressed = false; - m_state = StateNormal; -} -//! [1] - -void AxesInputHandler::handleElementSelected(QAbstract3DGraph::ElementType type) -{ - //! [4] - switch (type) { - case QAbstract3DGraph::ElementAxisXLabel: - m_state = StateDraggingX; - break; - case QAbstract3DGraph::ElementAxisYLabel: - m_state = StateDraggingY; - break; - case QAbstract3DGraph::ElementAxisZLabel: - m_state = StateDraggingZ; - break; - default: - m_state = StateNormal; - break; - } - //! [4] -} - -void AxesInputHandler::handleAxisDragging() -{ - float distance = 0.0f; - - //! [6] - // Get scene orientation from active camera - float xRotation = scene()->activeCamera()->xRotation(); - float yRotation = scene()->activeCamera()->yRotation(); - //! [6] - - //! [7] - // Calculate directional drag multipliers based on rotation - float xMulX = qCos(qDegreesToRadians(xRotation)); - float xMulY = qSin(qDegreesToRadians(xRotation)); - float zMulX = qSin(qDegreesToRadians(xRotation)); - float zMulY = qCos(qDegreesToRadians(xRotation)); - //! [7] - - //! [8] - // Get the drag amount - QPoint move = inputPosition() - previousInputPos(); - - // Flip the effect of y movement if we're viewing from below - float yMove = (yRotation < 0) ? -move.y() : move.y(); - //! [8] - - //! [9] - // Adjust axes - switch (m_state) { - case StateDraggingX: - distance = (move.x() * xMulX - yMove * xMulY) / m_speedModifier; - m_axisX->setRange(m_axisX->min() - distance, m_axisX->max() - distance); - break; - case StateDraggingZ: - distance = (move.x() * zMulX + yMove * zMulY) / m_speedModifier; - m_axisZ->setRange(m_axisZ->min() + distance, m_axisZ->max() + distance); - break; - case StateDraggingY: - distance = move.y() / m_speedModifier; // No need to use adjusted y move here - m_axisY->setRange(m_axisY->min() + distance, m_axisY->max() + distance); - break; - default: - break; - } - //! [9] -} diff --git a/examples/datavisualization/draggableaxes/axesinputhandler.h b/examples/datavisualization/draggableaxes/axesinputhandler.h deleted file mode 100644 index 9dde5190..00000000 --- a/examples/datavisualization/draggableaxes/axesinputhandler.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only - -#ifndef AXESINPUTHANDLER_H -#define AXESINPUTHANDLER_H - -#include -#include -#include - -//! [0] -class AxesInputHandler : public Q3DInputHandler -//! [0] -{ - Q_OBJECT - - enum InputState { - StateNormal = 0, - StateDraggingX, - StateDraggingZ, - StateDraggingY - }; - -public: - explicit AxesInputHandler(QAbstract3DGraph *graph, QObject *parent = 0); - - inline void setAxes(QValue3DAxis *axisX, QValue3DAxis *axisZ, QValue3DAxis *axisY) { - m_axisX = axisX; - m_axisZ = axisZ; - m_axisY = axisY; - } - - //! [1] - inline void setDragSpeedModifier(float modifier) { m_speedModifier = modifier; } - //! [1] - - virtual void mousePressEvent(QMouseEvent *event, const QPoint &mousePos); - virtual void mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos); - virtual void mouseReleaseEvent(QMouseEvent *event, const QPoint &mousePos); - -private: - void handleElementSelected(QAbstract3DGraph::ElementType type); - void handleAxisDragging(); - -private: - bool m_mousePressed; - InputState m_state; - QValue3DAxis *m_axisX; - QValue3DAxis *m_axisZ; - QValue3DAxis *m_axisY; - float m_speedModifier; -}; - -#endif diff --git a/examples/datavisualization/draggableaxes/data.cpp b/examples/datavisualization/draggableaxes/data.cpp deleted file mode 100644 index 532a0f7f..00000000 --- a/examples/datavisualization/draggableaxes/data.cpp +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only - -#include "data.h" - -#include -#include -#include -#include -#include -#include - -const int itemCount = 500; - -Data::Data(Q3DScatter *scatter) - : m_graph(scatter), - //! [1] - m_inputHandler(new AxesInputHandler(scatter)), - //! [1] - m_autoAdjust(false) -{ - m_graph->activeTheme()->setType(Q3DTheme::ThemeEbony); - m_graph->activeTheme()->setLabelBorderEnabled(true); - m_graph->activeTheme()->setLabelBackgroundColor(QColor(QRgb(0x151550))); - m_graph->activeTheme()->setLabelTextColor(Qt::lightGray); - m_graph->activeTheme()->setFont(QFont("Arial Black", 30)); - m_graph->setShadowQuality(QAbstract3DGraph::ShadowQualityMedium); - m_graph->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetIsometricRight); - - m_graph->axisX()->setRange(-20.0f, 20.0f); - m_graph->axisY()->setRange(-10.0f, 10.0f); - m_graph->axisZ()->setRange(-20.0f, 20.0f); - - //! [0] - // Give ownership of the handler to the graph and make it the active handler - m_graph->setActiveInputHandler(m_inputHandler); - //! [0] - - //! [2] - // Give our axes to the input handler - m_inputHandler->setAxes(m_graph->axisX(), m_graph->axisZ(), m_graph->axisY()); - //! [2] - - addData(); -} - -Data::~Data() -{ - delete m_graph; -} - -void Data::toggleRanges() -{ - if (!m_autoAdjust) { - m_graph->axisX()->setAutoAdjustRange(true); - m_graph->axisZ()->setAutoAdjustRange(true); - m_graph->axisY()->setAutoAdjustRange(true); - m_inputHandler->setDragSpeedModifier(1.5f); - m_autoAdjust = true; - } else { - m_graph->axisX()->setRange(-20.0f, 20.0f); - m_graph->axisY()->setRange(-10.0f, 10.0f); - m_graph->axisZ()->setRange(-20.0f, 20.0f); - m_inputHandler->setDragSpeedModifier(15.0f); - m_autoAdjust = false; - } -} - -void Data::addData() -{ - QScatter3DSeries *series = new QScatter3DSeries; - series->setMesh(QAbstract3DSeries::MeshCube); - series->setMeshSmooth(true); - m_graph->addSeries(series); - - QScatter3DSeries *series2 = new QScatter3DSeries; - series2->setMesh(QAbstract3DSeries::MeshMinimal); - series2->setMeshSmooth(true); - m_graph->addSeries(series2); - - QScatter3DSeries *series3 = new QScatter3DSeries; - series3->setMesh(QAbstract3DSeries::MeshSphere); - series3->setMeshSmooth(true); - m_graph->addSeries(series3); - - QScatter3DSeries *series4 = new QScatter3DSeries; - series4->setMesh(QAbstract3DSeries::MeshBevelCube); - series4->setMeshSmooth(true); - m_graph->addSeries(series4); - - QScatter3DSeries *series5 = new QScatter3DSeries; - series5->setMesh(QAbstract3DSeries::MeshSphere); - m_graph->addSeries(series5); - - QScatterDataArray *dataArray = new QScatterDataArray; - dataArray->resize(itemCount); - QScatterDataItem *ptrToDataArray = &dataArray->first(); - for (int i = 0; i < itemCount; i++) { - ptrToDataArray->setPosition(randVector()); - ptrToDataArray++; - } - QScatterDataArray *dataArray2 = new QScatterDataArray; - dataArray2->resize(itemCount); - ptrToDataArray = &dataArray2->first(); - for (int i = 0; i < itemCount; i++) { - ptrToDataArray->setPosition(randVector()); - ptrToDataArray++; - } - QScatterDataArray *dataArray3 = new QScatterDataArray; - dataArray3->resize(itemCount); - ptrToDataArray = &dataArray3->first(); - for (int i = 0; i < itemCount; i++) { - ptrToDataArray->setPosition(randVector()); - ptrToDataArray++; - } - QScatterDataArray *dataArray4 = new QScatterDataArray; - dataArray4->resize(itemCount); - ptrToDataArray = &dataArray4->first(); - for (int i = 0; i < itemCount; i++) { - ptrToDataArray->setPosition(randVector()); - ptrToDataArray++; - } - QScatterDataArray *dataArray5 = new QScatterDataArray; - dataArray5->resize(itemCount); - ptrToDataArray = &dataArray5->first(); - for (int i = 0; i < itemCount; i++) { - ptrToDataArray->setPosition(randVector()); - ptrToDataArray++; - } - - m_graph->seriesList().at(0)->dataProxy()->resetArray(dataArray); - m_graph->seriesList().at(1)->dataProxy()->resetArray(dataArray2); - m_graph->seriesList().at(2)->dataProxy()->resetArray(dataArray3); - m_graph->seriesList().at(3)->dataProxy()->resetArray(dataArray4); - m_graph->seriesList().at(4)->dataProxy()->resetArray(dataArray5); -} - -QVector3D Data::randVector() -{ - return QVector3D( - (float)(QRandomGenerator::global()->bounded(100)) / 2.0f - - (float)(QRandomGenerator::global()->bounded(100)) / 2.0f, - (float)(QRandomGenerator::global()->bounded(100)) / 2.0f - - (float)(QRandomGenerator::global()->bounded(100)) / 2.0f, - (float)(QRandomGenerator::global()->bounded(100)) / 2.0f - - (float)(QRandomGenerator::global()->bounded(100)) / 2.0f); -} diff --git a/examples/datavisualization/draggableaxes/data.h b/examples/datavisualization/draggableaxes/data.h deleted file mode 100644 index 84a3164b..00000000 --- a/examples/datavisualization/draggableaxes/data.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only - -#ifndef DATA_H -#define DATA_H - -#include "axesinputhandler.h" - -#include -#include - -class Data : public QObject -{ - Q_OBJECT -public: - explicit Data(Q3DScatter *scatter); - ~Data(); - - void toggleRanges(); - -private: - void addData(); - QVector3D randVector(); - -private: - Q3DScatter *m_graph; - AxesInputHandler *m_inputHandler; - bool m_autoAdjust; -}; - -#endif diff --git a/examples/datavisualization/draggableaxes/doc/images/draggableaxes-example.png b/examples/datavisualization/draggableaxes/doc/images/draggableaxes-example.png deleted file mode 100644 index 018694b5..00000000 Binary files a/examples/datavisualization/draggableaxes/doc/images/draggableaxes-example.png and /dev/null differ diff --git a/examples/datavisualization/draggableaxes/doc/src/draggableaxes.qdoc b/examples/datavisualization/draggableaxes/doc/src/draggableaxes.qdoc deleted file mode 100644 index 53810bb2..00000000 --- a/examples/datavisualization/draggableaxes/doc/src/draggableaxes.qdoc +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example draggableaxes - \meta tags {DataVisualization, Q3DScatter, Custom Input Handler, Scatter Graph} - \meta category {Graphics} - \title Input Handling for Axes - \ingroup qtdatavisualization_examples - \brief Implementing a custom input handler to support axis dragging. - \since QtDataVisualization 1.1 - - The Input Handling for Axes example shows how to customize the 3D graph controls in a widget - application to allow changing axis ranges by clicking on an axis label and dragging. This is - done by implementing a custom input handler to react to selection signals emitted from the - graph. - - \image draggableaxes-example.png - - \include examples-run.qdocinc - - \section1 Replacing Default Input Handling - - The default input handling mechanism is replaced by setting the active input handler of - Q3DScatter to \c AxesInputHandler that implements the custom behavior: - - \snippet draggableaxes/data.cpp 0 - - \c m_inputHandler was initialized in the constructor: - - \snippet draggableaxes/data.cpp 1 - - We will also need the pointers to the axes, so we will pass them to our input handler too: - - \snippet draggableaxes/data.cpp 2 - - \section1 Extending Mouse Event Handling - - First of all, we inherited our input handler from Q3DInputHandler instead of - QAbstract3DInputHandler. The reason for doing this is to keep all the functionality of the - default input handling, and to add our own functionality on top of it: - - \snippet draggableaxes/axesinputhandler.h 0 - - We start extending the default functionality by re-implementing some of the mouse events. - Let's start with \c {mousePressEvent}. We'll just add button pressed flag for left mouse button - into it, and keep the rest of the default functionality: - - \snippet draggableaxes/axesinputhandler.cpp 0 - - We'll need to modify \c mouseReleaseEvent too to clear the flag and reset the internal state: - - \snippet draggableaxes/axesinputhandler.cpp 1 - - Then we'll modify \c {mouseMoveEvent}. Here we check if the \c m_mousePressed is \c true and - our internal state is something other than \c StateNormal. If so, we'll set the input positions - for mouse move distance calculations and call the axis dragging function (see - \l {Implementing axis dragging} for details): - - \snippet draggableaxes/axesinputhandler.cpp 2 - - We don't need to change the functionality of mouse wheel, so we will not re-implement that. - - \section1 Implementing Axis Dragging - - First we need to start listening to the selection signal from the graph. We do that in the - constructor, and connect it to \c handleElementSelected method: - - \snippet draggableaxes/axesinputhandler.cpp 3 - - In \c handleElementSelected we check the type of the selection and set our internal state based on - it: - - \snippet draggableaxes/axesinputhandler.cpp 4 - - The actual dragging logic is implemented in \c handleAxisDragging method, which we call from - \c mouseMoveEvent in case the required conditions are met: - - \snippet draggableaxes/axesinputhandler.cpp 5 - - In \c handleAxisDragging we first get the scene orientation from our active camera: - - \snippet draggableaxes/axesinputhandler.cpp 6 - - Then we calculate the modifiers to mouse move direction based on the orientation: - - \snippet draggableaxes/axesinputhandler.cpp 7 - - After that, we calculate the mouse movement, and modify it based on the y rotation of the - camera: - - \snippet draggableaxes/axesinputhandler.cpp 8 - - And finally apply the moved distance to the correct axis: - - \snippet draggableaxes/axesinputhandler.cpp 9 - - We also have a function for setting the dragging speed: - - \snippet draggableaxes/axesinputhandler.h 1 - - This is needed, as the mouse movement distance is absolute (in screen coordinates) and we - need to adjust it to the axis range. The larger the value, the slower the dragging will be. - Note that on this example we do not take scene zoom level into account when determining the - drag speed, so you'll notice changes in the range adjustment as you change the zoom level. - - The modifier could be adjusted automatically based on the axis range and camera zoom level, but - we'll leave implementing that as an excercise for the reader. - - \section1 Example Contents -*/ diff --git a/examples/datavisualization/draggableaxes/draggableaxes.pro b/examples/datavisualization/draggableaxes/draggableaxes.pro deleted file mode 100644 index 2f21aee6..00000000 --- a/examples/datavisualization/draggableaxes/draggableaxes.pro +++ /dev/null @@ -1,18 +0,0 @@ -android|ios|winrt { - error( "This example is not supported for android, ios, or winrt." ) -} - -!include( ../examples.pri ) { - error( "Couldn't find the examples.pri file!" ) -} - -SOURCES += main.cpp \ - data.cpp \ - axesinputhandler.cpp -HEADERS += data.h \ - axesinputhandler.h - -QT += widgets - -OTHER_FILES += doc/src/* \ - doc/images/* diff --git a/examples/datavisualization/draggableaxes/main.cpp b/examples/datavisualization/draggableaxes/main.cpp deleted file mode 100644 index 3425d8ef..00000000 --- a/examples/datavisualization/draggableaxes/main.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only - -#include "data.h" - -#include -#include -#include -#include -#include -#include - -int main(int argc, char **argv) -{ - qputenv("QSG_RHI_BACKEND", "opengl"); - QApplication app(argc, argv); - Q3DScatter *graph = new Q3DScatter(); - QWidget *container = QWidget::createWindowContainer(graph); - - if (!graph->hasContext()) { - QMessageBox msgBox; - msgBox.setText("Couldn't initialize the OpenGL context."); - msgBox.exec(); - return -1; - } - - container->setMinimumSize(800, 600); - container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - container->setFocusPolicy(Qt::StrongFocus); - - QWidget *widget = new QWidget; - QHBoxLayout *hLayout = new QHBoxLayout(widget); - QVBoxLayout *vLayout = new QVBoxLayout(); - hLayout->addWidget(container, 1); - hLayout->addLayout(vLayout); - - QCommandLinkButton *rangeButton = new QCommandLinkButton(widget); - rangeButton->setText(QStringLiteral("Toggle axis ranges")); - rangeButton->setDescription(QStringLiteral("Switch between automatic axis ranges and preset ranges")); - rangeButton->setIconSize(QSize(0, 0)); - - vLayout->addWidget(rangeButton, 1, Qt::AlignTop); - - widget->setWindowTitle(QStringLiteral("Input Handling for Axes")); - - Data *graphData = new Data(graph); - - QObject::connect(rangeButton, &QCommandLinkButton::clicked, graphData, &Data::toggleRanges); - - widget->show(); - return app.exec(); -} diff --git a/examples/datavisualization/graphgallery/CMakeLists.txt b/examples/datavisualization/graphgallery/CMakeLists.txt index 9a53ece6..cde7adc7 100644 --- a/examples/datavisualization/graphgallery/CMakeLists.txt +++ b/examples/datavisualization/graphgallery/CMakeLists.txt @@ -29,6 +29,9 @@ qt_add_executable(graphgallery variantbardatamapping.cpp variantbardatamapping.h variantbardataproxy.cpp variantbardataproxy.h variantdataset.cpp variantdataset.h + scattergraph.cpp scattergraph.h + scatterdatamodifier.cpp scatterdatamodifier.h + axesinputhandler.cpp axesinputhandler.h ) set_target_properties(graphgallery PROPERTIES WIN32_EXECUTABLE TRUE diff --git a/examples/datavisualization/graphgallery/axesinputhandler.cpp b/examples/datavisualization/graphgallery/axesinputhandler.cpp new file mode 100644 index 00000000..4d48a9e8 --- /dev/null +++ b/examples/datavisualization/graphgallery/axesinputhandler.cpp @@ -0,0 +1,116 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "axesinputhandler.h" +#include + +AxesInputHandler::AxesInputHandler(QAbstract3DGraph *graph, QObject *parent) : + Q3DInputHandler(parent) +{ + //! [3] + // Connect to the item selection signal from graph + connect(graph, &QAbstract3DGraph::selectedElementChanged, this, + &AxesInputHandler::handleElementSelected); + //! [3] +} + +//! [0] +void AxesInputHandler::mousePressEvent(QMouseEvent *event, const QPoint &mousePos) +{ + Q3DInputHandler::mousePressEvent(event, mousePos); + if (Qt::LeftButton == event->button()) + m_mousePressed = true; +} +//! [0] + +//! [2] +void AxesInputHandler::mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos) +{ + //! [5] + // Check if we're trying to drag axis label + if (m_mousePressed && m_state != StateNormal) { + //! [5] + setPreviousInputPos(inputPosition()); + setInputPosition(mousePos); + handleAxisDragging(); + } else { + Q3DInputHandler::mouseMoveEvent(event, mousePos); + } +} +//! [2] + +//! [1] +void AxesInputHandler::mouseReleaseEvent(QMouseEvent *event, const QPoint &mousePos) +{ + Q3DInputHandler::mouseReleaseEvent(event, mousePos); + m_mousePressed = false; + m_state = StateNormal; +} +//! [1] + +void AxesInputHandler::handleElementSelected(QAbstract3DGraph::ElementType type) +{ + //! [4] + switch (type) { + case QAbstract3DGraph::ElementAxisXLabel: + m_state = StateDraggingX; + break; + case QAbstract3DGraph::ElementAxisYLabel: + m_state = StateDraggingY; + break; + case QAbstract3DGraph::ElementAxisZLabel: + m_state = StateDraggingZ; + break; + default: + m_state = StateNormal; + break; + } + //! [4] +} + +void AxesInputHandler::handleAxisDragging() +{ + float distance = 0.0f; + + //! [6] + // Get scene orientation from active camera + float xRotation = scene()->activeCamera()->xRotation(); + float yRotation = scene()->activeCamera()->yRotation(); + //! [6] + + //! [7] + // Calculate directional drag multipliers based on rotation + float xMulX = qCos(qDegreesToRadians(xRotation)); + float xMulY = qSin(qDegreesToRadians(xRotation)); + float zMulX = qSin(qDegreesToRadians(xRotation)); + float zMulY = qCos(qDegreesToRadians(xRotation)); + //! [7] + + //! [8] + // Get the drag amount + QPoint move = inputPosition() - previousInputPos(); + + // Flip the effect of y movement if we're viewing from below + float yMove = (yRotation < 0) ? -move.y() : move.y(); + //! [8] + + //! [9] + // Adjust axes + switch (m_state) { + case StateDraggingX: + distance = (move.x() * xMulX - yMove * xMulY) / m_speedModifier; + m_axisX->setRange(m_axisX->min() - distance, m_axisX->max() - distance); + break; + case StateDraggingZ: + distance = (move.x() * zMulX + yMove * zMulY) / m_speedModifier; + m_axisZ->setRange(m_axisZ->min() + distance, m_axisZ->max() + distance); + break; + case StateDraggingY: + distance = move.y() / m_speedModifier; // No need to use adjusted y move here + m_axisY->setRange(m_axisY->min() + distance, m_axisY->max() + distance); + break; + default: + break; + } + //! [9] +} diff --git a/examples/datavisualization/graphgallery/axesinputhandler.h b/examples/datavisualization/graphgallery/axesinputhandler.h new file mode 100644 index 00000000..cb8b161c --- /dev/null +++ b/examples/datavisualization/graphgallery/axesinputhandler.h @@ -0,0 +1,54 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef AXESINPUTHANDLER_H +#define AXESINPUTHANDLER_H + +#include +#include +#include + +//! [0] +class AxesInputHandler : public Q3DInputHandler +//! [0] +{ + Q_OBJECT + + enum InputState { + StateNormal = 0, + StateDraggingX, + StateDraggingZ, + StateDraggingY + }; + +public: + explicit AxesInputHandler(QAbstract3DGraph *graph, QObject *parent = 0); + + inline void setAxes(QValue3DAxis *axisX, QValue3DAxis *axisZ, QValue3DAxis *axisY) { + m_axisX = axisX; + m_axisZ = axisZ; + m_axisY = axisY; + } + + //! [1] + inline void setDragSpeedModifier(float modifier) { m_speedModifier = modifier; } + //! [1] + + virtual void mousePressEvent(QMouseEvent *event, const QPoint &mousePos); + virtual void mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos); + virtual void mouseReleaseEvent(QMouseEvent *event, const QPoint &mousePos); + +private: + void handleElementSelected(QAbstract3DGraph::ElementType type); + void handleAxisDragging(); + +private: + bool m_mousePressed = false; + InputState m_state = StateNormal; + QValue3DAxis *m_axisX = nullptr; + QValue3DAxis *m_axisZ = nullptr; + QValue3DAxis *m_axisY = nullptr; + float m_speedModifier = 15.f; +}; + +#endif diff --git a/examples/datavisualization/graphgallery/bargraph.cpp b/examples/datavisualization/graphgallery/bargraph.cpp index b8d450f9..49269648 100644 --- a/examples/datavisualization/graphgallery/bargraph.cpp +++ b/examples/datavisualization/graphgallery/bargraph.cpp @@ -38,7 +38,7 @@ bool BarGraph::initialize() } QSize screenSize = m_barsGraph->screen()->size(); - m_container->setMinimumSize(QSize(screenSize.width() / 2, screenSize.height() / 1.5)); + m_container->setMinimumSize(QSize(screenSize.width() / 2, screenSize.height() / 1.75)); m_container->setMaximumSize(screenSize); m_container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); m_container->setFocusPolicy(Qt::StrongFocus); @@ -51,9 +51,6 @@ bool BarGraph::initialize() hLayout->addLayout(vLayout); //! [1] - // TODO: Add a label into the main widget to show the title of the current example? - //m_barsWidget->setWindowTitle(QStringLiteral("Average temperatures in Oulu and Helsinki, Finland (2015-2022)")); - QComboBox *themeList = new QComboBox(m_barsWidget); themeList->addItem(QStringLiteral("Qt")); themeList->addItem(QStringLiteral("Primary Colors")); diff --git a/examples/datavisualization/graphgallery/doc/src/graphgallery.qdoc b/examples/datavisualization/graphgallery/doc/src/graphgallery.qdoc index e2695592..240fb359 100644 --- a/examples/datavisualization/graphgallery/doc/src/graphgallery.qdoc +++ b/examples/datavisualization/graphgallery/doc/src/graphgallery.qdoc @@ -3,7 +3,7 @@ /*! \example graphgallery - \meta tags {DataVisualization, Q3DBars, Bar Graph, Custom Proxy} + \meta tags {DataVisualization, Q3DBars, Bar Graph, Custom Proxy, Q3DScatter, Scatter Graph, Custom Input Handler} \meta category {Graphics} \title Graph Gallery \ingroup qtdatavisualization_examples @@ -52,7 +52,7 @@ \snippet graphgallery/bargraph.cpp 2 - \section2 Setting up the Graph + \section2 Setting up the Bar Graph Set up the graph in the constructor of the \c GraphModifier class: @@ -279,4 +279,144 @@ \snippet graphgallery/rainfalldata.h 0 + \section1 Scatter Graph + + In the \uicontrol {Scatter Graph} tab, create a 3D scatter graph using Q3DScatter. + The example shows how to: + + \list + \li Set up Q3DScatter graph + \li Use QScatterDataProxy to set data to the graph + \li Create a custom input handler by extending Q3DInputHandler + \endlist + + For basic application creation, see \l {Bar Graph}. + + \section2 Setting up the Scatter Graph + + First, set up some visual qualities for the graph in the constructor of the + \c ScatterDataModifier: + + \snippet graphgallery/scatterdatamodifier.cpp 0 + + None of these are mandatory, but are used to override graph defaults. You can try how it looks + with the preset defaults by commenting out the block above. + + Next, create a QScatterDataProxy and the associated QScatter3DSeries. Set a custom label format + and mesh smoothing for the series and add it to the graph: + + \snippet graphgallery/scatterdatamodifier.cpp 1 + + \section2 Adding Scatter Data + + The last thing to do in the \c ScatterDataModifier constructor is to add data to the graph: + + \snippet graphgallery/scatterdatamodifier.cpp 2 + + The actual data addition is done in \c addData() method. First, configure the axes: + + \snippet graphgallery/scatterdatamodifier.cpp 3 + + You could do this also in the constructor of \c {ScatterDataModifier}. Doing it here + keeps the constructor simpler and the axes' configuration near the data. + + Next, create a data array and populate it: + + \snippet graphgallery/scatterdatamodifier.cpp 4 + \dots + \snippet graphgallery/scatterdatamodifier.cpp 5 + + Finally, tell the proxy to start using the data we gave it: + + \snippet graphgallery/scatterdatamodifier.cpp 6 + + Now, the graph has the data and is ready for use. For information about adding widgets + to control the graph, see \l {Using Widgets to Control the Graph}. + + \section2 Replacing Default Input Handling + + Initialize \c m_inputHandler in the constructor with a pointer to the scatter graph instance: + + \snippet graphgallery/scatterdatamodifier.cpp 7 + + Replace the default input handling mechanism by setting the active input handler of + Q3DScatter to \c {AxesInputHandler}, which implements the custom behavior: + + \snippet graphgallery/scatterdatamodifier.cpp 8 + + The input handler needs access to the axes of the graph, so pass them to it: + + \snippet graphgallery/scatterdatamodifier.cpp 9 + + \section2 Extending Mouse Event Handling + + First, inherit the custom input handler from Q3DInputHandler instead of QAbstract3DInputHandler + to keep all the functionality of the default input handling, and to add the custom + functionality on top of it: + + \snippet graphgallery/axesinputhandler.h 0 + + Start extending the default functionality by re-implementing some of the mouse events. + First, extend \c {mousePressEvent}. Add a \c{m_mousePressed} flag for the left mouse button + to it, and keep the rest of the default functionality: + + \snippet graphgallery/axesinputhandler.cpp 0 + + Next, modify \c mouseReleaseEvent to clear the flag, and reset the internal state: + + \snippet graphgallery/axesinputhandler.cpp 1 + + Then, modify \c {mouseMoveEvent}. Check if \c m_mousePressed flag is \c {true} and + the internal state is something other than \c StateNormal. If so, set the input positions + for mouse movement distance calculations, and call the axis dragging function (see + \l {Implementing Axis Dragging} for details): + + \snippet graphgallery/axesinputhandler.cpp 2 + + \section2 Implementing Axis Dragging + + First, start listening to the selection signal from the graph. Do that in the + constructor, and connect it to the \c handleElementSelected method: + + \snippet graphgallery/axesinputhandler.cpp 3 + + In \c {handleElementSelected}, check the type of the selection, and set the internal state + based on it: + + \snippet graphgallery/axesinputhandler.cpp 4 + + The actual dragging logic is implemented in the \c handleAxisDragging method, which is called + from \c {mouseMoveEvent}, if the required conditions are met: + + \snippet graphgallery/axesinputhandler.cpp 5 + + In \c {handleAxisDragging}, first get the scene orientation from the active camera: + + \snippet graphgallery/axesinputhandler.cpp 6 + + Then, calculate the modifiers for mouse movement direction based on the orientation: + + \snippet graphgallery/axesinputhandler.cpp 7 + + After that, calculate the mouse movement, and modify it based on the y rotation of the + camera: + + \snippet graphgallery/axesinputhandler.cpp 8 + + Then, apply the moved distance to the correct axis: + + \snippet graphgallery/axesinputhandler.cpp 9 + + Finally, add a function for setting the dragging speed: + + \snippet graphgallery/axesinputhandler.h 1 + + This is needed, as the mouse movement distance is absolute in screen coordinates, and you + need to adjust it to the axis range. The larger the value, the slower the dragging will be. + Note that in this example, the scene zoom level is not taken into account when determining the + drag speed, so you'll notice changes in the range adjustment as you change the zoom level. + + You could also adjust the modifier automatically based on the axis range and camera zoom level. + + \section1 Example Contents */ diff --git a/examples/datavisualization/graphgallery/graphgallery.pro b/examples/datavisualization/graphgallery/graphgallery.pro index 1f8ce428..56ccde61 100644 --- a/examples/datavisualization/graphgallery/graphgallery.pro +++ b/examples/datavisualization/graphgallery/graphgallery.pro @@ -11,18 +11,25 @@ requires(qtConfig(fontcombobox)) requires(qtConfig(combobox)) SOURCES += main.cpp \ + bargraph.cpp \ graphmodifier.cpp \ rainfalldata.cpp \ variantdataset.cpp \ variantbardataproxy.cpp \ variantbardatamapping.cpp \ + scattergraph.cpp \ + scatterdatamodifier.cpp \ + axesinputhandler.cpp -HEADERS += \ +HEADERS += bargraph.h \ graphmodifier.h \ rainfalldata.h \ variantdataset.h \ variantbardataproxy.h \ - variantbardatamapping.h + variantbardatamapping.h \ + scattergraph.h \ + scatterdatamodifier.h \ + axesinputhandler.h RESOURCES += graphgallery.qrc diff --git a/examples/datavisualization/graphgallery/main.cpp b/examples/datavisualization/graphgallery/main.cpp index ad8eeefd..0d42388e 100644 --- a/examples/datavisualization/graphgallery/main.cpp +++ b/examples/datavisualization/graphgallery/main.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "bargraph.h" +#include "scattergraph.h" #include #include @@ -18,12 +19,19 @@ int main(int argc, char **argv) if (!bars->initialize()) return -1; - // Create a tab widget for creating own tabs for Bars3D, Scatter3D, and Surface3D + // Create scatter graph + ScatterGraph *scatter = new ScatterGraph(); + if (!scatter->initialize()) + return -1; + + // Create a tab widget for creating own tabs for Q3DBars, Q3DScatter, and Q3DSurface QTabWidget *tabWidget = new QTabWidget(); tabWidget->setWindowTitle(QLatin1String("Graph Gallery")); // Add bars widget tabWidget->addTab(bars->barsWidget(), QLatin1String("Bar Graph")); + // Add scatter widget + tabWidget->addTab(scatter->scatterWidget(), QLatin1String("Scatter Graph")); tabWidget->show(); return app.exec(); diff --git a/examples/datavisualization/graphgallery/rainfalldata.cpp b/examples/datavisualization/graphgallery/rainfalldata.cpp index 941e2171..ac366564 100644 --- a/examples/datavisualization/graphgallery/rainfalldata.cpp +++ b/examples/datavisualization/graphgallery/rainfalldata.cpp @@ -40,7 +40,7 @@ RainfallData::RainfallData() months << "January" << "February" << "March" << "April" << "May" << "June" << "July" << "August" << "September" << "October" << "November" << "December"; m_rowAxis->setTitle("Year"); m_colAxis->setTitle("Month"); - m_valueAxis->setTitle("rainfall"); + m_valueAxis->setTitle("rainfall (mm)"); m_valueAxis->setSegmentCount(5); m_rowAxis->setLabels(m_years); m_colAxis->setLabels(months); diff --git a/examples/datavisualization/graphgallery/scatterdatamodifier.cpp b/examples/datavisualization/graphgallery/scatterdatamodifier.cpp new file mode 100644 index 00000000..5dff1548 --- /dev/null +++ b/examples/datavisualization/graphgallery/scatterdatamodifier.cpp @@ -0,0 +1,198 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "scatterdatamodifier.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#define RANDOM_SCATTER // Uncomment this to switch to random scatter + +const int numberOfItems = 10000; +const float curveDivider = 7.5f; +const int lowerNumberOfItems = 900; +const float lowerCurveDivider = 0.75f; + +ScatterDataModifier::ScatterDataModifier(Q3DScatter *scatter) + : m_graph(scatter), + m_itemCount(lowerNumberOfItems), + m_curveDivider(lowerCurveDivider), + //! [7] + m_inputHandler(new AxesInputHandler(scatter)) + //! [7] +{ + //! [0] + m_graph->activeTheme()->setType(Q3DTheme::ThemeStoneMoss); + m_graph->setShadowQuality(QAbstract3DGraph::ShadowQualitySoftHigh); + m_graph->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetFront); + m_graph->scene()->activeCamera()->setZoomLevel(80.f); + //! [0] + + //! [1] + QScatterDataProxy *proxy = new QScatterDataProxy; + QScatter3DSeries *series = new QScatter3DSeries(proxy); + series->setItemLabelFormat(QStringLiteral("@xTitle: @xLabel @yTitle: @yLabel @zTitle: @zLabel")); + series->setMeshSmooth(m_smooth); + m_graph->addSeries(series); + //! [1] + + //! [8] + // Give ownership of the handler to the graph and make it the active handler + m_graph->setActiveInputHandler(m_inputHandler); + //! [8] + + //! [9] + // Give our axes to the input handler + m_inputHandler->setAxes(m_graph->axisX(), m_graph->axisZ(), m_graph->axisY()); + //! [9] + + //! [2] + addData(); + //! [2] +} + +ScatterDataModifier::~ScatterDataModifier() +{ + delete m_graph; +} + +void ScatterDataModifier::addData() +{ + // Configure the axes according to the data + //! [3] + m_graph->axisX()->setTitle("X"); + m_graph->axisY()->setTitle("Y"); + m_graph->axisZ()->setTitle("Z"); + //! [3] + + //! [4] + QScatterDataArray *dataArray = new QScatterDataArray; + dataArray->resize(m_itemCount); + QScatterDataItem *ptrToDataArray = &dataArray->first(); + //! [4] + +#ifdef RANDOM_SCATTER + for (int i = 0; i < m_itemCount; i++) { + ptrToDataArray->setPosition(randVector()); + ptrToDataArray++; + } +#else + //! [5] + float limit = qSqrt(m_itemCount) / 2.0f; + for (int i = -limit; i < limit; i++) { + for (int j = -limit; j < limit; j++) { + ptrToDataArray->setPosition(QVector3D(float(i) + 0.5f, + qCos(qDegreesToRadians(float(i * j) / m_curveDivider)), + float(j) + 0.5f)); + ptrToDataArray++; + } + } + //! [5] +#endif + + //! [6] + m_graph->seriesList().at(0)->dataProxy()->resetArray(dataArray); + //! [6] +} + +void ScatterDataModifier::changeStyle(int style) +{ + QComboBox *comboBox = qobject_cast(sender()); + if (comboBox) { + m_style = QAbstract3DSeries::Mesh(comboBox->itemData(style).toInt()); + if (m_graph->seriesList().size()) + m_graph->seriesList().at(0)->setMesh(m_style); + } +} + +void ScatterDataModifier::setSmoothDots(int smooth) +{ + m_smooth = bool(smooth); + QScatter3DSeries *series = m_graph->seriesList().at(0); + series->setMeshSmooth(m_smooth); +} + +void ScatterDataModifier::changeTheme(int theme) +{ + Q3DTheme *currentTheme = m_graph->activeTheme(); + currentTheme->setType(Q3DTheme::Theme(theme)); + emit backgroundEnabledChanged(currentTheme->isBackgroundEnabled()); + emit gridEnabledChanged(currentTheme->isGridEnabled()); +} + +void ScatterDataModifier::changePresetCamera() +{ + static int preset = Q3DCamera::CameraPresetFrontLow; + + m_graph->scene()->activeCamera()->setCameraPreset((Q3DCamera::CameraPreset)preset); + + if (++preset > Q3DCamera::CameraPresetDirectlyBelow) + preset = Q3DCamera::CameraPresetFrontLow; +} + +void ScatterDataModifier::shadowQualityUpdatedByVisual(QAbstract3DGraph::ShadowQuality sq) +{ + int quality = int(sq); + emit shadowQualityChanged(quality); // connected to a checkbox in scattergraph.cpp +} + +void ScatterDataModifier::changeShadowQuality(int quality) +{ + QAbstract3DGraph::ShadowQuality sq = QAbstract3DGraph::ShadowQuality(quality); + m_graph->setShadowQuality(sq); +} + +void ScatterDataModifier::setBackgroundEnabled(int enabled) +{ + m_graph->activeTheme()->setBackgroundEnabled((bool)enabled); +} + +void ScatterDataModifier::setGridEnabled(int enabled) +{ + m_graph->activeTheme()->setGridEnabled((bool)enabled); +} + +void ScatterDataModifier::toggleItemCount() +{ + if (m_itemCount == numberOfItems) { + m_itemCount = lowerNumberOfItems; + m_curveDivider = lowerCurveDivider; + } else { + m_itemCount = numberOfItems; + m_curveDivider = curveDivider; + } + m_graph->seriesList().at(0)->dataProxy()->resetArray(0); + addData(); +} + +void ScatterDataModifier::toggleRanges() +{ + if (!m_autoAdjust) { + m_graph->axisX()->setAutoAdjustRange(true); + m_graph->axisZ()->setAutoAdjustRange(true); + m_inputHandler->setDragSpeedModifier(1.5f); + m_autoAdjust = true; + } else { + m_graph->axisX()->setRange(-10.0f, 10.0f); + m_graph->axisZ()->setRange(-10.0f, 10.0f); + m_inputHandler->setDragSpeedModifier(15.0f); + m_autoAdjust = false; + } +} + +QVector3D ScatterDataModifier::randVector() +{ + return QVector3D( + (float)(QRandomGenerator::global()->bounded(100)) / 2.0f - + (float)(QRandomGenerator::global()->bounded(100)) / 2.0f, + (float)(QRandomGenerator::global()->bounded(100)) / 100.0f - + (float)(QRandomGenerator::global()->bounded(100)) / 100.0f, + (float)(QRandomGenerator::global()->bounded(100)) / 2.0f - + (float)(QRandomGenerator::global()->bounded(100)) / 2.0f); +} diff --git a/examples/datavisualization/graphgallery/scatterdatamodifier.h b/examples/datavisualization/graphgallery/scatterdatamodifier.h new file mode 100644 index 00000000..5b6a1c9f --- /dev/null +++ b/examples/datavisualization/graphgallery/scatterdatamodifier.h @@ -0,0 +1,50 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef SCATTERDATAMODIFIER_H +#define SCATTERDATAMODIFIER_H + +#include "axesinputhandler.h" + +#include +#include + +class ScatterDataModifier : public QObject +{ + Q_OBJECT +public: + explicit ScatterDataModifier(Q3DScatter *scatter); + ~ScatterDataModifier(); + + void addData(); + +public Q_SLOTS: + void setBackgroundEnabled(int enabled); + void setGridEnabled(int enabled); + void setSmoothDots(int smooth); + void changePresetCamera(); + void toggleItemCount(); + void toggleRanges(); + void changeStyle(int style); + void changeTheme(int theme); + void changeShadowQuality(int quality); + void shadowQualityUpdatedByVisual(QAbstract3DGraph::ShadowQuality shadowQuality); + +Q_SIGNALS: + void backgroundEnabledChanged(bool enabled); + void gridEnabledChanged(bool enabled); + void shadowQualityChanged(int quality); + +private: + QVector3D randVector(); + Q3DScatter *m_graph = nullptr; + QAbstract3DSeries::Mesh m_style = QAbstract3DSeries::MeshSphere; + bool m_smooth = true; + int m_itemCount; + float m_curveDivider; + + AxesInputHandler *m_inputHandler; + bool m_autoAdjust = true; +}; + +#endif diff --git a/examples/datavisualization/graphgallery/scattergraph.cpp b/examples/datavisualization/graphgallery/scattergraph.cpp new file mode 100644 index 00000000..17bb485b --- /dev/null +++ b/examples/datavisualization/graphgallery/scattergraph.cpp @@ -0,0 +1,149 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "scattergraph.h" +#include "scatterdatamodifier.h" + +#include +#include +#include +#include +#include +#include + +ScatterGraph::ScatterGraph() +{ + m_scatterGraph = new Q3DScatter(); + m_container = QWidget::createWindowContainer(m_scatterGraph); +} + +ScatterGraph::~ScatterGraph() +{ + delete m_container; +} + +bool ScatterGraph::initialize() +{ + if (!m_scatterGraph->hasContext()) { + QMessageBox msgBox; + msgBox.setText("Couldn't initialize the OpenGL context."); + msgBox.exec(); + return -1; + } + + QSize screenSize = m_scatterGraph->screen()->size(); + m_container->setMinimumSize(QSize(screenSize.width() / 2, screenSize.height() / 1.75)); + m_container->setMaximumSize(screenSize); + m_container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + m_container->setFocusPolicy(Qt::StrongFocus); + + m_scatterWidget = new QWidget; + QHBoxLayout *hLayout = new QHBoxLayout(m_scatterWidget); + QVBoxLayout *vLayout = new QVBoxLayout(); + hLayout->addWidget(m_container, 1); + hLayout->addLayout(vLayout); + + QCommandLinkButton *cameraButton = new QCommandLinkButton(m_scatterWidget); + cameraButton->setText(QStringLiteral("Change camera preset")); + cameraButton->setDescription(QStringLiteral("Switch between a number of preset camera positions")); + cameraButton->setIconSize(QSize(0, 0)); + + QCommandLinkButton *itemCountButton = new QCommandLinkButton(m_scatterWidget); + itemCountButton->setText(QStringLiteral("Toggle item count")); + itemCountButton->setDescription(QStringLiteral("Switch between 900 and 10000 data points")); + itemCountButton->setIconSize(QSize(0, 0)); + + QCommandLinkButton *rangeButton = new QCommandLinkButton(m_scatterWidget); + rangeButton->setText(QStringLiteral("Toggle axis ranges")); + rangeButton->setDescription(QStringLiteral("Switch between automatic axis ranges and preset ranges")); + rangeButton->setIconSize(QSize(0, 0)); + + QCheckBox *backgroundCheckBox = new QCheckBox(m_scatterWidget); + backgroundCheckBox->setText(QStringLiteral("Show background")); + backgroundCheckBox->setChecked(true); + + QCheckBox *gridCheckBox = new QCheckBox(m_scatterWidget); + gridCheckBox->setText(QStringLiteral("Show grid")); + gridCheckBox->setChecked(true); + + QCheckBox *smoothCheckBox = new QCheckBox(m_scatterWidget); + smoothCheckBox->setText(QStringLiteral("Smooth dots")); + smoothCheckBox->setChecked(true); + + QComboBox *itemStyleList = new QComboBox(m_scatterWidget); + itemStyleList->addItem(QStringLiteral("Sphere"), int(QAbstract3DSeries::MeshSphere)); + itemStyleList->addItem(QStringLiteral("Cube"), int(QAbstract3DSeries::MeshCube)); + itemStyleList->addItem(QStringLiteral("Minimal"), int(QAbstract3DSeries::MeshMinimal)); + itemStyleList->addItem(QStringLiteral("Point"), int(QAbstract3DSeries::MeshPoint)); + itemStyleList->setCurrentIndex(0); + + QComboBox *themeList = new QComboBox(m_scatterWidget); + themeList->addItem(QStringLiteral("Qt")); + themeList->addItem(QStringLiteral("Primary Colors")); + themeList->addItem(QStringLiteral("Digia")); + themeList->addItem(QStringLiteral("Stone Moss")); + themeList->addItem(QStringLiteral("Army Blue")); + themeList->addItem(QStringLiteral("Retro")); + themeList->addItem(QStringLiteral("Ebony")); + themeList->addItem(QStringLiteral("Isabelle")); + themeList->setCurrentIndex(3); + + QComboBox *shadowQuality = new QComboBox(m_scatterWidget); + shadowQuality->addItem(QStringLiteral("None")); + shadowQuality->addItem(QStringLiteral("Low")); + shadowQuality->addItem(QStringLiteral("Medium")); + shadowQuality->addItem(QStringLiteral("High")); + shadowQuality->addItem(QStringLiteral("Low Soft")); + shadowQuality->addItem(QStringLiteral("Medium Soft")); + shadowQuality->addItem(QStringLiteral("High Soft")); + shadowQuality->setCurrentIndex(6); + + vLayout->addWidget(cameraButton); + vLayout->addWidget(itemCountButton); + vLayout->addWidget(rangeButton); + vLayout->addWidget(backgroundCheckBox); + vLayout->addWidget(gridCheckBox); + vLayout->addWidget(smoothCheckBox); + vLayout->addWidget(new QLabel(QStringLiteral("Change dot style"))); + vLayout->addWidget(itemStyleList); + vLayout->addWidget(new QLabel(QStringLiteral("Change theme"))); + vLayout->addWidget(themeList); + vLayout->addWidget(new QLabel(QStringLiteral("Adjust shadow quality"))); + vLayout->addWidget(shadowQuality, 1, Qt::AlignTop); + + ScatterDataModifier *modifier = new ScatterDataModifier(m_scatterGraph); + + QObject::connect(cameraButton, &QCommandLinkButton::clicked, modifier, + &ScatterDataModifier::changePresetCamera); + QObject::connect(itemCountButton, &QCommandLinkButton::clicked, modifier, + &ScatterDataModifier::toggleItemCount); + QObject::connect(rangeButton, &QCommandLinkButton::clicked, modifier, + &ScatterDataModifier::toggleRanges); + + QObject::connect(backgroundCheckBox, &QCheckBox::stateChanged, modifier, + &ScatterDataModifier::setBackgroundEnabled); + QObject::connect(gridCheckBox, &QCheckBox::stateChanged, modifier, + &ScatterDataModifier::setGridEnabled); + QObject::connect(smoothCheckBox, &QCheckBox::stateChanged, modifier, + &ScatterDataModifier::setSmoothDots); + + QObject::connect(modifier, &ScatterDataModifier::backgroundEnabledChanged, + backgroundCheckBox, &QCheckBox::setChecked); + QObject::connect(modifier, &ScatterDataModifier::gridEnabledChanged, + gridCheckBox, &QCheckBox::setChecked); + QObject::connect(itemStyleList, &QComboBox::currentIndexChanged, modifier, + qOverload(&ScatterDataModifier::changeStyle)); + + QObject::connect(themeList, &QComboBox::currentIndexChanged, modifier, + qOverload(&ScatterDataModifier::changeTheme)); + + QObject::connect(shadowQuality, &QComboBox::currentIndexChanged, modifier, + qOverload(&ScatterDataModifier::changeShadowQuality)); + + QObject::connect(modifier, &ScatterDataModifier::shadowQualityChanged, shadowQuality, + &QComboBox::setCurrentIndex); + QObject::connect(m_scatterGraph, &Q3DScatter::shadowQualityChanged, modifier, + &ScatterDataModifier::shadowQualityUpdatedByVisual); + + return true; +} diff --git a/examples/datavisualization/graphgallery/scattergraph.h b/examples/datavisualization/graphgallery/scattergraph.h new file mode 100644 index 00000000..6e34082d --- /dev/null +++ b/examples/datavisualization/graphgallery/scattergraph.h @@ -0,0 +1,26 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef SCATTERGRAPH_H +#define SCATTERGRAPH_H + +#include +#include + +class ScatterGraph : public QObject +{ + Q_OBJECT +public: + explicit ScatterGraph(); + ~ScatterGraph(); + + bool initialize(); + QWidget *scatterWidget() { return m_scatterWidget; } + +private: + Q3DScatter *m_scatterGraph = nullptr; + QWidget *m_container = nullptr; + QWidget *m_scatterWidget = nullptr; +}; + +#endif diff --git a/examples/datavisualization/scatter/CMakeLists.txt b/examples/datavisualization/scatter/CMakeLists.txt deleted file mode 100644 index 9bcdaacf..00000000 --- a/examples/datavisualization/scatter/CMakeLists.txt +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -cmake_minimum_required(VERSION 3.16) -project(scatter LANGUAGES CXX) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(CMAKE_AUTOMOC ON) -set(CMAKE_AUTORCC ON) -set(CMAKE_AUTOUIC ON) - -if(NOT DEFINED INSTALL_EXAMPLESDIR) - set(INSTALL_EXAMPLESDIR "examples") -endif() - -set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}") - -find_package(Qt6 COMPONENTS Core) -find_package(Qt6 COMPONENTS Gui) -find_package(Qt6 COMPONENTS Widgets) -find_package(Qt6 COMPONENTS DataVisualization) - -qt_add_executable(scatter - main.cpp - scatterdatamodifier.cpp scatterdatamodifier.h -) -set_target_properties(scatter PROPERTIES - WIN32_EXECUTABLE TRUE - MACOSX_BUNDLE TRUE -) -target_link_libraries(scatter PUBLIC - Qt::Core - Qt::Gui - Qt::Widgets - Qt::DataVisualization -) - -install(TARGETS scatter - RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" - BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" - LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" -) diff --git a/examples/datavisualization/scatter/doc/images/scatter-example.png b/examples/datavisualization/scatter/doc/images/scatter-example.png deleted file mode 100644 index 82c13855..00000000 Binary files a/examples/datavisualization/scatter/doc/images/scatter-example.png and /dev/null differ diff --git a/examples/datavisualization/scatter/doc/src/scatter.qdoc b/examples/datavisualization/scatter/doc/src/scatter.qdoc deleted file mode 100644 index 6322e9cb..00000000 --- a/examples/datavisualization/scatter/doc/src/scatter.qdoc +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example scatter - \meta tags {DataVisualization, Q3DScatter} - \meta category {Graphics} - \title Scatter Graph - \ingroup qtdatavisualization_examples - \brief Using Q3DScatter in a widget application. - - The scatter graph example shows how to make a simple 3D scatter graph using Q3DScatter and - combining the use of widgets for adjusting several adjustable qualities. The example shows - how to: - - \list - \li Create an application with Q3DScatter and some widgets - \li Use QScatterDataProxy to set data to the graph - \li Adjust some graph properties using widget controls - \endlist - - For instructions about how to interact with the graph, see \l{Qt Data Visualization Interacting with Data}{this page}. - - \image scatter-example.png - - \include examples-run.qdocinc - - \section1 Creating the Application - - First, in main.cpp, we create a QApplication, instantiate Q3DScatter, and a window container - for it: - - \snippet scatter/main.cpp 0 - - The call to QWidget::createWindowContainer is required, as all data visualization graph classes - (Q3DBars, Q3DScatter, and Q3DSurface) inherit QWindow. Any class inheriting QWindow cannot be used - as a widget any other way. - - Then we'll create horizontal and vertical layouts. We'll add the graph and the vertical - layout into the horizontal one: - - \snippet scatter/main.cpp 1 - - We're not using the vertical layout for anything yet, but we'll get back to it in - \l {Using widgets to control the graph} - - Next, let's create another class to handle the data addition and other interaction with the - graph. Let's call it \c ScatterDataModifier (See \l {Setting up the graph} and - \l {Adding data to the graph} for details): - - \snippet scatter/main.cpp 2 - - The application main is done. We can show the graph and start the event loop: - - \snippet scatter/main.cpp 3 - - \section1 Setting up the Graph - - Let's set up some visual qualities for the graph in the constructor of the \c ScatterDataModifier - class we instantiated in the application main: - - \snippet scatter/scatterdatamodifier.cpp 0 - - None of these are required, but are used to override graph defaults. You can try how it looks - with the preset defaults by commenting the block above out. - - Finally we create a QScatterDataProxy and the associated QScatter3DSeries. We set custom label format - and mesh smoothing for the series and add it to the graph: - - \snippet scatter/scatterdatamodifier.cpp 2 - - That concludes setting up the graph. - - \section1 Adding Data to the Graph - - The last thing we do in the \c ScatterDataModifier constructor is to add data to the graph: - - \snippet scatter/scatterdatamodifier.cpp 3 - - The actual data addition is done in \c addData() method. First we configure the axes: - - \snippet scatter/scatterdatamodifier.cpp 4 - - This could have been done in the constructor of \c {ScatterDataModifier}, but we added it here - to keep the constructor simpler and the axes configuration near the data. - - Next we create a data array: - - \snippet scatter/scatterdatamodifier.cpp 5 - - and populate it: - - \snippet scatter/scatterdatamodifier.cpp 6 - - Finally we tell the proxy to start using the data we gave it: - - \snippet scatter/scatterdatamodifier.cpp 7 - - Now our graph has the data and is ready to be used. There isn't much interaction yet, though, - so let's continue by adding some widgets to play with. - - \section1 Using Widgets to Control the Graph - - First, back in the application main, we'll create some widgets: - - \snippet scatter/main.cpp 4 - - And add them to the vertical layout we created earlier: - - \snippet scatter/main.cpp 5 - - Now, let's connect them to methods in ScatterDataModifier: - - \snippet scatter/main.cpp 6 - - Here are the methods in ScatterDataModifier the signals were connected to: - - \snippet scatter/scatterdatamodifier.cpp 8 - - And so we have an application in which we can control: - - \list - \li Label style - \li Camera preset - \li Background visibility - \li Grid visibility - \li Dot shading smoothness - \li Dot style - \li Theme - \li Shadow quality - \li Label font - \endlist - - \section1 Example Contents -*/ diff --git a/examples/datavisualization/scatter/main.cpp b/examples/datavisualization/scatter/main.cpp deleted file mode 100644 index 73f412f5..00000000 --- a/examples/datavisualization/scatter/main.cpp +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only - -#include "scatterdatamodifier.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -int main(int argc, char **argv) -{ - qputenv("QSG_RHI_BACKEND", "opengl"); - //! [0] - QApplication app(argc, argv); - Q3DScatter *graph = new Q3DScatter(); - QWidget *container = QWidget::createWindowContainer(graph); - //! [0] - - if (!graph->hasContext()) { - QMessageBox msgBox; - msgBox.setText("Couldn't initialize the OpenGL context."); - msgBox.exec(); - return -1; - } - - QSize screenSize = graph->screen()->size(); - container->setMinimumSize(QSize(screenSize.width() / 2, screenSize.height() / 1.5)); - container->setMaximumSize(screenSize); - container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - container->setFocusPolicy(Qt::StrongFocus); - - //! [1] - QWidget *widget = new QWidget; - QHBoxLayout *hLayout = new QHBoxLayout(widget); - QVBoxLayout *vLayout = new QVBoxLayout(); - hLayout->addWidget(container, 1); - hLayout->addLayout(vLayout); - //! [1] - - widget->setWindowTitle(QStringLiteral("A Cosine Wave")); - - //! [4] - QComboBox *themeList = new QComboBox(widget); - themeList->addItem(QStringLiteral("Qt")); - themeList->addItem(QStringLiteral("Primary Colors")); - themeList->addItem(QStringLiteral("Digia")); - themeList->addItem(QStringLiteral("Stone Moss")); - themeList->addItem(QStringLiteral("Army Blue")); - themeList->addItem(QStringLiteral("Retro")); - themeList->addItem(QStringLiteral("Ebony")); - themeList->addItem(QStringLiteral("Isabelle")); - themeList->setCurrentIndex(6); - - QPushButton *labelButton = new QPushButton(widget); - labelButton->setText(QStringLiteral("Change label style")); - - QCheckBox *smoothCheckBox = new QCheckBox(widget); - smoothCheckBox->setText(QStringLiteral("Smooth dots")); - smoothCheckBox->setChecked(true); - - QComboBox *itemStyleList = new QComboBox(widget); - itemStyleList->addItem(QStringLiteral("Sphere"), int(QAbstract3DSeries::MeshSphere)); - itemStyleList->addItem(QStringLiteral("Cube"), int(QAbstract3DSeries::MeshCube)); - itemStyleList->addItem(QStringLiteral("Minimal"), int(QAbstract3DSeries::MeshMinimal)); - itemStyleList->addItem(QStringLiteral("Point"), int(QAbstract3DSeries::MeshPoint)); - itemStyleList->setCurrentIndex(0); - - QPushButton *cameraButton = new QPushButton(widget); - cameraButton->setText(QStringLiteral("Change camera preset")); - - QPushButton *itemCountButton = new QPushButton(widget); - itemCountButton->setText(QStringLiteral("Toggle item count")); - - QCheckBox *backgroundCheckBox = new QCheckBox(widget); - backgroundCheckBox->setText(QStringLiteral("Show background")); - backgroundCheckBox->setChecked(true); - - QCheckBox *gridCheckBox = new QCheckBox(widget); - gridCheckBox->setText(QStringLiteral("Show grid")); - gridCheckBox->setChecked(true); - - QComboBox *shadowQuality = new QComboBox(widget); - shadowQuality->addItem(QStringLiteral("None")); - shadowQuality->addItem(QStringLiteral("Low")); - shadowQuality->addItem(QStringLiteral("Medium")); - shadowQuality->addItem(QStringLiteral("High")); - shadowQuality->addItem(QStringLiteral("Low Soft")); - shadowQuality->addItem(QStringLiteral("Medium Soft")); - shadowQuality->addItem(QStringLiteral("High Soft")); - shadowQuality->setCurrentIndex(4); - - QFontComboBox *fontList = new QFontComboBox(widget); - fontList->setCurrentFont(QFont("Arial")); - //! [4] - - //! [5] - vLayout->addWidget(labelButton, 0, Qt::AlignTop); - vLayout->addWidget(cameraButton, 0, Qt::AlignTop); - vLayout->addWidget(itemCountButton, 0, Qt::AlignTop); - vLayout->addWidget(backgroundCheckBox); - vLayout->addWidget(gridCheckBox); - vLayout->addWidget(smoothCheckBox, 0, Qt::AlignTop); - vLayout->addWidget(new QLabel(QStringLiteral("Change dot style"))); - vLayout->addWidget(itemStyleList); - vLayout->addWidget(new QLabel(QStringLiteral("Change theme"))); - vLayout->addWidget(themeList); - vLayout->addWidget(new QLabel(QStringLiteral("Adjust shadow quality"))); - vLayout->addWidget(shadowQuality); - vLayout->addWidget(new QLabel(QStringLiteral("Change font"))); - vLayout->addWidget(fontList, 1, Qt::AlignTop); - //! [5] - - //! [2] - ScatterDataModifier *modifier = new ScatterDataModifier(graph); - //! [2] - - //! [6] - QObject::connect(cameraButton, &QPushButton::clicked, modifier, - &ScatterDataModifier::changePresetCamera); - QObject::connect(labelButton, &QPushButton::clicked, modifier, - &ScatterDataModifier::changeLabelStyle); - QObject::connect(itemCountButton, &QPushButton::clicked, modifier, - &ScatterDataModifier::toggleItemCount); - - QObject::connect(backgroundCheckBox, &QCheckBox::stateChanged, modifier, - &ScatterDataModifier::setBackgroundEnabled); - QObject::connect(gridCheckBox, &QCheckBox::stateChanged, modifier, - &ScatterDataModifier::setGridEnabled); - QObject::connect(smoothCheckBox, &QCheckBox::stateChanged, modifier, - &ScatterDataModifier::setSmoothDots); - - QObject::connect(modifier, &ScatterDataModifier::backgroundEnabledChanged, - backgroundCheckBox, &QCheckBox::setChecked); - QObject::connect(modifier, &ScatterDataModifier::gridEnabledChanged, - gridCheckBox, &QCheckBox::setChecked); - QObject::connect(itemStyleList, &QComboBox::currentIndexChanged, modifier, - qOverload(&ScatterDataModifier::changeStyle)); - - QObject::connect(themeList, &QComboBox::currentIndexChanged, modifier, - qOverload(&ScatterDataModifier::changeTheme)); - - QObject::connect(shadowQuality, &QComboBox::currentIndexChanged, modifier, - qOverload(&ScatterDataModifier::changeShadowQuality)); - - QObject::connect(modifier, &ScatterDataModifier::shadowQualityChanged, shadowQuality, - &QComboBox::setCurrentIndex); - QObject::connect(graph, &Q3DScatter::shadowQualityChanged, modifier, - &ScatterDataModifier::shadowQualityUpdatedByVisual); - - QObject::connect(fontList, &QFontComboBox::currentFontChanged, modifier, - &ScatterDataModifier::changeFont); - - QObject::connect(modifier, &ScatterDataModifier::fontChanged, fontList, - &QFontComboBox::setCurrentFont); - //! [6] - - //! [3] - widget->show(); - return app.exec(); - //! [3] -} diff --git a/examples/datavisualization/scatter/scatter.pro b/examples/datavisualization/scatter/scatter.pro deleted file mode 100644 index b9f29f9c..00000000 --- a/examples/datavisualization/scatter/scatter.pro +++ /dev/null @@ -1,17 +0,0 @@ -android|ios|winrt { - error( "This example is not supported for android, ios, or winrt." ) -} - -!include( ../examples.pri ) { - error( "Couldn't find the examples.pri file!" ) -} - -SOURCES += main.cpp scatterdatamodifier.cpp -HEADERS += scatterdatamodifier.h - -QT += widgets -requires(qtConfig(combobox)) -requires(qtConfig(fontcombobox)) - -OTHER_FILES += doc/src/* \ - doc/images/* diff --git a/examples/datavisualization/scatter/scatterdatamodifier.cpp b/examples/datavisualization/scatter/scatterdatamodifier.cpp deleted file mode 100644 index f2428d32..00000000 --- a/examples/datavisualization/scatter/scatterdatamodifier.cpp +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only - -#include "scatterdatamodifier.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//#define RANDOM_SCATTER // Uncomment this to switch to random scatter - -const int numberOfItems = 3600; -const float curveDivider = 3.0f; -const int lowerNumberOfItems = 900; -const float lowerCurveDivider = 0.75f; - -ScatterDataModifier::ScatterDataModifier(Q3DScatter *scatter) - : m_graph(scatter), - m_fontSize(40.0f), - m_style(QAbstract3DSeries::MeshSphere), - m_smooth(true), - m_itemCount(lowerNumberOfItems), - m_curveDivider(lowerCurveDivider) -{ - //! [0] - m_graph->activeTheme()->setType(Q3DTheme::ThemeEbony); - QFont font = m_graph->activeTheme()->font(); - font.setPointSize(m_fontSize); - m_graph->activeTheme()->setFont(font); - m_graph->setShadowQuality(QAbstract3DGraph::ShadowQualitySoftLow); - m_graph->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetFront); - //! [0] - - //! [2] - QScatterDataProxy *proxy = new QScatterDataProxy; - QScatter3DSeries *series = new QScatter3DSeries(proxy); - series->setItemLabelFormat(QStringLiteral("@xTitle: @xLabel @yTitle: @yLabel @zTitle: @zLabel")); - series->setMeshSmooth(m_smooth); - m_graph->addSeries(series); - //! [2] - - //! [3] - addData(); - //! [3] -} - -ScatterDataModifier::~ScatterDataModifier() -{ - delete m_graph; -} - -void ScatterDataModifier::addData() -{ - // Configure the axes according to the data - //! [4] - m_graph->axisX()->setTitle("X"); - m_graph->axisY()->setTitle("Y"); - m_graph->axisZ()->setTitle("Z"); - //! [4] - - //! [5] - QScatterDataArray *dataArray = new QScatterDataArray; - dataArray->resize(m_itemCount); - QScatterDataItem *ptrToDataArray = &dataArray->first(); - //! [5] - -#ifdef RANDOM_SCATTER - for (int i = 0; i < m_itemCount; i++) { - ptrToDataArray->setPosition(randVector()); - ptrToDataArray++; - } -#else - //! [6] - float limit = qSqrt(m_itemCount) / 2.0f; - for (int i = -limit; i < limit; i++) { - for (int j = -limit; j < limit; j++) { - ptrToDataArray->setPosition(QVector3D(float(i) + 0.5f, - qCos(qDegreesToRadians(float(i * j) / m_curveDivider)), - float(j) + 0.5f)); - ptrToDataArray++; - } - } - //! [6] -#endif - - //! [7] - m_graph->seriesList().at(0)->dataProxy()->resetArray(dataArray); - //! [7] -} - -//! [8] -void ScatterDataModifier::changeStyle(int style) -{ - QComboBox *comboBox = qobject_cast(sender()); - if (comboBox) { - m_style = QAbstract3DSeries::Mesh(comboBox->itemData(style).toInt()); - if (m_graph->seriesList().size()) - m_graph->seriesList().at(0)->setMesh(m_style); - } -} - -void ScatterDataModifier::setSmoothDots(int smooth) -{ - m_smooth = bool(smooth); - QScatter3DSeries *series = m_graph->seriesList().at(0); - series->setMeshSmooth(m_smooth); -} - -void ScatterDataModifier::changeTheme(int theme) -{ - Q3DTheme *currentTheme = m_graph->activeTheme(); - currentTheme->setType(Q3DTheme::Theme(theme)); - emit backgroundEnabledChanged(currentTheme->isBackgroundEnabled()); - emit gridEnabledChanged(currentTheme->isGridEnabled()); - emit fontChanged(currentTheme->font()); -} - -void ScatterDataModifier::changePresetCamera() -{ - static int preset = Q3DCamera::CameraPresetFrontLow; - - m_graph->scene()->activeCamera()->setCameraPreset((Q3DCamera::CameraPreset)preset); - - if (++preset > Q3DCamera::CameraPresetDirectlyBelow) - preset = Q3DCamera::CameraPresetFrontLow; -} - -void ScatterDataModifier::changeLabelStyle() -{ - m_graph->activeTheme()->setLabelBackgroundEnabled(!m_graph->activeTheme()->isLabelBackgroundEnabled()); -} - -void ScatterDataModifier::changeFont(const QFont &font) -{ - QFont newFont = font; - newFont.setPointSizeF(m_fontSize); - m_graph->activeTheme()->setFont(newFont); -} - -void ScatterDataModifier::shadowQualityUpdatedByVisual(QAbstract3DGraph::ShadowQuality sq) -{ - int quality = int(sq); - emit shadowQualityChanged(quality); // connected to a checkbox in main.cpp -} - -void ScatterDataModifier::changeShadowQuality(int quality) -{ - QAbstract3DGraph::ShadowQuality sq = QAbstract3DGraph::ShadowQuality(quality); - m_graph->setShadowQuality(sq); -} - -void ScatterDataModifier::setBackgroundEnabled(int enabled) -{ - m_graph->activeTheme()->setBackgroundEnabled((bool)enabled); -} - -void ScatterDataModifier::setGridEnabled(int enabled) -{ - m_graph->activeTheme()->setGridEnabled((bool)enabled); -} -//! [8] - -void ScatterDataModifier::toggleItemCount() -{ - if (m_itemCount == numberOfItems) { - m_itemCount = lowerNumberOfItems; - m_curveDivider = lowerCurveDivider; - } else { - m_itemCount = numberOfItems; - m_curveDivider = curveDivider; - } - m_graph->seriesList().at(0)->dataProxy()->resetArray(0); - addData(); -} - -QVector3D ScatterDataModifier::randVector() -{ - return QVector3D( - (float)(QRandomGenerator::global()->bounded(100)) / 2.0f - - (float)(QRandomGenerator::global()->bounded(100)) / 2.0f, - (float)(QRandomGenerator::global()->bounded(100)) / 100.0f - - (float)(QRandomGenerator::global()->bounded(100)) / 100.0f, - (float)(QRandomGenerator::global()->bounded(100)) / 2.0f - - (float)(QRandomGenerator::global()->bounded(100)) / 2.0f); -} diff --git a/examples/datavisualization/scatter/scatterdatamodifier.h b/examples/datavisualization/scatter/scatterdatamodifier.h deleted file mode 100644 index 2726c70f..00000000 --- a/examples/datavisualization/scatter/scatterdatamodifier.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only - -#ifndef SCATTERDATAMODIFIER_H -#define SCATTERDATAMODIFIER_H - -#include -#include -#include - -class ScatterDataModifier : public QObject -{ - Q_OBJECT -public: - explicit ScatterDataModifier(Q3DScatter *scatter); - ~ScatterDataModifier(); - - void addData(); - void changeStyle(); - void changePresetCamera(); - void changeLabelStyle(); - void changeFont(const QFont &font); - void changeFontSize(int fontsize); - void setBackgroundEnabled(int enabled); - void setGridEnabled(int enabled); - void setSmoothDots(int smooth); - void toggleItemCount(); - void start(); - -public Q_SLOTS: - void changeStyle(int style); - void changeTheme(int theme); - void changeShadowQuality(int quality); - void shadowQualityUpdatedByVisual(QAbstract3DGraph::ShadowQuality shadowQuality); - -Q_SIGNALS: - void backgroundEnabledChanged(bool enabled); - void gridEnabledChanged(bool enabled); - void shadowQualityChanged(int quality); - void fontChanged(const QFont &font); - -private: - QVector3D randVector(); - Q3DScatter *m_graph; - int m_fontSize; - QAbstract3DSeries::Mesh m_style; - bool m_smooth; - int m_itemCount; - float m_curveDivider; -}; - -#endif diff --git a/src/datavisualization/doc/src/qtdatavisualization.qdoc b/src/datavisualization/doc/src/qtdatavisualization.qdoc index ea5b2047..68378564 100644 --- a/src/datavisualization/doc/src/qtdatavisualization.qdoc +++ b/src/datavisualization/doc/src/qtdatavisualization.qdoc @@ -113,9 +113,9 @@ QHeightMapSurfaceDataProxy is a specialized proxy for generating a surface graph from a heightmap image. See the QHeightMapSurfaceDataProxy documentation for more information. - The \l{Data from Custom Proxy}{Custom Proxy} example shows how a custom proxy can be created. It - defines a custom data set based on variant lists and an extension of the basic proxy to resolve - that data with an associated mapper. + The \l{Graph Gallery} example shows how a custom proxy can be created, under the + \uicontrol {Bar Graph} tab. It defines a custom data set based on variant lists and an + extension of the basic proxy to resolve that data with an associated mapper. \section1 Dealing with Real-time Data @@ -163,8 +163,8 @@ the default touch controls, see QTouch3DInputHandler. The default handlers must be disabled when using customized input handlers. - The \l{Input Handling for Axes} illustrates how to use a custom input handler - to drag an axis label to move the visible part of the data. + The \l{Graph Gallery} example, under \uicontrol {Scatter Graph} tab, illustrates how to use + a custom input handler to drag an axis label to move the visible part of the data. In addition to perspective projection, orthographic projection can be used to create 2D graphs by replacing the default input handler with one that diff --git a/src/datavisualization/engine/qabstract3dgraph.cpp b/src/datavisualization/engine/qabstract3dgraph.cpp index 8ef9ecf1..35c678f5 100644 --- a/src/datavisualization/engine/qabstract3dgraph.cpp +++ b/src/datavisualization/engine/qabstract3dgraph.cpp @@ -567,7 +567,7 @@ QCustom3DItem *QAbstract3DGraph::selectedCustomItem() const * \c selectedElementChanged signal is emitted. * * The signal can be used for example for implementing custom input handlers, as - * demonstrated by the \l {Input Handling for Axes} example. + * demonstrated in the \l {Graph Gallery} example under \uicontrol {Scatter Graph} tab. * * \sa selectedLabelIndex(), selectedAxis(), selectedCustomItemIndex(), selectedCustomItem(), * Q3DBars::selectedSeries(), Q3DScatter::selectedSeries(), Q3DSurface::selectedSeries(), -- cgit v1.2.3