a concerned citizen a concerned citizen - 4 months ago 76
C++ Question

Qt QGraphicsScene add and delete lines

I am (very) new to Qt and I am trying to make a simple plot (without involving external libraries&co), which also has a box, axes, and grid lines, which I want to be able to toggle.

I have the

QGraphicsScene
defined as
scene
where I can use
scene->addLine(...)
, but I don't know how I can remove those lines based on a
QCheckBox
. This is (in short) what I have set in the function
plotAxes()
which will be used with
connect()
:

QGraphicsLineItem *xAxis {new QGraphicsScene::addLine(xMin, 0, xMax, 0, *dashedLine)};
if (boxToggle->isChecked())
{
scene->addItem(xAxis);
//scene->addLine(yCenter, yMin, yCenter, yMax, *dashedLine);
scene->update();
}
else
{
scene->removeItem(xAxis);
scene->update();
}


The code only shows the first axis, if it works for that I can extend to everything else, but it doesn't work. For
xAxis
I tried
QGraphicsItem
,
QGraphicsScene
, combinations, but this isn't how I want to continue. I don't know how to add the line (axis) as a variable, or pointer, and then use that to add/delete to/from the scene. Can someone please tell me how to do it?




[edit]
I'm sorry, forgot to say I want to be able to toggle them without affecting what's already plotted.

Answer

If you have fixed amount of lines, you can store them as member variables and the problem becomes trivial. But I'm going to assume the number of lines can vary. I'm also assuming you have a separate checkbox for each line you wish to show/hide. What you want to do, is use the toggled signal of your checkboxes to hide/show your lines. You can use a QSignalMapper to do this, but I recommend using a lambda expression.

I put an example below that you can just copy-paste and run. Now in this example I used a lambda expression, which requires c++11. If you are using Qt 5.7 (or newer for future reference), I think it is enabled automatically. But if you're using an older version, you'll have to add CONFIG += c++11 in your .pro file.

#include <QApplication>
#include <QGraphicsView>
#include <QLayout>
#include <QCheckBox>
#include <QGraphicsLineItem>

class Widget : public QWidget
{
    Q_OBJECT
public:
    Widget()
    {
        resize(600, 400);
        setLayout(new QVBoxLayout);
        view = new QGraphicsView;
        scene = new QGraphicsScene(this);
        view->setScene(scene);
        layout()->addWidget(view);

        for(int i = 0; i < 5; i++)
        {
            QGraphicsLineItem *line = scene->addLine(0, i * 20, width(), i * 20, Qt::DashLine);
            lines.append(line);

            QCheckBox *checkbox = new QCheckBox(QString("Show line %1").arg(i+1));
            connect(checkbox, &QCheckBox::toggled, [=](bool toggled){line->setVisible(toggled);});
            layout()->addWidget(checkbox);
            checkbox->setChecked(true);
        }
    }

private:
    QGraphicsView *view;
    QGraphicsScene *scene;
    QVector<QGraphicsLineItem*> lines;
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

#include "main.moc"
Comments