In my project, I have a window that has been masked with setMask(QRect()). It works fine, but the shadow that the Window Manager leaves is gone. I definitely want that drop shadow effect on my program.
At first, I moved all of my objects into a single widget and had that widget cast a box shadow onto the MainWindow. Then I made the MainWindow transparent with setAttribute(Qt::WA_TranslucentBackground, true) and setWindowFlags(Qt::FramelessWindowHint). This did the job, however, having a frameless window caused many issue that I can't seem to fix. Namely, this: https://stackoverflow.com/questions/31418494/qtframelesswindowhint-window-cant-be-recorded-with-obs
If I just do setAttribute(Qt::WA_TranslucentBackground, true) or set the style sheet, the background becomes black, not transparent.
So my question is, how do I make the MainWindow transparent without removing the frame? Or how do I cast a shadow when using setMask?
Thanks for your time.
Related
Working with widgets, c++ and Linux
need something kind of:
this
but no borders and custom title.
Search for a few days, but nothing.
For now, there is a widget with setWindowFlags(Qt::FramelessWindowHint); and a peace of qss for semitransparent background. How can I blur it? Is is possible at all?
I do not think this can be done with Qt. Blurring can be done using https://doc.qt.io/qt-5/qgraphicsblureffect.html but it is only limited to the widgets painted by Qt. Which the underlying background is not, even if you manage to make your widgets transparent or semitransparent. Painting the background is always the business of the operating system (or window manager) and not the business of your application Qt.
You can certainly try to do some extreme hacking like grabbing the active screen before your window is displayed (see How to capture the current screen image using Qt?) then getting certain rectangle content of the image, which corresponds to the background of your window, then paint it blurred to the background of your application and then update it everytime you move or resize your window... But anyway, even if you manage this, this background will be static and not dynamic.
I recommend that you abandon the idea of blurry background and leave this function to the window manager and the operating system.
I'm using Qt5.6, I have QWidget graphic objects rendered and when other graphics are rendered in front of others this seems to trigger updates of the graphics under the graphics in front.
This creates overhead, I would like to determine if the graphic behind is completely obscured by the graphic in front and if so, then it should abort the paint event.
I thought this would be automatic and done as part of the internals of Qt, but it seems not.
Each widget's paint event is comes from the widget compositor, once the compositor determines that a widget should be repainted. There's no way to abort it: if the event arrives, it means that the widget must paint, or else you'll get visually undefined results.
By default, widgets can be transparent, and the widget compositor has to paint the entire stack of widgets in back-to-front order to compose them.
Any widget that is not transparent should have the Qt::WA_OpaquePaintEvent attribute set. This will inform the widget compositor that any widgets completely hidden behind the widget don't have to be painted. Ensure that you paint every pixel of your widget!
I have a QDockWidget:
I would like to alert the user to certain events by setting the background color of the title bar.
I have achieved this by setting the style sheet for my DockWidget:
void DockWidget::setCriticalAlert()
{
setStyleSheet("QDockWidget { background-color:red; }");
}
The result is this:
The problem is that the background-color doesn't get applied when the QDockWidget is docked:
How can I get the background color to be applied when the QDockWidget is docked?
This is a bug in Qt.
Issue 10537
Quoting from the linked issue:
The problem is that in QDockWidget::paintEvent, there is a
isFloating() condition before drawing PE_FrameDockWidget. We cannot
jsut remove this condition as it would break the other style (that
does not whish to draw frame when the dockwidget is docked) We cannot
either use PE_Widget to draw the frame as then it goes over the
dockwidget's title The solution is maybe to introduce a new
PE_FrameDockWidgetDocked primitive element. Or some
SH_DockWidget_DrawDockedFrame stylehint to draw the frame in every
cases.
a valid workaround seems to be to set the stylesheet of the parent, and use the class-and-id selector. Forgive the python formatted code but the concept is the same - in this case, 'dock' is a QDockWidget which has been given an object name using setObjectName(), and its parent, the QMainWindow, is 'self':
self.setStyleSheet("QDockWidget#"+str(dock.objectName())+"::title {background-color:red}")
In PyQt5.5, this works at runtime, i.e., can be changed on the fly.
I find a solution like this:
Firstly put a frame behind all the widgets of dockwidget's center widget, as the background.
Then set stylesheet for the frame.
By this way, we could change the background color of dockwidget.
Or you can extend the dockwidget and overwrite the function
void QDockWidget::setWidget(QWidget *widget)
using private/qdockwidget_h. and add a frame as this widget's father.
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();
Using Qt Creator, I have set a QWidget's background property to black. However, some parts of the QWidget, more specifically, between QFrames/QGroupBoxes are still in its system's default color.
Now, I thought that the QFrames and QGroupBoxes need to have its background property set to black too, but it did not work. I have also tried setting the border-color to black, but it does not work, since by default borders, margins are set to 0.
QWidget { background: black; }
Any advice on this issue?
EDIT
The QWidgets are placed in QMdiArea. However, if I make it a QWindow, it works. However, I want the QWidgets to be in the QMdiArea. Also, if I just show the QWidgets as it is, the spaces that I have mentioned above are transparent.
It sounds like you have some widgets within another widget, and are setting the contained widgets to be black, but then the space between them is not black. If that is the case, it is likely because you have a layout in the containing widget, which allocates space between each contained widget. The empty space between widgets will be drawn with the containing widget's background color.
Found out the solution. It seems that you need to set the background color at the QMdiSubWindow, not at QWidget. Don't know why, but it seems logical.