qt malloc(): smallbin double linked list corrupted - qt

In my Qt widget I sometimes get this error:
malloc(): smallbin double linked list corrupted
It does not happen all the time but I think I have narrowed it down to when it starts.
I have a QGraphicsView and QGraphicsScene and there I'm drawing lines whos points are stored in a vector. Reason for this is I need to pass this points to another library. Once I draw the points I have an option if I click on a line I'm prompted to another window where I can change the coordinates of a line.
ResizeDialog *dialog = new ResizeDialog(this);
dialog->exec();
delete dialog;
The above code is the code I use to open a new QDialog. I know if I use this->close() the
qt malloc(): smallbin double linked list corrupted does not appear but then I lose the instance of QGraphicsView. Reason I need to keep the QGraphicsView window open if I need to chose to add further lines.
Any advice on how I can eliminate this issue wold be helpful.

Rather than using delete dialog;, use dialog->deleteLater();. I assume the small code portion is inside a slot of the object referenced by "this", and direct deletion is source of trouble as ResizeDialog *dialog = new ResizeDialog(this); affect the parent object this.

Related

Adding a high number of QML objects in a QWidget application using QQuickView or QQuickWidget poses performance problem

I'm developping a Qt application in which the user can add QML objects inside a QGraphicsScene. The available QML objects are listed and the user can add as many as he wants.
Until now, I used QQuickWidgets. The QGraphicsScene contains a top-level widget which is the parent of all the QQuickWidgets I create. It works fine, but I have a performance problem. With a high number of objects, the application starts to slow down, and takes too much space in RAM (more than 1.5 GB with the first example I created, containing 400 objects).
I thought it comes from the way QQuickWidgets are handled by Qt, and wanted to try another way, with QQuickViews. To do so I created a root view, converted in a QWidget so I can embed it in my view, which is a QWidget. Then I add a new QQuickView in the root view for each created object.
The creation of the root view, its container and the engine:
_rootView = new QQuickWindow();
_rootView->resize(1024, 720);
_rootView->show();
QWidget *container = QWidget::createWindowContainer(_rootView, this);
container->resize(_rootView->size());
container->setObjectName("TopLevelQmlViewWidget");
_layout->addWidget(container);
_engine = new QQmlEngine(_rootView);
The creation of the QQuickViews representing the objects:
QQuickView *view = new QQuickView(_engine, _rootView);
view->setSource(url);
view->setResizeMode(QQuickView::SizeViewToRootObject);
view->show();
It works, but the problem is that each QQuickView creates its own thread, which doesn't change the way I handle it but takes place in memory. I don't understand why, because I reparent them to the root view.
So my questions are the following :
1 - Is there a way to prevent the QQuickViews to create their own threads ?
2 - Is using QQuickViews, indeed, less memory-consuming than using QQuickWidgets ?
3 - If no, how can I handle adding a big number of QML objects in a QWidget view without consuming too much memory ?
I think using multiple QQuickViews is a bad idea. An application usually only needs one. I would take a look at QQmlComponent instead. Here is an example:
QQmlComponent component(_engine, QUrl::fromLocalFile("MyItem.qml"));
QQuickItem *childItem = qobject_cast<QQuickItem*>(component.create());
childItem->setParentItem(_rootView);
I'm by no means a QML expert. However, here are some pointers I can think of
Avoid mixing and matching QQuick: widget/View.
Consider creating objects dynamically
You can also make use of Loaders, but they have a small amount of extra overhead.
Consider using something like a stack/swipe view to minimize amount of loaded objects.
For best ROI, I'd first try implementing something like stack view and see how much it may help with the RAM. Then go on to create other objects dynamically as needed.
Finally I think QT has a tool that lets you see during runtime the amount of memory of the QML tree. You can look at that and see where your biggest memory hogs are.

Artifacts showing when modifying a custom QGraphicsItem

I'm currently developping a small vector drawing program in wich you can create lines and modify them after creation (those lines are based on a custom QGraphicsItem). For instance, the picture below shows what happens when the leftmost (marked yellow) point of the line is dragged to the right of the screen, effectively lengthening the line :
Everything works fine when the point is moved slowly, however, when moved rapidly, some visual artifacts appear :
The piece of code I'm using to call for a repaint is located in the mouseMoveEvent redefined method, which holds the following lines of code :
QRectF br = boundingRect();
x2 = static_cast<int>(event->scenePos().x()-x());
y2 = static_cast<int>(event->scenePos().y()-y());
update(br);
There's apparently no problem with my boundingRect definition, since adding painter->drawRect(boundingRect()) in the paint method shows this :
And there are also no problem when the line is simply moved (flag QGraphicsItem::ItemIsMovable is set), even rapidly.
Does anyone know what is happening here ? My guess is that update is not being called immediately hence mouseMoveEvent can be called multiple times before a repaint occurs, maybe canceling previous calls ? I'm not sure.
Of course the easy fix is to set the viewport mode of the QGraphicsView object holding the line to QGraphicsView::FullViewportUpdate), but that is ugly (and slow).
Without seeing the full function for how you're updating the line, I would guess that you've omitted to call prepareGeometryChange() before updating the bounding rect of the items.
As the docs state: -
Prepares the item for a geometry change. Call this function before changing the bounding rect of an item to keep QGraphicsScene's index up to date.

QObject::findChild returns null, can't find cross QML objects

I have a question about accessing QML components on the C++ side, sorry it might be little beginner.
I am currently working with the sample map view, the app alone works great, but after I try to put this sample together with a navigation panel, it stopped working.
I have added my own main.qml, another page called menu.qml, and renamed the app's original main.qml to map.qml. So now user would require to navigate the panel like this: main.qml -> menu.qml -> map.qml
My problem is:
Originally, from the sample, app constructor saves a mapView pointer when it creates main.qml so later it can add markers/change location to the mapview.
It gets mapView pointer by calling:
QmlDocument *qml = QmlDocument::create("asset:///main.qml").parent(this);
qml->setContextProperty("_mapViewTest", this);
AbstractPane *root = qml->createRootObject<AbstractPane>();
QObject* mapViewAsQObject = root->findChild<QObject*>(QString("mapViewObj"));
mapView = qobject_cast<bb::cascades::maps::MapView*>(mapViewAsQObject);
However, I have changed the name to map.qml, findChild returned as null. Since my app is unable to find mapView, the whole app crushes when I try to set a marker/locate myself.
I tried to QmlDocument::create("asset:///map.qml"), and use the same method as above to find the mapview, and I was able to get it, but nothing happens when I try to put down a marker/locate.
I have also tried to add a new function that calls findChild and get the mapView pointer. The function gets called in onCreationCompleted inside the map.qml page, but mapViewAsQObject still returned null and app crushed.
Any hints would be really appreciated! Thanks
I have found the solution to my problem, when the next button is clicked, I have to nav push the page using C++, this way it can find the right mapView pointer.
QmlDocument *qml = QmlDocument::create("asset:///map.qml").parent(this);
qml->setContextProperty("_mapViewTest", this);
Page *root = qml->createRootObject<Page>();
QObject* mapViewAsQObject = root->findChild<QObject*>(QString("mapViewObj"));
... etc
nav->push(root);

QwtPlot how to select point(s) curve

I have a QwtPlot that contains some curves and I would like to be able to get the selected point(s) (and curve pointer) from these curves : select a point by clicking and select points by dragging a rect.
I use the following code:
// Picker with click point machine to provide point selection
QwtPlotPicker* clickPicker = new QwtPlotPicker(this->canvas());
clickPicker->setStateMachine(new QwtPickerClickPointMachine);
clickPicker->setMousePattern(0,Qt::LeftButton,Qt::SHIFT);
connect(clickPicker, SIGNAL(appended(QPointF)),
this, SLOT(pointSelected(QPointF)));
// Picker with drag rect machine to provide multiple points selection
QwtPlotPicker* rectPicker = new QwtPlotPicker(
this->xBottom, this->yLeft, QwtPicker::RectRubberBand,
QwtPicker::AlwaysOff, this->canvas());
QwtPickerDragRectMachine* test = new QwtPickerDragRectMachine();
test->setState(QwtPickerMachine::RectSelection);
rectPicker->setStateMachine(test);
connect(rectPicker, SIGNAL(selected(QRectF)),
this, SLOT(pointsSelected(QRectF)));
but the pointSelected slot is called every time I click on the QwtPlot and not only on a curve
BTW, I also try to connect a slot to the signal QwtPlotPicker::selected(const QVector &pa) but it is never emitting ...
I think it is more convenient to use the CanvasPicker as it comes with the examples and can be extended easily.
Please have a look at the event_filter which comes with Qwt. You should use the class CanvasPicker (it is not part of the Qwt API, but you'll find the code in the examples).
You can instantiate it in your class using
picker = new CanvasPicker(plot); // plot is a pointer to your instance of QwtPlot
You'll see that the event filter is installed in the constructor of CanvasPicker.
Now have a look at CanvasPicker::eventFilter(QObject *object, QEvent *e) which is called when an event occurs in the event loop of QwtPlot. Implement your application logic in the switch construct, f.i. change case QEvent::MouseMove:.

QGraphicsScene::clear() clearing scene but not the view

I use a custom class (Configuration) derived from QGraphicsItem and I add its objects to a QGraphicsScene, which is then displayed in a QGraphicsView. Usual stuff. What Im doing exactly is drawing a tree, in multiple steps, one level a step, each node beeing my custom QGraphicsItem.
Here a screenshot. The tree happens to be sequential in the simple case.
I first draw the root node. The signal that triggers that is fired after the user entered a string.
void MainWindow::drawRootSlot(ConfigTreeBuilder & builder)//this is a slot
{
c_scene->clear(); //the clear cause headache. i'll expain
Configuration* conf = new Configuration(builder.getNodesX(), builder.getNodesY(),builder.getNodesConfig());
//code
c_scene->addItem(conf);
//code
}
Each subsequent Configuration is draw inside another slot.
void MainWindow::configTreeSlot(ConfigTreeBuilder & builder) //SLOT!!!
{
while(builder.chooseNextNode()) {
Configuration* conf = new Configuration(builder.getNodesX(), builder.getNodesY(), builder.getNodesConfig());
//code, while loop
QGraphicsLineItem *edge = c_scene->addLine(QLineF(*(parentsPoint), conf->getLeftOrigin()));
edge->setZValue(-1); //below the Configuration item
c_scene->addItem(conf);
}
}
All works fine when done for the first time. When I enter a new string, resetting the tree, dark magic happens. What I expected to it do is: call drawRootSlot(), deleting the whole tree (c_scene->clear()), draw a new root node. And, if I put a debugger breakpoint inside drawRootSlot() this is exactly what happens! But when I run it (without breakpoints), what I get is this:
The previous tree got mangled, but not deleted. The scene gets indeed cleared of its items (printed that) but the view does not reflect that. But again, when I put a breakpoint inside drawRootSlot() thhe view and the scene are in sync.
I tried to delete the scene object, and instaciate a new one instead of calling c_scene->clear(), to guarantee it empty. Then the changes are reflected on the view (the first time drawing always works).
So, I have no idea what to deduce from these symptoms. It works as expected with a breakpoint or with a freshh QGraphicsScene object. It does not when just using c_scene->clear(). One couldsay I just messed up the parent-object/child-object relation, but clear() does remove items from the view... I tried calling it right after c_scene->addItem().
What is this sorrcery? One that makes me believe I'm not actually stupid?
EDIT: Whats interesting and may be a hint to the real problem, is that when c_scene->clear() is called, the edges of the tree, which are normal QGraphicsLineItems, are indeed deleted in all cases (breakpoint or not). Something to do with them not beeing custom?
Ok, calling QGraphicsView::viewport().update() after QGraphicsScene::clear() solved my problems.
But does anyone have an explanaition to the behavior described above?
EDIT: Upon doing doing something else I stumbled upon the actual core of the problem: I messed up the boundingRect() of my GraphicItems, so it was below the visble item, touching only its lower edge (which got deleted, as seen on the screenshot). So now no calls to any update() methods are neccesary.
I think when you call this fitInView() for the graphicsview it cleans up the view from any artifacts that remain from a previous scene.
You can clear both scene and Graphics View
scene->clear();
ui->graphicsView->items().clear();
graphicsView = name of your graphics view
This code will delete both scene and graphics view

Resources