How to make Transparent QT Dock Widget - qt

On Windows ,I am trying to create Qt application with transparent DOCKWIDGETS, where background of dock widget is transparent when it is floated. So we can see through dock widget.
Currently it looks black as below.
Code as below
QDockWidget * dock3 = new QDockWidget(tr("DOCK3 TranslucentBackground"),
textEdit,Qt::FramelessWindowHint);
dock3->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
//dock3->setWindowFlags(dock2->windowFlags()|Qt::FramelessWindowHint);
dock3->setAttribute(Qt::WA_TranslucentBackground);
//dock3->setAttribute(Qt::WA_NoSystemBackground);
{
QWidget* WindowRect = new QWidget(dock3);
QWidget* titleRect = new QLabel ("Title",WindowRect);
titleRect->setFixedSize(QSize(30,60));
titleRect->setStyleSheet("background:rgb(0,0,255);");
QWidget* ContentRect = new QLabel("Content",WindowRect);
ContentRect->setFixedSize(QSize(60,30));
ContentRect->setStyleSheet("background:rgb(0,255,0);");
QVBoxLayout* layout = new QVBoxLayout(WindowRect);
layout->addWidget(titleRect);
layout->addWidget(ContentRect);
dock3->setWidget(WindowRect);
}

One way is to use setWindowOpacity(qreal) of the QDockWidget.
But keep in mind that this will apply the opacity to all children of the QDockWidget.
For reference: https://doc.qt.io/qt-5/qwidget.html#windowOpacity-prop
Another way is to use style sheets:
setStyleSheet("background-color: transparent;");. Unfortunately this doesn't work for top level widgets until you set the attribute WA_TranslucentBackground of the base widget.
For reference:
https://doc.qt.io/qt-5/stylesheet.html
https://doc.qt.io/qt-5/qwidget.html#styleSheet-prop

Try with this article:
Qt tip & Trick: Masking Widgets
You can do it with:
setStyleSheet("background-color: rgba(0,0,0,0)");
You can try to to it in the drawin customisation by changing the style of your widget like:
MyCustomWidget {background-color: none;}
It should work

I understand that you want to see through the docking bar only when it is floating. When it's not (docked), it makes no sense because there's nothing behind to be shown.
Using setAttribute(Qt::WA_TranslucentBackground) does the trick. I'm under Linux, hopefully, it also works for Windows (I found some posts where people additionally set setAttribute(Qt::WA_NoSystemBackground), it made no difference for me under Linux, if Qt::WA_TranslucentBackground is not enough for you, give it a try with both).
#include <QMainWindow>
#include <QApplication>
#include <QDockWidget>
#include <QLabel>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QMainWindow w;
w.setCentralWidget( new QWidget() );
w.centralWidget()->setStyleSheet("background-color: green");
QDockWidget* dock = new QDockWidget();
dock->setWidget( new QLabel("Hello World",dock) );
// make docking bar transparent!
dock->setAttribute(Qt::WA_TranslucentBackground);
w.addDockWidget(Qt::BottomDockWidgetArea,dock, Qt::Horizontal);
w.show();
return a.exec();
}
When docked, it looks like this:
When floating, it looks like this:
You can see the central widget (green), can be visible through the docking bar.
Reference: Make QWidget transparent

Related

Would that be possible to build a particular customized QPushButton?

I was trying to understand if there is a way to build a particular customized QPushButton?
What I am trying to achieve is the following layout and appearance:
The button is shown below, notice the red line (which meas that the button is not clicked). I am not sure how to achieve the red line. I think it could be widget? or a QProgressbar, that when is clicked goes/loads up to green..I am not sure because I don't have enough experience and have been trying to build it. However this seems to be a bit tough:
And below how it should look like right after the click happened (note the green line):
Despite my efforts, I found some useful sources that I could use to get me started: for example this source was great to understand how to start. I studied the fact that in order to achieve that, the button need to be subclassed, and that is great because it lays some sort of route.
Below the code I used:
custombutton.h
#ifndef CUSTOMBUTTON_H
#define CUSTOMBUTTON_H
#include <QPushButton>
class CustomButton : public QPushButton
{
public:
CustomButton( const QString& text, QWidget* parent = 0 );
void writeText();
};
#endif // CUSTOMBUTTON_H
custombutton.cpp
#include "CustomButton.h"
#include "algorithm"
CustomButton::CustomButton( const QString& text, QWidget* parent )
: QPushButton( text, parent )
{
}
void CustomButton::writeText()
{
QString buttonText = text();
setText( buttonText );
}
main
#include <QApplication>
#include "CustomButton.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
CustomButton w( "MyButton" );
w.show();
w.writeText();
a.exec();
return 0;
}
Another useful source I found is this one which also was useful.
The official documentation points to use the styles, but I am trying not to do that because I would like to solve the problem understanding what is the potential of subclassing with Qt.
Unless going in the style direction is the only possible way to solve this problem?
I would like to thank anyone in advance for sharing or pointing to a potential solution on how to do that.
You can set your button as checkable and then set a different icon for the 2 states.
In your case you'd have to set the red icon for the Normal mode and the green one for the Selected mode
Here's an example:
https://www.dropbox.com/s/x40byuyu2ph8m1y/CheckableButton.zip?dl=0
Here someone asked the same thing:
https://forum.qt.io/topic/72363/change-icon-of-pushbutton
Here you can read abouth the modes:
https://doc.qt.io/qt-5/qicon.html#Mode-enum
PS: Of course overriding QAbstractButton::paintEvent(QPaintEvent *event) is a viable option too

How to align two widgets in a QHBoxLayout where one is aligned far left, and one is aligned far right?

I want to have a QHBoxLayout where one QLabel is on the far left, the one QLabel is on the far right.
My Google-fu fails me. :( I cannot find the solution.
Here is a screenshot of the QHBoxLayout with two QLabel widgets:
Whatever I try, I cannot get the second QLabel widget aligned on the far right.
Roughly speaking, I tried something like this:
QHBoxLayout* const hboxLayout = new QHBoxLayout{};
hboxLayout->addWidget(m_leftLabel, 1);
hboxLayout->addStretch(1);
hboxLayout->addWidget(m_rightLabel, 0, Qt::AlignmentFlag::AlignRight);
I tried various large stretch values for the first addWidget() call and addStretch().
I also tried:
m_rightLabel->setAlignment(Qt::AlignmentFlag::AlignRight)
None of these solutions works. I am sure the solution is very simple ( ! ), but I cannot find it.
How can I do this?
My solution is to set a stretch in the middle:
#include <QtWidgets>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget w;
QHBoxLayout *lay = new QHBoxLayout(&w);
lay->addWidget(new QLabel("Left"));
lay->addStretch();
lay->addWidget(new QLabel("Right"));
w.show();
return a.exec();
}

Qt how to put QLabel without any layout

Can someone tell me, is it possible to use QWidget without any Layout. I have QSplashScreen with image as a background and I want to add one more QLabel with another image inside of my splash screen, but because splash screen is not resizable and there is no reason to do this, I haven't want use any Layout. I want just add QLabel with image and set its geometry.
There's nothing to it: just add your widget as a child of the splash screen, and manually set its position, and perhaps size as well.
int main(int argc, char ** argv) {
QApplication a{argc, argv};
QSplashScreen splash;
QLabel image{&splash};
image.move(50, 50);
...
splash.show();
return a.exec();
}
Much the same as Kuba Ober's above code with some minor but necessary additions.
QPixmap pixmap(":/splash.png"); //from resources
QSplashScreen splash(pixmap);
QLabel label(&splash);
label.setPixmap(pixmap); //you can use different image for label
label.setScaledContents(true);
label.setGeometry(50,50,50,50);
splash.show();

Styled top-level QPushButton widget does not render properly

I've successfully made a QPushButton the top-level widget/window of an application and am attempting to style the button like so:
#include <QPushButton>
#include <QApplication>
class MyButton : public QPushButton
{
public:
MyButton() : QPushButton( "Button" )
{
setFixedSize( 250 , 65 );
setStyleSheet( "border-radius: 10px;" ); // style
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyButton b;
b.setWindowFlags( Qt::FramelessWindowHint | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint );
b.setAttribute(Qt::WA_TranslucentBackground); // Fixes opaque BG
b.show();
return a.exec();
}
Unfortunately, as the following image shows, the button is no longer rendered properly when the style is applied. I'd appreciate help getting the button to render the style properly.
Edit
Following Kuber Obas answer, I'd appreciate help styling the edges of the widget, i.e. those that are outside the rounded corner, to transparent as shown below
In most native styles, the border is drawn with the rest of the button using native functionality and its elements cannot be replaced one-by-one. Once you introduce your own styling, the monolithic native styling is gone. So, you'll need to replace all of the functionality provided by the native style, including the border, the background gradient, etc. You will need to tweak it to "match" native style if you so need.
Here, you need to redefine the border completely: at the minimum provide the pen (border:). The radius only makes sense with the pen. You also need to redefine the background, if you care for one, redefine all of the button's state selectors, etc. You start with an unstyled button!
The screenshot below demonstrates it well. On the left you have a Mac-styled native button, on the right you have a button with just its border defined anew. It's obvious that the default state background should also be adjusted to match that of the platform in this case, and some margin needs to be added.
Qt doesn't really re-do modern native styles entirely from scratch, that's why you can't tweak their individual elements. It'd be too much work and a constantly moving target. It used to be done for the old Windows-95/NT style. Starting with the XP style, it was decided to let the platform APIs provide the visual style bitmaps. Similar thing presumably happens on OS X. That's also the reason why you can't use the fancier XP/Aqua/Mac Qt styles outside of their native platform: the relevant native APIs are not present and thus the style is disabled.
// https://github.com/KubaO/stackoverflown/tree/master/questions/styledbutton-20642553
#include <QPushButton>
#include <QHBoxLayout>
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a{argc, argv};
QWidget w;
QHBoxLayout layout{&w};
QPushButton button1{"Default"};
button1.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
layout.addWidget(&button1);
QPushButton button2{"Styled"};
button2.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
button2.setStyleSheet(
"* { border: 2px solid #8f8f91; border-radius: 12px; background-color: #d02020; }"
"*:pressed { background-color: #f6f7fa; }");
layout.addWidget(&button2);
auto pal = w.palette();
pal.setBrush(QPalette::Background, Qt::darkBlue);
w.setPalette(pal);
w.show();
return a.exec();
}

Qt alignment in QGridLayout eliminates the resizing of its elements

Ok, so basically I have a simple table with a QWidget and two buttons as shown below:
QGridLayout *layout = new QGridLayout;
layout->addWidget(viewcontainer,0,0,1,2);
layout->addWidget(reset,1,0);
layout->addWidget(done,1,1);
This is basically what I want, where "reset" and "done" are buttons. Essentially it's a QWidget, viewcontainer, which resizes as the window size is changed by the user while the buttons' heights remains the same. But, the default for the gridlayout is to align the contents to the left. If I change this with:
layout->addWidget(viewcontainer,0,0,1,2, Qt::AlignCenter);
It does sort of what I want, but the graphicsscene no longer resizes (remains a small constant size). I'd like to retain the resizing while just aligning the widget to the center. Thanks.
I think the easiest solution which provides a clean solution is to nest 2 layouts.
Your 'outer' (parent) layout should be a QHBoxLayout and you can add your QGridLayout into it as an 'inner' (child) layout with addLayout().
Based on my experience you should avoid to set Qt::Alignment every time you can. It can really mess up your layout. For simple layouts it can work but for more complex ones you should avoid it. And you never know that you should extend your layout in the future or not so my suggestion is to use nested layouts.
Of course you can create a QWidget for the 'outer' layout and for the 'innser' layout as well but most of the times it should be fine to just nest 2 layouts.
Also you can use QSpacerItem to fine-tune your layout.
Have a look at this example code, I think it does what you want:
#include <QApplication>
#include <QPushButton>
#include <QGraphicsView>
#include <QGridLayout>
#include <QPalette>
class MyWidget : public QWidget
{
public:
MyWidget()
{
QGridLayout * layout = new QGridLayout(this);
QGraphicsView * gv = new QGraphicsView;
layout->addWidget(gv, 0,0, 1,2);
layout->setRowStretch(0, 1); // make the top row get more space than the second row
layout->addWidget(new QPushButton("reset"), 1,0);
layout->addWidget(new QPushButton("done"), 1,1);
}
};
int main(int argc, char ** argv)
{
QApplication app(argc, argv);
MyWidget w;
w.show();
return app.exec();
}

Resources