Hello friends I am resizing and rotating QGraphicsItem using setTransform-method of QGraphicsItem, I am drawing QGraphicsItem of any shape in its paint-method, when I scale item using setTransform method border of QGraphicsItem also gets thicker and I am setting name to QGraphicsItem, it also gets bigger as per scaling factor. So is there any method by which I could draw the border of item and name given using drawtext in paint method remains of same pen width that I am specifying.
You need to make a pen cosmetic with pen.setCosmetic(true) and use this pen to draw border. Cosmetic pen's width doesn't depend on applied transformations.
I recommend using QGraphicsSimpleTextItem or QGraphicsTextItem to draw text in the scene. You can disable text transformation by calling textItem->setFlag(QGraphicsItem::ItemIgnoresTransformations);. It may be convinient to make main graphics item the parent of the text item, so that text item is positioned relative to the main item.
Note that reimplementing QGraphicsItem::paint is not necessary in most cases because built-in QGraphicsItem subclasses satisfy variety of needs.
Related
What I want to do:
In PySide, one could override the paintEvent() method of a QWidget to draw a custom widget. The bounding rect can be customized by overriding the boundingRect() method.
How does one do this in JavaFX? My goal is to create a custom Rectangle object, that draws itself smaller than it's bounding rect.
In context:
I'm creating an MS Paint clone in JavaFX. I'm working on the selection box that you use to select/move pixels around. I want the cursor to change to the appropriate resizing cursor when it is near the outside of the selection box.
However, the bounding rect is the same size as the selection box drawn on the screen, so the cursor only changes when it is on top of the box, but not when near. My solution is to set the bounding rect to larger than the actual selection box is, so the cursor change will occur. Then, override it's paintEvent() equivalent to draw a smaller selection box.
Thanks for your help.
I have a similar use case to you, and asked a similiar question here : Drawing transform independent layout bounds in JavaFX.
The JavaFX API is much higher level though than Java2D or PySide (I am assuming from your snippets, because I actually never heard of it ;) ), it does not allow you to override painting of Nodes, nor can you stop a Node from inheriting its parents transform.
This means that you need a seperate Group parallel to your content where you create the selection box and update it according to your needs (content changes etc.).
Example SceneGraph:
Scene
contentGroup
someShapeFromUser
selectionBoxGroup
selectionBoxOfSomeShapeFromUser
I would like to draw inside a Qt QFrame, however the QFrame will have a border. As far as I understand, the paintEvent receives a QPainter which is associated to the whole frameRect, so I will have to offset my paint operations of the border. Is this correct? Is there a way of getting a QPainter already associated to the inner part of the widget, without the (variable in size) border?
you have to consider the contentsRect contentsRect()-> Returns the area inside the widget's margins.using the return value rect of contensRect() you can restrict to draw anything inside the rect.
One way to do this would be to embed a QWidget inside the QFrame, place it in a simple QVBoxLayout layout or QStackedLayout layout with no margins and paint the QWidget instead. You'll probably get better performance if you simply offset your painting, though.
I have a full size QGLWidget which paints the application background using QPainter (might change to native openGL commands in the future).
On top of this QGLWidget I use QWidgets (non-GL) for the user interface elements. These are, for example, QLineEdits and QPushButtons. I put them into a custom painted QWidget which uses semi-transparent background painting. The paintEvents of the QLineEdit and QPushButton are overwritten and use semi-transparent backgrounds, too.
The whole UI should look like the following (This is a screenshot where I disabled OpenGL and used QWidget instead of QGLWidget for the background. Note the semi-transparent top bar which also draws a shadow (within its own region)):
When the QLineEdit has the focus, it should have a higher opacity but still not fully opaque:
So now, with OpenGL enabled (The background then is a QGLWidget), the semi-transparent widgets above don't paint on top of the background but on (it seems to be) uninitialized data. The image shining through the top bar is sometimes the whole window itself and sometimes other windows currently being on my desktop.
This currently looks like the following (In this screenshot, the data on which the semi-transparent painting operations are painted on seems to be an image of the widget itself, having an offset.):
When I wrote text into the line edit (here: "This is some text which has been there before!"), removed it and set the focus back to the background widget (so the magnifier icon and the placeholder text appear), the previously painted things still shine through (Note that the visible border should not be visible anymore, but also still shines through):
So the problem is: Instead of being painted on top of the underlying widgets, the semi-transparent widget is painted on top of the old results, initially being something like "uninitialized memory".
Why does this happen? How can I solve the problem?
Things you should know before answering:
The background scene is a composition of tiles which are rendered off-screen. So it can be painted very fast and repainting of the background for every little change of the overlay isn't problematic.
The top bar is a custom QWidget with manual painting and arrangement of the contained two widgets (the button and line edit).
The two widgets overwrite the paintEvent, only draw their own (semi-transparent) background when they have focus and don't use frames already provided by Qt. So the white border in the second screenshot is drawn in my custom paintEvent.
I want the background and the composition of overlay widgets to be separately implementable. The background is an AbstractMapView which has some concrete map view classes. The whole window is an AbstractView (there are multiple concrete views, too), which contains both a concrete map view and the overlay widgets, composed in a way itself decides. Therefore, I don't want the logic of the overlay widgets to be part of the underlying map view. (I hope you understood this, as it is a bit complicated.)
This sounds like an issue where the GL content (i.e. your background aka the QGLWidget) is not in the Qt context. While I'm not a pro on GL painting with Qt, you may want to look at this discussion regarding GL painting and a QLabel for some direction/potential hints.
http://www.qtcentre.org/threads/40335-QLabel-on-top-of-a-QGLWidget-background-issue
In short, we here at the office use OpenGL painting and offscreen rendering of maps and it's very important to make sure Qt is aware of the pixels so your foreground widgets can have the semi-transparency applied to their backgrounds.
The particular product we use also renders the map in tiles and supports providing the GL output in a buffer (i.e. it's call a snapshot and is provided as a bitmap) at which point we use the paintEvent of a regular QWidget to paint the buffer so that the painted pixels are in Qt context.
You can define a Qframe with Qt::SplashScreen flag as the search box and set its opacity. Put your widgets inside it such as the search textbox and positon it where it should appear on the mainwindow. It will also be a good idea to reposition it as the mainwindow is moved or resized overriding its moveEvent.
Hi i'm trying to get a photoshop-like behaviour for my QGraphicsScene
The grid in the background should not resize with the call of scale. And I must be able to save the picture with QPixmap::grabWidget(view) but without the background grid. I can probably do it with removing the background layer just before saving the picture, but i'm not sure if its cleanest way to do it.
Any ideas ?
thx.
Question 1
The grid in the background should not resize with the call of scale.
Use the QGraphicsItem::ItemIgnoresTransformations flag.
The item ignores inherited transformations (i.e., its position is
still anchored to its parent, but the parent or view rotation, zoom or
shear transformations are ignored). This flag is useful for keeping
text label items horizontal and unscaled, so they will still be
readable if the view is transformed. When set, the item's view
geometry and scene geometry will be maintained separately.
In order to set this flag use the setFlag function when creating the grid item.
Question 2
I must be able to save the picture with QPixmap::grabWidget(view) but without the
background grid.
Call the hide function on the grid item before calling the grabWidget. After you have grabbed it you show it again by calling the show function.
At the following web page: http://web.mit.edu/qt-dynamic/www/tutorials-tutorial-t3.html
The following sentence is mentioned:
A widget is clipped by its parent and by the widgets in front of it.
What do we mean by such sentence?
Thanks.
Qt has the concept of parent/child widgets. The parent widget is the container of the child widget, all the way up to the main window widget. So this is just saying that a widget will be clipped by its parent (container) widget. This means it won't extend past its parent's boundaries, but will be cut off if it goes beyond. Likewise, a widget is clipped by any widgets in front of it.
First off: the second part of the sentence is no longer true for Qt >= 4.1 where a parent may paint behind its children.
In graphics, clipping describes the limiting of the painting to a given area. E.g. if you drew a line from (0,0) to (100,100) with a clipping rectangle of (50x50)#(0,0), you'd effectively draw a line only from (0,0) to (50,50), ie. all pixels that would have been painted, but lay outside the clipping region, were discarded.
In Qt, painting can optionally be clipped using QPainter methods, but the painting is always implicitly clipped by the QPaintDevice you're operating on. QWidget is a QPaintDevice, and as such, painting outside of its QWidget::rect() will have no effect (= it will be clipped to rect()).
Now, about the second part of the sentence: In older Qt versions, the child widgets would first fill their area with the background color/image, thus effectively clipping the parent's painting to outside the union of all children's geometries. Since Qt 4.1, this behaviour can be disabled by setting the QWidget::autoFillBackground property to false. Indeed, this happens to be the new default, too.
In the autoFillBackground == false case, the child widgets do no longer erase the parent's drawing acting as their background, except where they actually paint. Take a QLabel as an example: with autoFillBackground == false, it merely paints its text, leaving the parent's drawing to shine through as the label's background.