qwt: howto use QVariant(QwtPlotItem*) for QwtPlotCurve->setVisible?
-
I'm trying to make a graph where the user can choose what traces to have visible.
I do get a signal when the QwtLegend is clicked, but I can't figure out howto choose the correct trace to setVisible().In the slot, I have these variables. On toggles as expected dependent if the label is pressed, but index stays 0. I don't know how to handle iteminfo to extract what tracelabel has just been changed.
const QVariant &iteminfo, bool on, int index
Here's the screenshot after the curve_A,B,C buttons have been clicked a couple of times. Note the visibility of the traces is out of sync with the buttons:
Here's the qdebug output of the program: when first curve_A is clicked two times, then curve_B is clicked two times, then curve_C is clicked two times.
dpi is invalid got from xsettings(Qt/DPI/ and Xft/DPI), fallback to get dpi from QXcbScreen::logicalDpi() dpi is invalid got from xsettings(Qt/DPI/ and Xft/DPI), fallback to get dpi from QXcbScreen::logicalDpi() dpi is invalid got from xsettings(Qt/DPI/ and Xft/DPI), fallback to get dpi from QXcbScreen::logicalDpi() dpi is invalid got from xsettings(Qt/DPI/ and Xft/DPI), fallback to get dpi from QXcbScreen::logicalDpi() Function Name: void MainWindow::slot_qwtlegendChecked(const QVariant&, bool, int) Item: QVariant(QwtPlotItem*, ) on: true index: 0 Function Name: void MainWindow::slot_qwtlegendChecked(const QVariant&, bool, int) Item: QVariant(QwtPlotItem*, ) on: false index: 0 Function Name: void MainWindow::slot_qwtlegendChecked(const QVariant&, bool, int) Item: QVariant(QwtPlotItem*, ) on: true index: 0 Function Name: void MainWindow::slot_qwtlegendChecked(const QVariant&, bool, int) Item: QVariant(QwtPlotItem*, ) on: false index: 0 Function Name: void MainWindow::slot_qwtlegendChecked(const QVariant&, bool, int) Item: QVariant(QwtPlotItem*, ) on: true index: 0 Function Name: void MainWindow::slot_qwtlegendChecked(const QVariant&, bool, int) Item: QVariant(QwtPlotItem*, ) on: false index: 0
Here's the program.
Mainwindow.cpp:#include "mainwindow.h" #include "ui_mainwindow.h" #include <QwtPlot> #include <QwtPlotCurve> #include <QwtPlotGrid> #include <QwtSymbol> #include <QwtLegend> #include <QDebug> #include <QSettings> #include <qwt_magnifier.h> #include <qwt_plot_canvas.h> #include <qwt_plot_magnifier.h> #include <qwt_plot_zoomer.h> #include <qwt_date_scale_draw.h> #include <qdebug.h> #include <qdatetime.h> typedef enum { CURVE_TF_A = 0, CURVE_TF_B, CURVE_TF_C, NUM_TF_CURVES, }TF_CURVES_ENUM; const QString TF_STRINGS [NUM_TF_CURVES] = { "curve_A", "curve_B", "curve_C", }; QwtPlot* plotTF0 = nullptr; QwtPlotGrid* gridTF0 = nullptr; QwtPlotCurve* myCurvesTF[NUM_TF_CURVES]; QPolygonF myPontsTF[NUM_TF_CURVES]; QwtLegend* myLegend0 = nullptr; MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); plotTF0 = new QwtPlot(); gridTF0 = new QwtPlotGrid(); myLegend0 = new QwtLegend(); for (int curve = 0; curve < NUM_TF_CURVES; ++curve) { myCurvesTF[curve] = new QwtPlotCurve(); } myLegend0 -> setDefaultItemMode(QwtLegendData::Checkable); plotTF0->insertLegend( myLegend0 ); connect(myLegend0,&QwtLegend::checked,this,&MainWindow::slot_qwtlegendChecked); myPontsTF[CURVE_TF_A] << QPointF((qreal)0,(qreal)1); myPontsTF[CURVE_TF_A] << QPointF((qreal)1,(qreal)2); myPontsTF[CURVE_TF_A] << QPointF((qreal)2,(qreal)3); myPontsTF[CURVE_TF_B] << QPointF((qreal)0,(qreal)0.5); myPontsTF[CURVE_TF_B] << QPointF((qreal)1,(qreal)1.5); myPontsTF[CURVE_TF_B] << QPointF((qreal)2,(qreal)2.5); myPontsTF[CURVE_TF_C] << QPointF((qreal)0,(qreal)0.7); myPontsTF[CURVE_TF_C] << QPointF((qreal)1,(qreal)1.7); myPontsTF[CURVE_TF_C] << QPointF((qreal)2,(qreal)2.7); for (int i = 0; i < NUM_TF_CURVES; ++i) { myCurvesTF[i]->setSamples(myPontsTF[i]); myCurvesTF[i]->setTitle(TF_STRINGS[i]); //myCurvesTF[i]->setRenderHint( QwtPlotItem::RenderAntialiased, true ); myCurvesTF[i]->attach(plotTF0); qint16 hue = (360/NUM_TF_CURVES) * i; //so each color is as far away as possible from other colors QColor color; color.setHsv(hue,255,255,128); //last number is alpha myCurvesTF[i]->setPen(color,2); } plotTF0->resize( 600, 400 ); plotTF0->show(); } MainWindow::~MainWindow() { delete ui; } void MainWindow::slot_qwtlegendChecked(const QVariant &iteminfo, bool on, int index) { qDebug() << "Function Name: " << Q_FUNC_INFO; qDebug() << "Item: " << iteminfo; qDebug() << "on: " << on; qDebug() << "index: " << index; //(myCurvesTF)iteminfo->setVisible(on); ///home/werk/qwt/mainwindow.cpp:97: error: Member reference type 'const QVariant' is not a pointer; did you mean to use '.'? (fix available) myCurvesTF[index]->setVisible(on); //this works, but index is always 0 plotTF0->replot(); }
mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <qwt_plot.h> // for QwtPlotItem QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private: Ui::MainWindow *ui; private slots: void slot_qwtlegendChecked(const QVariant &itemInfo, bool on, int index); }; #endif // MAINWINDOW_H
main.cpp
#include "mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }
QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets CONFIG += c++17 CONFIG += qwt win32: { INCLUDEPATH += C:\Qwt-6.2.0\include CONFIG(debug, debug|release) { message("Windows debug build") LIBS += -LC:\Qwt-6.2.0\lib\ -lqwtd } CONFIG(release, debug|release) { message("Windows release build") LIBS += -LC:\Qwt-6.2.0\lib\ -lqwt } } unix: { message("Linux build") LIBS += -lqwt } # You can make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ main.cpp \ mainwindow.cpp HEADERS += \ mainwindow.h FORMS += \ mainwindow.ui # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target
-
I forgot to post my versions:
$ uname -a Linux cedric 6.6.1-arch1-1 #1 SMP PREEMPT_DYNAMIC Wed, 08 Nov 2023 16:05:38 +0000 x86_64 GNU/Linux Qt 5.15.11 in PATH(system) $ pacman -Q qt5-base qt5-base 5.15.11+kde+r146-1 $ pacman -Q qwt qwt 6.2.0-1
-
@Cedric-air The QWT CpuPlot example* works, but I can't integrate it into my program.
https://github.com/opencor/qwt/tree/master/examples/cpuplotI get the error ‘infoToItem’ was not declared in this scope in my slot definition:
void MainWindow::slot_qwtlegendChecked(const QVariant &itemInfo, bool onn, int index) { qDebug() << "Function Name: " << Q_FUNC_INFO; qDebug() << "Iteminfo: " << itemInfo; qDebug() << "on: " << onn; qDebug() << "index: " << index; //QwtPlotItem* plotitem = QwtPlot::infoToItem(iteminfo); //error: cannot call member function ‘virtual QwtPlotItem* QwtPlot::infoToItem(const QVariant&) const’ without object //QwtPlotItem* plotItem = infoToItem( itemInfo ); //from cpuplot, error: ‘infoToItem’ was not declared in this scope qDebug() << "plotItem: " << plotItem; if (plotItem) { plotItem->setVisible(on); } }
These are the includes in my program:
#include "mainwindow-cont.h" #include "ui_mainwindow-cont.h" #include <QwtPlot> #include <QwtPlotCurve> #include <QwtPlotGrid> #include <QwtSymbol> #include <QwtLegend> #include <QDebug> #include <QSettings> #include <qwt_magnifier.h> #include <qwt_plot_canvas.h> #include <qwt_plot_magnifier.h> #include <qwt_plot_zoomer.h> #include <qwt_date_scale_draw.h> #include <qwt_plot.h> //for infoToItem #include <qdebug.h> #include <qdatetime.h>
this is the connect line in CpuPlot.cpp
connect( legend, SIGNAL(checked(const QVariant&,bool,int)), SLOT(legendChecked(const QVariant&,bool)) );
this is the slot definition in CpuPlot.cpp
void CpuPlot::legendChecked( const QVariant& itemInfo, bool on ) { QwtPlotItem* plotItem = infoToItem( itemInfo ); if ( plotItem ) showCurve( plotItem, on ); } void CpuPlot::showCurve( QwtPlotItem* item, bool on ) { item->setVisible( on ); QwtLegend* lgd = qobject_cast< QwtLegend* >( legend() ); QList< QWidget* > legendWidgets = lgd->legendWidgets( itemToInfo( item ) ); if ( legendWidgets.size() == 1 ) { QwtLegendLabel* legendLabel = qobject_cast< QwtLegendLabel* >( legendWidgets[0] ); if ( legendLabel ) legendLabel->setChecked( on ); } replot(); }
this is in CpuPlot.h
private Q_SLOTS: void legendChecked( const QVariant&, bool on );
-
@Cedric-air said in qwt: howto use QVariant(QwtPlotItem*) for QwtPlotCurve->setVisible?:
//(myCurvesTF)iteminfo->setVisible(on); ///home/werk/qwt/mainwindow.cpp:97: error: Member reference type 'const QVariant' is not a pointer; did you mean to use '.'? (fix available)
I don't know about the rest of what you have written, but if you were intending to use the
const QVariant &iteminfo
parameter did you try correcting your C++ just as it says?Having said that, you are not going to be able to call a method like
setVisible()
on aconst
variable. Where did you get told that the signal/slot signature should beconst QVariant&, bool, int
? What is this parameter supposed to represent? -
@JonB said in qwt: howto use QVariant(QwtPlotItem*) for QwtPlotCurve->setVisible?:
Having said that, you are not going to be able to call a method like setVisible() on a const variable. Where did you get told that the signal/slot signature should be const QVariant&, bool, int? What is this parameter supposed to represent?
https://qwt.sourceforge.io/class_qwt_legend.html
I didn't know const was optional there. I'll try to see if that makes a difference.
-
@Cedric-air
No, that shows it is not optional, it shows that you should not be trying to alteritemInfo
in the signal/slot. But your commented out/erroneous code was trying to set that visible.