Drawing on a label that's a layer behind a table - c++

In my application I have a table in the foreground. It has a transparent background so I can see a label with an image through it. Both the table and the label have the exact same size.
I want to draw on the label while the table is still viewable, but not usable. Since the label is a layer behind the table, I just can't draw on it, even if I disable the table and disable the focus. It only works if the label is in the foreground which however would mean that the table is not visible anymore.
I want to draw as soon as I hit a button:
void MainWindow::on_btn_draw_clicked()
{
fg_table->setFocusPolicy(Qt::NoFocus);
fg_table->setEnabled(false);
bg_label->setFocusPolicy(Qt::StrongFocus);
bg_label->setFocus();
}
Which however is not working. The table is disabled and not usable (which is correct), but drawing on bg_label is not possible.
In the Designer the bg_label is a placeholder for the class 'DrawLabel' which inherits from QLabel. In the class drawing is made possible and I can react to various mouse events. Everything works fine and in theory I can draw, but just not if the bg_label is a layer behind the table.
I know that you can raise/lower the layer of a widget with
bg_label->activateWindow();
bg_label->raise();
but this is not what I want. The layers should not be changed and I just want to draw behind the table on bg_label.
Is there any way to achieve this? I haven't seen a similar problem anywhere.

The fact that fg_table is visually transparent is irrelevant. The simple fact is that fg_table will receive all mouse events. Those that it doesn't accept will be propogated to the parent -- not necessarily the widget that appears to be visually underneath -- i.e. bg_label.
Assuming the foreground table doesn't need to interact with mouse events you could probably use...
fg_table->setAttribute(Qt::WA_TransparentForMouseEvents);
That should result in all mouse events going to bg_label.

Related

Drag an errorbar around in a plot in qt

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.

Is it possible to disable the light-blue mouse over highlighting on a QTreeWidgetItem?

I've a QTreeWidget and need to disable the mouse over highlighting on the childItems but not the click selection. The point here is, that I need to set this per Item because some are selectable. I was thinking about the QTreeWidget::itemEntered signal to check if the item should be highlighted or not but I can't get it to work because the description says
QTreeWidget mouse tracking needs to be enabled for this feature to
work.
and I can't figure out how.
So my questions for are: How can I enable mouse tracking?
Is there an easier way to disable the highlighting?
Simply invoke setMouseTracking() to enable mouse tracking for a specific widget.
I ran into this problem (I know this is an old post, but I might as well post my solution, since it can be useful for others).
I could not properly disable the mouse feedback while keeping the mouse tracking enabled, but I could make this feedback invisible. I'm using qss stylesheets, and I set the mousehover feedback color to transparent:
MyTreeWidget::item:hover {
background-color: transparent
}
It did the trick for me. Sadly it makes the feedback invisible all the time, rather than allowing to turn it off and on.
So as a next step, for when I needed it, I implemented my own feedback by using a delegate and overwritting the paint function.
The QTreeView overwrite mouseMoveEvent and sends mouse coordinates to the delegate. This way, the delegate can adapt what it does in paint to this position. It feels pretty heavy, and a bit dirty, but it works. Delegate should also allow to have different behavior for different items.
PS: If you're using a delegate, in most cases, that should be enough without the qss change. In my case it wasn't, because I call QStyledItemDelegate::paint in my overwritten paint method, so I inherited some unwanted behavior.

How to disable ListView select visual effect and draw a rectangle around item instead?

When a ListView item is selected, its color changes to indicate that it is selected. Now what I want to do is to disable this visual effect and implement my own, so for example I want when an item is selected to draw a rectangle around the item.
How can I do that? (Note that I am talking about the Icon view).
This is a case for custom drawing of controls.
It's all about handling the NM_CUSTOMDRAW notification and then to draw the control more or less by yourself.
I've never done it by myself changing the appearance seriously but I've change background colors of controls using this mechanism.
There is a lot of information about this on the internet...

Stringray Grid transparent background

In Stringray grid, there is the ability to use a transparent background which allows the background of the dialog to be shown through the grid.
In the documentation it states:
But be careful; you should disable scrolling or you have to redraw the grid each time it is scrolled (by overriding DoScroll).
I have a scrollable gird and override the DoScroll and make sure I call Redraw and also tried Invalidate, however the grid is still not completely erasing and redrawing.
I also tried using the old drawing method by setting m_bForceOldDrawing to TRUE.
How can I create a grid that has a transparent background that paint correctly after a scroll without leaving artifacts?
Yes you have to redraw the grid by overriding DoScroll because it is no longer using ScrollWindow to scroll contents because the background is transparent.
However you now have artifacts of the grid over your background.
This is because the background behind the grid is not getting redrawn.
Do you have clipchildren set for the parent?
Another potential problem is that the background is not being drawn because it doesn't realize it has been exposed.
Try calling the parent with the following.
Parent.Invalidate();
Parent.UpdateWindow();
before calling...
Invalidate();

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?