Drag an errorbar around in a plot in qt - c++

I am using QPainter in Qt 5.9 using C++ to make a plot and update it based on mouse events.
I would like to know how to plot an error bar that is something like this:
-
|
-
Of course the gaps shouldn't be there between the vertical and horizontal lines.
I need to be able to drag the error bar around on the plot and obtain the co-ordiantes of the center position of the error bar when the mouse button is released. So far I have made a plot with axes and labels. Not sure how to get the error bar using QPainter or any other Qt lib class.
Please provide some insight on how make/plot the error bars. Is there a simple way to do that in QPainter ?

If you are using QPainter you should implement drag-n-drop yourself. It's not that difficult if you don't have too many objects on your plot.
Here's the basic idea:
First of all render all objects. Than you need to reimplement mousePressEvent and mouseMoveEvent in your plot widget. In mousePressEvent you should check if you've clicked on the draggable object and define this object as currently being dragged. In mouseMoveEvent just move this object (if there is one) by changing its coordinates and rerender plot.
You will probably want to optimize plotting to avoid full plot rerender at each mouse move tick. This can be achieved by plotting rarely changing objects to QPixmap/QImage, than rendering this QPixmap/QImage on widget and than plotting error bars and all other kinds of objects that could change at each mouse move tick over this pixmap. At each repaint you will need to define if you need to replot just error bars (or some other dynamic objects) or all widget. I personally implement this by defining bool needFullRepaint which is set to false by widget after each render tick and is set to true after some data inside widget changed.
This is kinda low-level approach, it will require high level of skill and some time to be spend but you will be awarded with maximum control of the rendering and interactions with the widget, which is not always possible with the QGraphicsScene or QCharts

It's going to be a fairly involved project for someone who hasn't used Qt before.
You will want to use QGraphicsScene in all likelihood, rather than a QPainter example. QGraphicsScenes are way easier than QPainter for interactive examples.
Use QCharts as a starting point, they have examples for how to plot data and then move items as a result. Check out the callout example, in particular, which has you paint a callout labeling the position of the cursor on the graph.
Look at the "Drag and Drop Robot" example from Qt.
All of these are an excellent starting point for how to implement draggable features to create an interactive plot. Qt makes it easy for a generalized sense: however, for many plotting features (at least until QtCharts), Qt was much more difficult than specialized plotting libraries.

Related

Suggestion wanted for MFC custom scrollbars

I want to make my own scrollbars for a custom drawn plot, like this image, what would be the best way to go?
Scrollbars should:
Only be visible when mouse hover over it (with fade in/out)
Be a part of the x/y axis of the plot, like in the picture
Not have any arrow buttons, just the thumb Thinner than the normal scrollbars
Would you suggest to:
Create everything from scratch, handling paging, scrollwheel etc.
Try to inherit CScrollBar and do my own drawing?
From what I've read, it's not very easy to customize scrollbars in MFC, for example here)
First off, these have to be scrollbar (or other) controls, not window scrollbars (used for scrolling a window).
Second, the statement "it's not very easy to customize scrollbars in MFC", is only partially true. MFC is a "thin wrapper" of Windows API, so you should better refer to the documentation of the Windows scrollbar control.
Then there is the CScrollBar class, but took a short look, and indeed, it does not really offer anything more than the Windows scrollbar does. As for the sample in the link you posted is a new (custom) control (painting everything on its own), i.e. literally "from scratch", not inheriting anything from CScrollBar.
So, you have to look into the Windows scrollbar control, and what it offers. Did take a look, and saw few things. Unfortunately there seems to be no owner-draw functionality. You can process the WM_CTLCOLORSCROLLBAR message, but this only allows you to change colors.
And according to the documentation the background color only. This appears to be the only possible customization, apart from the SBM_ENABLE_ARROWS message, which can hide the arrows. And no fading effect. If these are enough to you, you could try the Windows/MFC scrollbar, otherwise try writing your own.

How to enable mouse popup in QtCharts?

I need a small popup be shown when the mouse hovers over series in my QtChart.
Highcharts (Javascript) has some really nice examples like this one:
How can I implement this QtCharts?
I cannot find any documentation on implementing popups.
As far as I know you will have to do it by yourself. I needed exactly the same and used a simple QWidget embedded in a QGraphicsProxyWidget that I added to the QGraphicsScene of the chart view.
QWidget *popup = new MyPopUpWidget;
QChartView v;
QGraphicsProxyWidget *proxy = v.scene()->addWidget(popup);
// if you want a drop shadow you can use QGraphicsDropShadowEffect
QGraphicsDropShadowEffect* shadow = new QGraphicsDropShadowEffect();
shadow->setOffset(0, 4);
shadow->setBlurRadius(8);
proxy->setGraphicsEffect(shadow);
While this is nice and simple, the positioning of the popup is the actual work. All the simple solutions weren't good enough for me. For example there are signals if your mouse hits a QGraphicsItem (all line items of your charts are QGraphicsItems) but they are usually to small and you only want to react on the actual data points, not on the line segments.
You can override your mouseMove(QMouseMoveEvent *) function and always check your mouse position against all data points and adjust your popup (show/hide, positioning). If you have many points that will be slow, so I used a spatial grid and assigned data points to grid cells initially. Then you only need to check against points within the grid cells around your mouse position.
I didn't find a better solution.

How can I create a QPushButton with a custom (triangular) shape in Qt 5.5?

How can I create a triangular pushbutton in Qt? What is the most simplest way of executing this? I use the designer to create buttons and not code.
Also, I read somewhere that shapes may be changed as long as the frame of the button is still rectangular but I want the frame to adjust according to the shape as well. How can I achieve this?
More detail: I want to place lots of small triangular buttons next to each other with every other triangle flipped. Each triangle button has it's own function, etc (no overlapping borders accepted). Can anyone give me a descriptive explanation for how I might go about this?
The geometry on a QWidget is always a rectangle.
It would be possible to create a QPushButton derivative, override its paintevent and do some nasty painting considering its neighborhood etc. but it would be really a pain...
it is much easier to use a QGraphicsView, QGraphicsScene and add appropriate QGraphicsItem (maybe the QGraphicsPolygonItem?), add them and use their signals/slots or create a derived class for your purposes.
It is not that hard to override the mouseevents to recognize clicks and you can even use the QStyleSheets to let the "button" look like it gets pressed.

Qt: scrolling complex content. Web-Browser engine. Selecting a text

Just curious about scrolling complicated content inside web browser - like application. Lets assume i am using Qt and C++. This is not "how to" question, but more like "how does it work"? Completely derived from my curiosity irrational questions.
I did small experiment.
Created large QWidget 800x60000 px.
Added 300 QWidgets 800x200 px that are painting themselves using QPainter. Each widget prints its unique name to console when paintEvent() is called.
Added (1.) to a QScrollArea 800x800.
When scrolling, i notice redrawing only widgets that are not fully displayed on the screen. It is only 1 widget at a time (scene: http://savepic.ru/2670640.jpg).
So QScrollArea (or QWidget? Who deside what widget to repaint?) is smart - we do not have CPU loaded redrawing all the 300 widgets all the time or memory consumption storing 800x60000 pixmap (-;
Lets assume i want to use mouse to select text and other elements on my "webpage". So i want to be able to mark them (by changing background). How would i implement that? How different web browsers do that? Selecting pictures, text, tables... Should i think about tracking the mouse and drawing gray/blue/pink background boxes behind elements and my custom widgets?
I have another experiment - displaying stack of messages. The scheme is the same, except QPainter is not used here - only QLabels, QTextExits, QPushButtons (scene: http://savepic.ru/2632728.jpg). I can set a flag SelectableByMouse for QLabel, but how do i select more than 1 message?
You could suggest me to use some Qt HTML renderer, but this is not the answer for 'how does it work".

Displaying a popup widget in QT over application border

Let's say that I have an application frame, and I want to show a popup QCalendarWidget over on the right side of the frame. Normally, QT will clip the edges of the QCalendarWidget, cutting it in half and not displaying the rest, as it would be over the right side border.
Is there a way to work around this limitation without resorting to implementing a QDialog?
I want the widget to be visible outside the bounds of it's container.
If you'd show your Calendar, let's say, after a button click, as QDateTimeEditor does, it's contents will not be clipped, cause it do not belong to frame. It will be just a widget, that shows in a dialog manner. And maybe you should even place it in QDialog, that is modal and provides some convenience methods, rather then simple QWidget.
Btw, why don't you want to use QDatetimeEditor?