QGraphicsView resize issue
-
I have a program which continually captures images from a connected camera.
The captured images are rendered by a QGraphicsView using QGraphicsPixmapItem.
Here's how I initialize my scene/"renderer".void MainWindow::showEvent(QShowEvent* event) { // We have to initialize QGraphicsScene in 'showEvent' function to get correct scene dimensions _graphicsScene = new QGraphicsScene(this); const auto scaledPixmap = _pixmapImage->scaled(ui->GraphicsView->size(), Qt::AspectRatioMode::IgnoreAspectRatio, Qt::TransformationMode::FastTransformation); _pixmapItem = new QGraphicsPixmapItem(scaledPixmap); _graphicsScene->addItem(_pixmapItem); // Set the scene and show ui->GraphicsView->setScene(_graphicsScene); // ... };
The problem is this, if I just capture a single image, then initialize the renderer, it all works fine.
I can resize without issue (Other than the white few-pixel border around the scene).The problem starts when I begin capturing images. I have a background thread which grabs an image from the camera, and signals a function to update the QGraphicsPixmapItem to update the image.
void MainWindow::UpdateImage(const QImage& image) { // Convert 'grabbed' QOmage to QPixmap _pixmapImage->convertFromImage(image); _pixmapItem->setPixmap(_pixmapImage->scaled(ui->GraphicsView->size(), Qt::AspectRatioMode::IgnoreAspectRatio, Qt::TransformationMode::FastTransformation)); };
This all works fine, except for when I resize. When I start resizing while the image-capture is running I get strange scaling issues (see image). When down-scaling, the image "jumps", and leaves behind a white background. On the other hand, if I scale the window up, it jumps beyond the bounds of the window.
Here's how I handle resizing.
void MainWindow::resizeEvent(QResizeEvent* event) { ui->GraphicsView->fitInView(_graphicsScene->sceneRect()); };
Any help is greatly appreciated
-
I have found an solution. It seems you can display images using a
QLabel
.
Instead of usingfitInView
, I can instead resize the image inresizeEvent
handler and display it usingQLabel
, this seems to work perfectly.
Using a label to display images feels hacky. Also, I don't know how this will affect the rest of the development with some feature I'm tasked with adding. So unless this is the only option I have, I'd rather not use this as a solution. -
Hi,
First thing: do not create your scene in the showEvent method, it may be called several times through the lifetime of your application and thus leak objects.
One thing you can do is to disable updates while resizing and then enable them again once done.
Since you are mentioning a camera, would QtMultimedia simplify your life ?
-
@SGaist I'm off work atm, so any code changes will have to wait for tomorrow.
do not create your scene in the showEvent method, it may be called several times through the lifetime of your application and thus leak
This seems similar to the spurious wakeup problem? Even the description of
showEvent
in the docs seems similar. If that's the case,then I'll update the code, when I'm at work again.One thing you can do is to disable updates while resizing and then enable them again once done
Can you be a bit more specific? Which updates should I disable? The window's resize event?
Only resize the scene once we finished resizing? I tried doing that, it seems there's no easy way of only handling the "resizeDone" event.Since you are mentioning a camera, would QtMultimedia simplify your life ?
Thanks for the suggestion, I'll keep that in mind if I need a more "QT" camera interface. But thankfully we already have a pretty good camera API.
-
I was thinking about setUpdatesEnabled.
-
@SGaist Thanks, I'll keep that feature of QT in mind when I'll need it.
I'll be frank, I've opted to use aQLabel
as the image presenter. It's does exactly everything I needed fromQGraphicsView
, without all issues.Which raises the question for me. For what purpose would someone use
QgraphicsView
to present only images, ifQLabel
already does it (Fairly simply). Is there any significant performance reasons, or anything? -
Animation, composition, overlaying and whatever comes to your imagination.
That said, if you are really only showing one single image and nothing more then, indeed, a QLabel is enough.