I am new to C++,Qt and Visual Studio and this is my first post on Stack Overflow.
I apologize in advance if this is a repeated question, I tried searching for a similar question but couldn't find one. Let me know if this is a repeated question and I will delete it.
I am trying to create a line plot using QWidget::paintEvent(). The line plot I am drawing is actually a QPainterPath. I want to detect when the mouse hovers over my line plot and so I create a small rectangle where my mouse cursor is and detect when this rectangle intersects with my line plot using bool QPainterPath::intersects() function. The problem is that this function returns true even when my mouse is not exactly over my line plot. In the Image 1 (I am not allowed to embed images yet) my line plot is the thick black curve and the bool QPainterPath::intersects() returns true even when my cursor is over the yellow region. As per the Qt document this is because:
There is an intersection if any of the lines making up the rectangle crosses a part of the path or if any part of the rectangle overlaps with any area enclosed by the path.
There is no way to have a QPainterPath without any enclosed area as Qt only provides two types of fill for QPainterPath: Qt::OddEvenFill or Qt::WindingFill. (To be honest, I find this kind of annoying, since an open path is a series of line segments connected end-to-end, if someone wants to enclose an area they can easily connect the first and last point using either QPainterPath::lineTo() or QPainterPath::moveTo() functions)
Anyway, I decided to get smarter than Qt and drew two extra QPainterPath with pathUp being a few pixels above my line plot and pathDn being a few pixels below my line plot. Image 2 shows these 3 line plots, red one is pathUp, black one is real line plot and green one is pathDn. I thought I coould detect the intersection in the QWidget::mouseMoveEvent() by using the following code:
// cRect: Rectangle at mouse cursor position
if((pathUp.intersects(cRect) && (!pathDn.intersects(cRect))) || ((!pathUp.intersects(cRect)) && pathDn.intersects(cRect)))
{
qDebug() << "Intersects";
}
But this still produces wrong results because now the enclosed area is different, as you can see in Image 3 the green area is an enclosed area of pathDn and red area is the enclosed area of pathUp. The thick black curve is again the line plot that I want to detect my mouse hover on. This enclosed area is not affected by Qt::setFillRule of QPainterPath.
What's even more frustrating is that I tried this technique using QPolygonF instead of QPainterPath on QWidget and the results were exactly the same. I also tried QGraphicsView, there I used QGraphicsPathItem to create my line plot and then used QGraphicsScene::focusItemChanged() signal to detect when I click on my line plot. It again produced the same result of detecting the click when my cursor is over the enclosed area. I do not want to create a custom QGraphicsItem (unless I absolutely have to) just to reimplement it's hoverEnterEvent() and hoverLeaveEvent() method because of the limitations imposed on the boundingRect() of the QGraphicsItem as explained in Qt Docs:
QGraphicsScene expects all items boundingRect() and shape() to remain unchanged unless it is notified. If you want to change an item's geometry in any way, you must first call prepareGeometryChange() to allow QGraphicsScene to update its bookkeeping.
Since I making a plot in real-time the boundingRect() will change quite frequently (> 20 Hz), which will result in an extra computational burden on the software. Is there any way I can solve my problem without creating a custom QGraphicsItem?
P.S. I have been using Stack Overflow for many years whenever I got stuck. I just never made an account here because I never needed to post anything. You guys are the best and I am very happy to be a part of this community!
Related
I have to segment a few things in a dataset I have (.nrrd-file) by drawing a rectangle around the area of interest and saving the segments (also as .nrrd-files).
I tried everything in the Segmentation-Tool that comes with MITK but I cannot seem to find a way to draw rectangles. I also tried to do some key combos (like holding shift, ctrl or alt) while drawing but in vain.
I know I can use the Measurement-Tool to select rectangles and save them (as .pf-files), but using that I'd have to write a some code to convert those selected rectangles into rectangle segmentations later on.
Does anyone know whether there's a possibility (that I didnt find yet) to draw rectangles in the Segmentation tool, or some other way so there's no need to write a workaround?
You can use the Image Cropper plugin in MITK 2016.11 for rectangular image masking and cropping (scissors icon).
Open the plugin, select your image in the Data Manager and click on the New button in the plugin to create a bounding object. You can modify the rectangular bounding shape in the render windows by dragging its red handles. You can move the whole shape by hovering over the bounding shape (it will turn green), click, and than drag.
Click on the Mask button if you want to get an image with the same dimensions in which all pixels outside the bounding shape are set to a user defined value (see the Advanced settings in the plugin). Click on the Crop button otherwise.
Note that you can always press F1 in any active MITK plugin to open a help page with detailed instructions.
I want to draw a visualization of the stack at certain points while executing a program, so some kind of rectangles, filled with an address and value and in some color, depending on some events. I'm using C++ with Qt.
Right now, my Stackview class holds all StackItems and then uses the paintEvent to draw all of those into my Dialog-window. This window isn't scrollable, so if the stack is bigger, I can't see all stack items or scroll down!
My question is should I use a GraphicsView and a GraphicsScene and add my Rects there or should I do something with a QScrollArea, I'm not sure, what fits my needs best and how to implement it?
The end result should be, that my Debugger can step through code line by line and update the stack, depending on the line.
I have some custom QGraphicsItems in a QGraphicsView of a QGraphicsScene. With items(QPoint(x, y)) method I retrieve all the items at given scene point.
Once these items are drawn they will not be moved, rotated or scaled, so their shapes will not change.
I would to know if there is a way to change the color of the overlapping area only (if I have at least two items, of course).
A different way to write my question is: given a starting point, color the scene until some borders are found.
I have not enough reputation to post an image, so I uploaded three examples of desired results here.
Edit 1: solution from Nejat works if I select a point that actually is within two Items' shapes, but it doesn't work if the point belongs to only one Item or to no Items (I uploaded an example of this case here).
Maybe should I use a different approach? Once painted, I don't need to change an item, so I will be interested also in a "flat/static" pixel-oriented solution. Could I use QImage class?
Edit 2: Nejat's answer was right for the original question. Btw, for my purpose I used a QImage, drawing on it all the shapes and finally using a "flood fill" algorithm to fill the area I wanted.
You can use the QGraphicsItem::shape () which returns a QPainterPath to retrieve the shape of an item. For taking the intersection path this can be used :
QPainterPath QPainterPath::intersected ( const QPainterPath & p ) const;
So you can get the intersection path of two items like:
QPainterPath intersectedPath = item1->shape()->intersected(item2->shape());
Now you can fill the intersected area by :
painter->setBrush(QColor(122, 163, 39));
painter->drawPath(intersectedPath);
I have a class derived from CStatic and on that i m painting lines to show measurement in MFC C++ project. The problem is that I m displaying the line's distance at round about the mid of the line. I m using ExtTextOut function to draw the text. As i m using device context for that, I googled alot to erase that text and redraw on some other location, but i m unable to do. Basically CStatic has an image display over which i m drawing for measurement. Please can anyone tell me how to erase the text drawn through ExtTextOut without harming the background image?
Thanks In advance
I don't think you can just erase the text, leaving what's behind it untouched. You have to redraw the background again.
If you don't want to redraw everything, you can invalidate the part where the text lies (with InvalidateRect or InvalidateRgn) and only that will be redrawn.
Another option, that works with lines but I don't know if it works with text, would be to set the drawing mode with CDC::SetROP2 to R2_XORPEN (I think), draw the text, then draw it again to erase it. By doing it this way, the text will look "mixed" with the background, though.
I subclassed QGraphicsItem and reimplemented paint.
In paint I wrote something like this for labeling the item:
painter->drawText("Test",10,40);
After some time I think It may be useful to handle labeling with seperate item. So I wrote something like this.
QGraphicsTextItem *label = new QGraphicsTextItem("TEST",this);
setPos(10,40);
But two "TEST" drawing do not appear in the same place on screen. I guess difference may be related with item coordinates - scene coordinates. I tried all mapFrom... and mapTo... combinations inside QGraphicsItem interface but no progress. I want to drawings to appear in the same place on screen.
What I miss?
I assume that you are using the same font size and type in both cases. If the difference in position is very small the reason can be the QGraphicTextItem is using some padding for the text it contains. I would try to use QGraphicsSimpleTextItem that is not going to add fancy stuff internally and see if you still have the same problem. The coordinates system is the same one if you use painter or setPost so that is not the problem. If this doesn't help I will suggest to specify the same rect for both to avoid Qt adding it owns separation spaces.