Best approach to displaying a picture for my purposes
-
I have never done anything picturey-graphicy like this, so I want to know what approach I should best take.
I have a
.jpeg
file picture (a map, as it happens, but shouldn't matter). At present I just allow the user to open it via my OS's Image Viewer application, and that's fine. To give an idea, that scales it down to 22% to fit in a comfortable window, and that's what I'll want to do in my own window.Now I want to incorporate into my application. I will want to show it in a window such that I can map the user's mouse position on the pic to a logical coordinate, so I know where the mouse is in map coordinates. I do not intend to put any objects of my own onto it. The only thing I might want is to be able to draw a shape somewhere near the mouse to pick out a small map area.
I can think of a few possibilities:
QLabel
withQPixmap
.QLabel
with HTML<img src=
.- Simple
QWidget
with the.jpg
as a stylesheetbackgroung-image: url()
. - Some kind of direct
QPainter
andQImage
to paint on a window-widget. - Something with
QGraphicsScene
&QGraphicsPixmapItem
.
I have read through the following usefuls:
- https://forum.qt.io/topic/71836/how-to-display-a-picture
- https://doc.qt.io/qt-5/qtwidgets-widgets-imageviewer-example.html
- https://stackoverflow.com/questions/1357960/qt-jpg-image-display
The last one, in particular, seems to have replies suggesting most of these alternatives, but I'm not sure what conclusion to come to. The Qt ImageViewer example is quite a bit of code. I will need to scale-to-fit, but I don't think I'll need its zooming or scrolling as I will just want my pic always scaled to fit completely.
My goal, as ever, is the least complicated with the least code which suffices for my needs. And I don't like doing it one way only to have to change later on to a different way :)
So, which approach is best for me, where should I start from?
-
@J-Hilk , @ollarch , @JKSH , @SimonSchroeder
Dear All,I hope nobody will be offended, but I am going for
QGraphicsScene
, @ollarch's recommendation and the one in the accepted stackoverflow post.I worry terribly about offending anyone, or looking like I don't heed expert advice! :( All of your suggestions/comments have been good. I just feel comfortable with this, and it will give me a chance to play with graphics stuff instead of widgets. I hope that if I eventually come back and say "this may not be the right choice" you won't just say "go away, told you so!" :-;
-
Hello @JonB, have you considered using QML? There are some easy ways of doing what you want to with it: https://doc.qt.io/qt-5/qml-qtquick-image.html
I recommend using QML as a way of separating the UI logic with any other kind of logic your application may have. Also, the code is quite simple and you can create a widget for this and re-use it elsewhere in your application. -
I have never done anything picturey-graphicy like this, so I want to know what approach I should best take.
I have a
.jpeg
file picture (a map, as it happens, but shouldn't matter). At present I just allow the user to open it via my OS's Image Viewer application, and that's fine. To give an idea, that scales it down to 22% to fit in a comfortable window, and that's what I'll want to do in my own window.Now I want to incorporate into my application. I will want to show it in a window such that I can map the user's mouse position on the pic to a logical coordinate, so I know where the mouse is in map coordinates. I do not intend to put any objects of my own onto it. The only thing I might want is to be able to draw a shape somewhere near the mouse to pick out a small map area.
I can think of a few possibilities:
QLabel
withQPixmap
.QLabel
with HTML<img src=
.- Simple
QWidget
with the.jpg
as a stylesheetbackgroung-image: url()
. - Some kind of direct
QPainter
andQImage
to paint on a window-widget. - Something with
QGraphicsScene
&QGraphicsPixmapItem
.
I have read through the following usefuls:
- https://forum.qt.io/topic/71836/how-to-display-a-picture
- https://doc.qt.io/qt-5/qtwidgets-widgets-imageviewer-example.html
- https://stackoverflow.com/questions/1357960/qt-jpg-image-display
The last one, in particular, seems to have replies suggesting most of these alternatives, but I'm not sure what conclusion to come to. The Qt ImageViewer example is quite a bit of code. I will need to scale-to-fit, but I don't think I'll need its zooming or scrolling as I will just want my pic always scaled to fit completely.
My goal, as ever, is the least complicated with the least code which suffices for my needs. And I don't like doing it one way only to have to change later on to a different way :)
So, which approach is best for me, where should I start from?
-
Hello @JonB, have you considered using QML? There are some easy ways of doing what you want to with it: https://doc.qt.io/qt-5/qml-qtquick-image.html
I recommend using QML as a way of separating the UI logic with any other kind of logic your application may have. Also, the code is quite simple and you can create a widget for this and re-use it elsewhere in your application. -
@JonB If you want to stay with c++, which I can understand and respect, I would go with option 4
especially, if you plan to draw custom shapes on it later on
@J-Hilk
So #4 was https://stackoverflow.com/a/48783550/489865 from that stackoverflowvoid SomeWidget::paintEvent(QPaintEvent* event) { QPainter painter(this); QRect rect = event->rect(); painter.drawImage(rect, image, rect); }
In this case, where is my "scale to fit"? (While preserving aspect ratio.)
-
@J-Hilk
So #4 was https://stackoverflow.com/a/48783550/489865 from that stackoverflowvoid SomeWidget::paintEvent(QPaintEvent* event) { QPainter painter(this); QRect rect = event->rect(); painter.drawImage(rect, image, rect); }
In this case, where is my "scale to fit"? (While preserving aspect ratio.)
@JonB
there's a build in functionality for that in drawImageNote: The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
For a more fancy scaling, including fit to aspect ratio . I would suggest overriding/listening to resizeEvent and scaling by hand to the new size constrains,
-
Hi,
Use the QGraphicsView with a QGraphicsScene. The image can be displayed on a QGraphicsPixmapItem or a QGraphicsRectItem (setting the image to the item brush).
To fit the image on the view just add the item and call the view to fit to this item. If the window can be resized you will have to override the resizeEvent of the view and call fit again.
To get the mouse coordinates you have to override the QGraphicsScene::mouseMoveEvent and map the event position to the scene.
This will get you the pixel coordinate. Knowing the map scale resolution you can convert it to world coordinates.Hope it helps.
-
Hi,
Use the QGraphicsView with a QGraphicsScene. The image can be displayed on a QGraphicsPixmapItem or a QGraphicsRectItem (setting the image to the item brush).
To fit the image on the view just add the item and call the view to fit to this item. If the window can be resized you will have to override the resizeEvent of the view and call fit again.
To get the mouse coordinates you have to override the QGraphicsScene::mouseMoveEvent and map the event position to the scene.
This will get you the pixel coordinate. Knowing the map scale resolution you can convert it to world coordinates.Hope it helps.
@ollarch
Yep this all makes sense.You guys are being kind :) But I kind of feel I'm going to end up with as many suggested "best" approaches as the ones I name and are in that stackoverflow post! I wish I knew who is "right" ;-) Maybe it doesn't matter which....
-
@ollarch
Yep this all makes sense.You guys are being kind :) But I kind of feel I'm going to end up with as many suggested "best" approaches as the ones I name and are in that stackoverflow post! I wish I knew who is "right" ;-) Maybe it doesn't matter which....
@JonB said in Best approach to displaying a picture for my purposes:
I wish I knew who is "right" ;-) Maybe it doesn't matter which....
In the first instance, the one who is "right" is the one that produces a reliable, functioning application.
Once that is established, you can try some of the other approaches and see if they give you any improvements (e.g. better code readability/maintainability, better performance, etc.). If an approach is found with significant improvements and few drawbacks, that becomes the new "right" one.
-
I have never done anything picturey-graphicy like this, so I want to know what approach I should best take.
I have a
.jpeg
file picture (a map, as it happens, but shouldn't matter). At present I just allow the user to open it via my OS's Image Viewer application, and that's fine. To give an idea, that scales it down to 22% to fit in a comfortable window, and that's what I'll want to do in my own window.Now I want to incorporate into my application. I will want to show it in a window such that I can map the user's mouse position on the pic to a logical coordinate, so I know where the mouse is in map coordinates. I do not intend to put any objects of my own onto it. The only thing I might want is to be able to draw a shape somewhere near the mouse to pick out a small map area.
I can think of a few possibilities:
QLabel
withQPixmap
.QLabel
with HTML<img src=
.- Simple
QWidget
with the.jpg
as a stylesheetbackgroung-image: url()
. - Some kind of direct
QPainter
andQImage
to paint on a window-widget. - Something with
QGraphicsScene
&QGraphicsPixmapItem
.
I have read through the following usefuls:
- https://forum.qt.io/topic/71836/how-to-display-a-picture
- https://doc.qt.io/qt-5/qtwidgets-widgets-imageviewer-example.html
- https://stackoverflow.com/questions/1357960/qt-jpg-image-display
The last one, in particular, seems to have replies suggesting most of these alternatives, but I'm not sure what conclusion to come to. The Qt ImageViewer example is quite a bit of code. I will need to scale-to-fit, but I don't think I'll need its zooming or scrolling as I will just want my pic always scaled to fit completely.
My goal, as ever, is the least complicated with the least code which suffices for my needs. And I don't like doing it one way only to have to change later on to a different way :)
So, which approach is best for me, where should I start from?
For any solution you need a derived class if you want to calculate the mouse position. Basically, you need to override
mouseMoveEvent
and/ormousePressEvent
.Let's have a quick look at the variants you suggested:
- QLabel with QPixmap.
This is a good solution. However, by default QLabel will not scale the Pixmap for you. I recently had the problem and found a good solution here: https://stackoverflow.com/questions/8211982/qt-resizing-a-qlabel-containing-a-qpixmap-while-keeping-its-aspect-ratio. Still, you need to add code to a derived class to track the mouse.
- QLabel with HTML <img src=.
I am not sure how much control over the size of the image you will have with this approach. It is not one of my favorites, as it adds some complexity by using HTML. Usually, I try to stay clear of any texts that need to be parsed during display as this is slower (even though I never encountered any speed problems with today's computers).
- Simple QWidget with the .jpg as a stylesheet backgroung-image: url().
Here again I am trying to avoid stylesheets as long as possible. It's a similar reasoning as number 2.
- Some kind of direct QPainter and QImage to paint on a window-widget.
As I said already, you need to derive anyway for mouse tracking. Also, as you can see the paint method is quite simple and short.
- Something with QGraphicsScene & QGraphicsPixmapItem.
That sound awfully complicated for such a simple task. I don't recommend this approach as it introduces several layers of indirections.
To sum it up: For a clean solution pick either 1. or 4. In the end it doesn't really matter as the two are quite similar. If done properly, the only major difference will be if you inherit from QWidget or QLabel.
-
Hi,
First of all, using the QGraphicsView is not as complicated as you think. It can be done in less than an hour if its your first time using it.
Second, all the other aproaches resize the image into a widget and when you try to obtain the pixel coordinates in the image you have to take into account that it have been scaled. So, as I said, QGraphicsScene is able to map the view coordinates to the item coordinates to get you the real pixel position. -
Hi,
First of all, using the QGraphicsView is not as complicated as you think. It can be done in less than an hour if its your first time using it.
Second, all the other aproaches resize the image into a widget and when you try to obtain the pixel coordinates in the image you have to take into account that it have been scaled. So, as I said, QGraphicsScene is able to map the view coordinates to the item coordinates to get you the real pixel position.@ollarch
Ah! I was about to go for option #4,QPainter
andQImage
, from other's posts. However, you are persistent in holding your ground! I know I can resize, scale & multiply/divide for coordinates if I do widgets+mouse, but I rather like yourQGraphicsScene is able to map the view coordinates to the item coordinates to get you the real pixel position
as making Qt do the work for me on what I think will be the most common operation I will want to be dong.... :)
What about what @J-Hilk wrote earlier about option #4/
QWidget
:especially, if you plan to draw custom shapes on it later on
? I will probably want to draw a square/hexagon/circle (of a fixed size, just the frame, see-through inside) as I move the mouse around which "snaps" to the nearest such area (calculated by me from coordinates) and is drawn on top of the map to show "where the nearest box for the mouse" is. Is this an issue in widget vs gfx scene/view?
-
@ollarch
Ah! I was about to go for option #4,QPainter
andQImage
, from other's posts. However, you are persistent in holding your ground! I know I can resize, scale & multiply/divide for coordinates if I do widgets+mouse, but I rather like yourQGraphicsScene is able to map the view coordinates to the item coordinates to get you the real pixel position
as making Qt do the work for me on what I think will be the most common operation I will want to be dong.... :)
What about what @J-Hilk wrote earlier about option #4/
QWidget
:especially, if you plan to draw custom shapes on it later on
? I will probably want to draw a square/hexagon/circle (of a fixed size, just the frame, see-through inside) as I move the mouse around which "snaps" to the nearest such area (calculated by me from coordinates) and is drawn on top of the map to show "where the nearest box for the mouse" is. Is this an issue in widget vs gfx scene/view?
-
Hi,
Take a look at QGraphicsScene, specially methods like "addRect", "addLine", "addEllipse", "addPath", "addPolygon", and of course you can derive your own class from QGraphicsItem with your own shape.
Of course that you can do this with option #4, but I think that this is easier, at least for me.
-
@J-Hilk , @ollarch , @JKSH , @SimonSchroeder
Dear All,I hope nobody will be offended, but I am going for
QGraphicsScene
, @ollarch's recommendation and the one in the accepted stackoverflow post.I worry terribly about offending anyone, or looking like I don't heed expert advice! :( All of your suggestions/comments have been good. I just feel comfortable with this, and it will give me a chance to play with graphics stuff instead of widgets. I hope that if I eventually come back and say "this may not be the right choice" you won't just say "go away, told you so!" :-;
-
@J-Hilk , @ollarch , @JKSH , @SimonSchroeder
Dear All,I hope nobody will be offended, but I am going for
QGraphicsScene
, @ollarch's recommendation and the one in the accepted stackoverflow post.I worry terribly about offending anyone, or looking like I don't heed expert advice! :( All of your suggestions/comments have been good. I just feel comfortable with this, and it will give me a chance to play with graphics stuff instead of widgets. I hope that if I eventually come back and say "this may not be the right choice" you won't just say "go away, told you so!" :-;
@JonB I'm sure none of us are offended (I'm certainly not). There were numerous options and you picked one based on features that you believe will be useful for your project. That is sound reasoning.
I hope that if I eventually come back and say "this may not be the right choice" you won't just say "go away, told you so!" :-;
The best way to learn a new tool's strengths and weaknesses is to use it for yourself. After this project, you'll have a much better understanding of
QGraphicsScene
. Then, you'll be better placed to determine how "right" it is for your project. That learning is a worthwhile pursuit in itself.Happy coding, and best of luck!