QtQuick colour palette for disabled widgets - qt

I am working on a Qt (QML) application that requires darker color palette. Based on some examples I created a qtquickcontrols2.conf file with the following content:
[Controls]
Style=Fusion
[Fusion\Palette]
AlternateBase=#353535
Base=#191919
BrightText=red
Button=#353535
ButtonText=white
Highlight=#2a82da
HighlightedText=gray
Link=#2a82da
Text=white
ToolTipBase=white
ToolTipText=white
Window=#353535
WindowText=#dddddd
The colour palette works just fine for active mode of widgets. However, disabled widgets look exactly the same as active ones. I did not find a way to add colours for disabled widgets to the config file. It seems that it can't be done.
Then I had an idea to create lighter version of active palette in application main.
QPalette& updateDisabledColors(QPalette &palette)
{
palette.setColor(QPalette::Disabled, QPalette::Window, palette.window().color().lighter());
palette.setColor(QPalette::Disabled, QPalette::WindowText, palette.windowText().color().lighter());
palette.setColor(QPalette::Disabled, QPalette::Base, palette.base().color().lighter());
palette.setColor(QPalette::Disabled, QPalette::AlternateBase, palette.alternateBase().color().lighter());
palette.setColor(QPalette::Disabled, QPalette::Text, palette.text().color().lighter());
palette.setColor(QPalette::Disabled, QPalette::Button, palette.button().color().lighter());
palette.setColor(QPalette::Disabled, QPalette::ButtonText, palette.buttonText().color().lighter());
palette.setColor(QPalette::Disabled, QPalette::BrightText, palette.brightText().color().lighter());
palette.setColor(QPalette::Disabled, QPalette::Link, palette.link().color().lighter());
palette.setColor(QPalette::Disabled, QPalette::Highlight, palette.highlight().color().lighter());
palette.setColor(QPalette::Disabled, QPalette::HighlightedText, palette.highlightedText().color().lighter());
return palette;
}
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
// Tried to change palette here also
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));
if (engine.rootObjects().isEmpty()) {
return -1;
}
auto palette = app.palette();
palette = updateDisabledColors(palette);
app.setPalette(palette);
return app.exec();
}
The palette acquired from the app is not the one defined in qtquickcontrol2.conf.
What is the proper way to modify palette colours for disabled widgets when using QML?

As far as I can tell, setting the Fusion style Palette in qtquickcontrols2.conf does not update the default Q[Gui]Application palette. But the opposite works -- the default Controls2 palette is the system-wide default QPalette which can be set with Q[Gui]Application::setPalette(). So you could set all the color groups in C++ code, like you do now for just the Disabled group.
Looking at the relevant code, it also looks like you can specify a Disabled subgroup in qtquickcontrols2.conf (e.g. Fusion/Palette/Disabled). I'm not sure which versions of Qt this is available in, nor do I see this documented anywhere.
ADDED: Looks like the Palette and subgroups are read from conf file since at least Qt 5.10 (which is also when the Control::palette property was introduced).

Related

How to maintain default background color of each items inside Qt group box?

When I changed the background color of Qt group box so combobox background color is also changed. Which is inside the group box. I want default color of combobox so this is why i am not changing the bg-color of combobox. Please tell me how can I change the background color of Qt group box without changing default bg-color of inside items. I changed the background of QT group box using style sheet in qt designer (ui). I am beginner please help.
you should follow these steps :
set specific names for your objects :
select parent object and add a stylesheet to the parent like this :
this is the Stylesheet :
QGroupBox#gBox1
{
background-color: rgb(138, 226, 52);
}
first, you should set which kind of class you want like QGroupBox, and for set style, to the specific object you call its object name after #.
out put :
Simple project with styles
#include <QtCore>
#include <QtGui>
#include <QtWidgets>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGroupBox GroupBox;
GroupBox.setMinimumSize(QSize(400, 400));
GroupBox.setStyleSheet("QGroupBox {background-color: green}");
QComboBox Combo1, Combo2;
Combo1.setStyleSheet("QComboBox {background-color: yellow}");
Combo2.setStyleSheet("QComboBox {background-color: red}");
Combo1.addItem("Test1");
Combo1.addItem("Test2");
Combo2.addItem("Test3");
Combo2.addItem("Test4");
QVBoxLayout vbox;
vbox.addWidget(&Combo1);
vbox.addWidget(&Combo2);
GroupBox.setLayout(&vbox);
GroupBox.show();
return a.exec();
}
also you can change object name 'setObjectName(const QString &)' function and then style different objects using there names
Combo1.setObjectName("TestObject");
Combo1.setStyleSheet("QComboBox#TestObject {background-color: yellow}");

Qt set default value for style-sheet property

I have an application where users can modify the Qt stylesheets. I want to set default value for some property in case the user-provided stylesheet does not define them, e.g.
// user provided style sheet for the whole app
qApp->setStyleSheet("file://user-provided.qss");
// default value for my button
myButton->setStyleSheet("color: red"); // I'd like this to apply only if the stylesheet does not provide it
The way Qt cascading works, setting the stylesheet on the widget override anything from the application style-sheet, even if the specifier on the application stylesheet are stronger.
I tried using QPalette, or different foreground roles with custom color in the .ui, but nothing worked. Unless I use setStyleSheet, the foreground color does not change (as expected since QPalette is ignored when a stylesheet is used).
Is there a way to have a default value in case a property is missing from the application stylesheet? Basically reverse the cascading effect of Qt?
You can set the "default" stylesheet with all needed style rules on the QApplication instance (for the whole application) and the "user" stylesheet on the top level widget.
So the stylesheet set on the top level widgets extends and overrides the application stylesheet.
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget widget;
auto label_1 = new QLabel(&widget);
label_1->setObjectName(QString::fromUtf8("label_1"));
label_1->setText("Label 1");
auto label_2 = new QLabel(&widget);
label_2->setObjectName(QString::fromUtf8("label_2"));
label_2->setText("Label 2");
auto layout = new QVBoxLayout(&widget);
layout->addWidget(label_1);
layout->addWidget(label_2);
widget.setLayout(layout);
QString defaultStyle = "#label_1{color:red};"; // default for label_1
QString userStyle = "#label_2{color:blue};"; // rule for label_1 is missing
app.setStyleSheet(defaultStyle); // set the default stylesheet on the application
widget.setStyleSheet(userStyle); // set the user stylesheet on the top level widget
widget.show(); // label 1 has blue color and label 2 has red color
return app.exec();
}

Increase QTabWidget tab size while using custom palette

My app uses a QTabWidget. I want the tabs to fill the entire length of the tab bar.
My app also uses a palette to set the colors of all widgets, forms, etc.
I found that I can set the tab size as intended like so:
ui->tabWidget->setStyleSheet(QString("QTabBar::tab { width: %1px; }").arg(ui->tabWidget->size().width()/ui->tabWidget->count()));
But this causes the tab widget and all of its children to ignore my palette.
How can I use my palette and also increase the tab size?
I tried to reproduce your described behavior, but I was not able to do so. I'm using Qt 5.13.0, maybe it is in older version. At first I also thought, that I reproduced your behavior, but then I recognized, that I just didn't fully understood the options in QPalette, which really has a lot of ColorGroups and ColorRoles with different meanings.
Try the following simple test runner in order to verify it with your Qt Version.
#include <QApplication>
#include <QTabWidget>
#include <QFrame>
#include <QHBoxLayout>
#include <QPushButton>
int main(int argc, char** args) {
QApplication app(argc, args);
auto p=app.palette();
p.setColor(QPalette::ColorGroup::Active, QPalette::ColorRole::Background, QColor("red"));
p.setColor(QPalette::ColorGroup::Active, QPalette::ColorRole::Foreground, QColor("blue"));
p.setColor(QPalette::ColorGroup::Active, QPalette::ColorRole::ButtonText, QColor("magenta"));
app.setPalette(p);
auto w= new QTabWidget;
auto f=new QFrame;
f->setLayout(new QHBoxLayout);
f->layout()->addWidget(new QPushButton("Test"));
w->addTab(f,"Tab1");
w->setStyleSheet(QString("QTabBar::tab { width: %1px; height: %1px }").arg(100));
w->show();
app.exec();
}

How to customize text on Qpushbutton using QPalette?

How to set font, size and color for the Text of QPushButton in Qt5.6.1 using QPalette? As I am curious to know how we can set these properties without using QStyleSheet in Qt. Also how we can set hex code of color in QT.
Please suggest any way to do with QPalette.
Thanks
How to set font, size and color for the Text of QPushButton in Qt5.6.1 using QPalette?
A QPalette contains color groups for each widget state. It does not contain font/size information.
You can use QWidget::setPalette() to change specific color roles (Button, ButtonText, Window. . .), and use QWidget::setFont() to change font family/size. For example:
QPushButton button("Press Me");
//get initial default palette
QPalette pal= button.palette();
//change some color roles
pal.setColor(QPalette::Window, QColor(255, 0, 0)); //red color
pal.setColor(QPalette::Button, QColor(0x00, 0x00, 0xff)); //blue color (hex representation)
pal.setColor(QPalette::ButtonText, QColor(Qt::yellow)); //Qt global color
button.setPalette(pal);
//change font family and size
button.setFont(QFont("Helvetica [Cronyx]", 15, QFont::Bold));
In order for palettes to work properly, you may want to first use Fusion style in the application by calling:
QApplication::setStyle(QStyleFactory::create("Fusion"));
before instantiating the QApplication instance in main() because some styles do not use the palette for all drawing, for instance, if they make use of native theme engines. This is the case for both the Windows XP, Windows Vista, and the OS X styles.
Also, You may want to set the palette/font on the whole application, so that you get those colors in all widgets in the application. Something like this:
#include <QtWidgets>
int main(int argc, char** argv)
{
QApplication::setStyle(QStyleFactory::create("Fusion"));
QPalette pal= QApplication::palette();
pal.setColor(QPalette::Window, QColor(Qt::red));
pal.setColor(QPalette::Button, QColor(Qt::blue));
pal.setColor(QPalette::ButtonText, QColor(Qt::yellow));
pal.setBrush(QPalette::WindowText, QBrush(QColor(Qt::yellow)));
pal.setColor(QPalette::Highlight, QColor(Qt::green));
//further palette customization. . .
QApplication::setPalette(pal);
QApplication::setFont(QFont("Helvetica [Cronyx]", 15, QFont::Bold));
QApplication a(argc, argv);
//setup and show GUI components
return a.exec();
}
I agree with the above mentioned points.
Following is the another approach to achieve the Font Customization with QWidgets.
QPushButton *button3 = new QPushButton("CheckFont", this);
button3->setGeometry(QRect(QPoint(50,50),QSize(200,50)));
QFont FontObj;
FontObj.setFamily(QStringLiteral("Helvetica [Cronyx]"));
FontObj.setPointSize(15);
FontObj.setBold(true);
FontObj.setUnderline(true);
button3->setFont(FontObj);
Also when Color code is in format like "#ffffff" (which is white color code) then you can use following way to set the hex color code with QPalette.
pal.setColor(QPalette::Button, QColor(QRgb("#ffffff")));
OR
pal.setColor(QPalette::Button, QColor("#ffffff"));

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();
}

Resources