QCustomPlot QML
-
Hello,
I was trying to integrate a qml program that can represent math expressions. I saw that there were a library for that goal called QCustomPlot and I also saw a example of how can I integrate it with QML: https://www.qcustomplot.com/index.php/support/forum/172However when I run the code I have the following error:
QWidget: Cannot create a QWidget without QApplicationThis is my code:
.pro
QT += quick CONFIG += c++11 QT += script QT += printsupport QT += widgets # The following define makes your compiler emit warnings if you use # any Qt feature that has been marked deprecated (the exact warnings # depend on your compiler). Refer to the documentation for the # deprecated API to know how to port your code away from it. DEFINES += QT_DEPRECATED_WARNINGS # You can also make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. # You can also select to disable deprecated APIs only up to a certain version of Qt. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ calculadorafunciones.cpp \ customplotitem.cpp \ main.cpp \ qcustomplot.cpp RESOURCES += qml.qrc # Additional import path used to resolve QML modules in Qt Creator's code model QML_IMPORT_PATH = # Additional import path used to resolve QML modules just for Qt Quick Designer QML_DESIGNER_IMPORT_PATH = # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target HEADERS += \ calculadorafunciones.h \ customplotitem.h \ qcustomplot.h
main.cpp (There are two comments for two librery because I tried with different options but any of them worked)
//#include <QGuiApplication> #include <QQmlApplicationEngine> #include "exprtk/exprtk.hpp" #include <QQmlContext> #include "calculadorafunciones.h" #include "customplotitem.h" #include <QtWidgets/QApplication> //#include <QApplication> int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); QQmlApplicationEngine engine; qmlRegisterType<CalculadoraFunciones>("mi.calculadora", 1, 0,"MyCalculadora"); qmlRegisterType<CustomPlotItem>("CustomPlot", 1, 0, "CustomPlotItem"); const QUrl url(QStringLiteral("qrc:/main.qml")); QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.load(url); return app.exec(); }
customplotitem.h
#pragma once #include <QtQuick> #include "qcustomplot.h" class QCustomPlot; class CustomPlotItem : public QQuickPaintedItem { Q_OBJECT public: CustomPlotItem( QQuickItem* parent = 0 ); virtual ~CustomPlotItem(); void paint( QPainter* painter ); Q_INVOKABLE void initCustomPlot(); protected: void routeMouseEvents( QMouseEvent* event ); virtual void mousePressEvent( QMouseEvent* event ); virtual void mouseReleaseEvent( QMouseEvent* event ); virtual void mouseMoveEvent( QMouseEvent* event ); virtual void mouseDoubleClickEvent( QMouseEvent* event ); void setupQuadraticDemo( QCustomPlot* customPlot ); private: QCustomPlot* m_CustomPlot; private slots: void graphClicked( QCPAbstractPlottable* plottable ); void onCustomReplot(); void updateCustomPlotSize(); };
customplotitem.cpp
#include "CustomPlotItem.h" #include <QDebug> CustomPlotItem::CustomPlotItem( QQuickItem* parent ) : QQuickPaintedItem( parent ) , m_CustomPlot( nullptr ) { setFlag( QQuickItem::ItemHasContents, true ); // setRenderTarget(QQuickPaintedItem::FramebufferObject); // setAcceptHoverEvents(true); setAcceptedMouseButtons( Qt::AllButtons ); connect( this, &QQuickPaintedItem::widthChanged, this, &CustomPlotItem::updateCustomPlotSize ); connect( this, &QQuickPaintedItem::heightChanged, this, &CustomPlotItem::updateCustomPlotSize ); } CustomPlotItem::~CustomPlotItem() { delete m_CustomPlot; m_CustomPlot = nullptr; } void CustomPlotItem::initCustomPlot() { m_CustomPlot = new QCustomPlot(); updateCustomPlotSize(); setupQuadraticDemo( m_CustomPlot ); connect( m_CustomPlot, &QCustomPlot::afterReplot, this, &CustomPlotItem::onCustomReplot ); m_CustomPlot->replot(); } void CustomPlotItem::paint( QPainter* painter ) { if (m_CustomPlot) { QPixmap picture( boundingRect().size().toSize() ); QCPPainter qcpPainter( &picture ); //m_CustomPlot->replot(); m_CustomPlot->toPainter( &qcpPainter ); painter->drawPixmap( QPoint(), picture ); } } void CustomPlotItem::mousePressEvent( QMouseEvent* event ) { qDebug() << Q_FUNC_INFO; routeMouseEvents( event ); } void CustomPlotItem::mouseReleaseEvent( QMouseEvent* event ) { qDebug() << Q_FUNC_INFO; routeMouseEvents( event ); } void CustomPlotItem::mouseMoveEvent( QMouseEvent* event ) { routeMouseEvents( event ); } void CustomPlotItem::mouseDoubleClickEvent( QMouseEvent* event ) { qDebug() << Q_FUNC_INFO; routeMouseEvents( event ); } void CustomPlotItem::graphClicked( QCPAbstractPlottable* plottable ) { qDebug() << Q_FUNC_INFO << QString( "Clicked on graph '%1 " ).arg( plottable->name() ); } void CustomPlotItem::routeMouseEvents( QMouseEvent* event ) { if (m_CustomPlot) { QMouseEvent* newEvent = new QMouseEvent( event->type(), event->localPos(), event->button(), event->buttons(), event->modifiers() ); //QCoreApplication::sendEvent( m_CustomPlot, newEvent ); QCoreApplication::postEvent( m_CustomPlot, newEvent ); } } void CustomPlotItem::updateCustomPlotSize() { if (m_CustomPlot) { m_CustomPlot->setGeometry( 0, 0, width(), height() ); } } void CustomPlotItem::onCustomReplot() { qDebug() << Q_FUNC_INFO; update(); } void CustomPlotItem::setupQuadraticDemo( QCustomPlot* customPlot ) { // make top right axes clones of bottom left axes: QCPAxisRect* axisRect = customPlot->axisRect(); // generate some data: QVector<double> x( 101 ), y( 101 ); // initialize with entries 0..100 QVector<double> lx( 101 ), ly( 101 ); // initialize with entries 0..100 for (int i = 0; i < 101; ++i) { x[i] = i / 50.0 - 1; // x goes from -1 to 1 y[i] = x[i] * x[i]; // let's plot a quadratic function lx[i] = i / 50.0 - 1; // ly[i] = lx[i]; // linear } // create graph and assign data to it: customPlot->addGraph(); customPlot->graph( 0 )->setPen( QPen( Qt::red ) ); customPlot->graph( 0 )->setData( x, y ); customPlot->addGraph(); customPlot->graph( 1 )->setPen( QPen( Qt::magenta ) ); customPlot->graph( 1 )->setData( lx, ly ); // give the axes some labels: customPlot->xAxis->setLabel( "x" ); customPlot->yAxis->setLabel( "y" ); // set axes ranges, so we see all data: customPlot->xAxis->setRange( -1, 1 ); customPlot->yAxis->setRange( -1, 1 ); customPlot ->setInteractions( QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables ); connect( customPlot, SIGNAL( plottableClick( QCPAbstractPlottable*, QMouseEvent* ) ), this, SLOT( graphClicked( QCPAbstractPlottable* ) ) );
Does anyone know what is wrong?
Thanks for the help -
@Dooham said in QCustomPlot QML:
QWidget: Cannot create a QWidget without QApplication
Do you have any static QWidget derived instances in your app somewhere?
Also, did you try with QApplication instead of QGuiApplication?
From https://doc.qt.io/qt-5/qguiapplication.html
"For QWidget based Qt applications, use QApplication instead, as it provides some functionality needed for creating QWidget instances." -
@jsulm In my Qml file I have some buttons and a textField. This is the file qml:
import QtQuick 2.12 import QtQuick.Controls 2.5 import mi.calculadora 1.0 import CustomPlot 1.0 ApplicationWindow { visible: true width: 640 height: 480 title: qsTr("Hello World") MyCalculadora{ id: miCalculadora } Row{ Button{ text: "Raiz" onClicked: { inputExpresion.text= inputExpresion.text+" sqrt(" } } Button{ text: "Logaritmo" onClicked: { inputExpresion.text= inputExpresion.text+" log(" } } Button{ text: "Coseno" onClicked: { inputExpresion.text= inputExpresion.text+" cos(" } } Button{ text: "Seno" onClicked: { inputExpresion.text= inputExpresion.text+" sin(" } } Button{ text: "Tangente" onClicked: { inputExpresion.text= inputExpresion.text+" tan(" } } Button{ text: "Limpiar" onClicked: { inputExpresion.text= "" } } } Column{ anchors.centerIn: parent TextField{ id: inputExpresion width:150 text: "" focus: true selectByMouse: true inputMethodHints: Qt.ImhDigitsOnly //validator: DoubleValidator{notation: DoubleValidator.StandardNotation} //onEditingFinished: {cuadriculaItem.parametrosCuad[1]=Funciones.deStringADouble(inputParam1.text)} } Button{ id: miBoton text: "Pulsar Aqui" onClicked: { miCalculadora.evaluarFuncion(inputExpresion.text) } } CustomPlotItem{ id:plot height: 100 width: 100 Component.onCompleted: plot.initCustomPlot(); } } }
Yes, I tried with QApplication instead of QGuiApplication.