I have a QGraphicsItem with drawn shapes (below image). How do I detect if the mouse pointer is over the circle, the text or the green rect? All shapes were drawn using the painter method (i.e.: painter.drawText()).
Would be possible make this using a QGraphicsItem into its parent (also a QGraphicsItem) and use the hover mouse events?
The solution you suggested is the easiest approach--rather than draw all of the circles from a single GraphicsItem, make each circle its own GraphicsItem and make them children of the original GraphicsItem. Then you can handle mouse hover events individually for each circle.
Related
It appears that in Python graphics.py, new objects are drawn behind existing objects. So if I draw a blue circle and THEN place a rectangular box over half the circle, you find the circle in on top of the rectangular box. The box, even though it was written last, is appearing behind the circle. Is there a way to control this behavior so the rectangle would appear on top of the circle and not behind it? I want to avoid having to undraw the circle, draw the rectangle, then redraw the circle, so that the rectangle is on top of the circle instead of behind it.
Certainly, this becomes more cumbersome as you have more and more overlapped objects.
Say I have an opaque window for the user to click and drag on, creating a selection rectangle. Is it possible to make just that rectangular area transparent, leaving the rest of the window opaque? Kind of like this image. The black being the opaque part and the white being the transparent part. All part of the same widget.
Edit: Transparent as in being able to see behind the window.
As I understood pygame drawing method, the 2nd argument of the blit function (screen.blit(surface, (0,0))) tells pygame where to draw the given surface (like an offset to start drawing from, or rather a placement of the surface on the screen). Although, from recent experimenting, it seems that pygame surfaces placements are fixed, and that (0,0) is used to crop the surface before pygame blit it to the screen, for efficiency purposes.
Are surfaces placement really fixed (is my latter observation correct)? and if so, is there another way to conveniently move an already drawn surface to another position on the screen? Or should i implement my own way of moving complex "drawable" objects?
Thanks!
A pygame.Surface object has no position, it has a size only. Note, the location of the Rect object which is returned by pygame.Surface.get_rect() is always (0, 0).
When you blit a Surface on another Surface, then each pixel is copied and placed at the corresponding position of the destination Surface. Thus always a position has to be specified, when a Surface is blit on a destination Surface.
See also Why is my collision test always returning 'true' and why is the position of the rectangle of the image always wrong (0, 0)?
[...] if so, is there another way to conveniently move an already drawn surface to another position [...]
You have a basic misunderstanding. A Surface cannot be "moved". A Surface is copied on the Surface object which is associated to the game window.
A Surface appears to be moving, because the entire scene is drawn in every frame. First the background is drawn, then the objects (Sprites, Surfaces) are drawn on top of the background and finally the display is updated (in every frame). If an object is placed at a slightly different position in every frame, then the object appears to be moving smoothly.
I use a wx.PaintDC() to draw shapes on a panel. After drawing the shapes, when I left click and drag mouse, a rubberband (transparent rectangle) is drawn over shapes. While dragging the mouse, for each motion of mouse, an EVT_PAINT is sent and everything (all shapes and rectangle) is redrawn.
How do I just draw the rubberband over the existing shapes (I don't want to redraw the shapes), I mean, it would be nice if I can save the existing shapes on some DC object and just draw the rubberband on it. So that the application will draw it faster.
You presumably want to have a look at wx.Overlay. Look here for an example.
I want to set up like the image bellow.
I want differents backgrounds color for QGraphicsView (say, same as window color) and QGraphicsScene (say, white). Also, I want that if some item is drawn out of the scene bounds that part is not rendered (the star 'any item' in img with legs cropped).
I have no clue how to set up this. I'm new on Qt.
PS: I'm using python, but you can examplify in c++ if you feel confortable.
Answering Jeremy Friesner
This is my code applying your tips:
scene = QtGui.QGraphicsScene(0, 0, 256, 256)
scene.setBackgroundBrush(QtGui.QBrush(scene.palette().color(QtGui.QPalette.Window)))
scene.addRect(scene.sceneRect(), QtGui.QPen(QtCore.Qt.NoPen), QtGui.QBrush(QtCore.Qt.white))
scene.addLine(0, 0, 356, 356)
view = QtGui.QGraphicsView(scene)
self.setCentralWidget(view) # we are in a QMainWindow
As you can see, I add a white QRect using scene bounds and a line a bit bigger than the scene bounds. This is the screenshot result of my app (the line is drawn out the scene too):
If the app size is lesser than scene bounds (ie, View <= Scene), the part out the scene is not rendered (bc scroll bars doesn't allow), but if the app is bigger (ie, View > Scene), then it is drawn. How to solve that?
I want different backgrounds color for QGraphicsView (say, same as
window color) and QGraphicsScene (say, white).
A QGraphicsScene object is never directly shown on the screen -- that is to say, it is not a subclass of QWidget and therefore there is no way to add it to your window's widget hierarchy. The only way to view the contents of a QGraphicsScene is by associating a QGraphicsView with the QGraphicsScene and adding the QGraphicsView to the widget hierarchy.
Given that, the solution to your problem should be to simply call setBackgroundBrush(window->palette().color(QPalette::Window)) on your QGraphicsScene object. The QGraphicsView will automatically reflect the background color of the QGraphicsScene.
If you then want the actual contents-area of the QGraphicsScene to be a different color (so that e.g. after you've zoomed out there is a window-background-colored border around a different background-color in the scene-area, as shown in your screenshot), you can get that effect by adding a QGraphicsRect item of the appropriate color and size (as given by QGraphicsScene::sceneRect()) to your scene. (Be sure to call setZValue() on it with a negative value so that it will remain behind all of the other objects in your scene!)
Also, I want that if some item is drawn out of the scene bounds that
part is not rendered (the star 'any item' in img with legs cropped).
AFAIK this is the usual behavior of the QGraphicsView -- any content that is outside the area defined by QGraphicsScene::sceneRect() is automatically clipped to that area. Are you seeing behavior that is different than that?