Qt set default value for style-sheet property - qt

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

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

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

QPushButton Main Gui

I'm beginning with Qt and I do not understand something. Here is my code:
#include <QApplication>
#include <QtWebKitWidgets/QWebView>
#include <QMainWindow>
#include <QPushButton>
QApplication a(argc, argv);
QMainWindow *mWin = new QMainWindow();
QPushButton *button = new QPushButton("Button");
button->setGeometry(0,0,128,56);
button->show();
mWin->setGeometry(QRect(300,300,1024,640));
mWin->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint);
mWin->show();
return a.exec();
When I launch the program, it makes a pushbutton, but not on the main GUI. It instead makes it in the upper lefthand corner of my scoeen. How do I make the pushbutton part of the main GUI?
Both QMainWindow and QPushButton derive from QWidget and generally, QWidgets can display themselves independently, so don't need to be attached to a parent, though it's likely you'll want to group and organise the widgets you're presenting to the user.
For a beginner, I think that QMainWindow is a bit misleading as you don't actually need it to display widgets. If, for example, you wanted to just display the button, you only need create the QPushButton and call show: -
QPushButton pButton = new QPushButton("Test");
pButton->show();
Though it's rare that you'll actually want to do this. In actuality, though it appears pointless, you can even just create a QWidget and display that: -
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget w;
w.show();
return a.exec();
}
The QWidget can now be the parent to all other widgets, still without you defining a QMainWindow.
It is likely that you will want other widgets to display and Qt uses a parent / child hierarchy system of linking them together. Amongst other things, an advantage here is that you don't need to keep track of the different widgets in order to release their memory. When you're finished, you just delete the top level item, which may be a QMainWidget, or QDialog or other QWidget based object. In the case of Windows, all you need to do is close them and their children are cleaned up too.
Adding Widgets to a QMainWindow can be done in different ways, depending upon what you're trying to achieve. Eventually, you'll likely want to use layouts that allow grouping of widgets in logical arrangements, but to start with, if you look at the constructor of the QPushButton, you'll see that it takes an optional parameter of QWidget* : -
QPushButton(QWidget * parent = 0)
This allows you to attach the widget you're creating (QPushButton in this case) to a parent. Therefore, create the QMainWindow and then pass its pointer to the QPushButton.
QMainWindow* pWindow = new QMainWindow; // create the main window
QPushButton pButton = new QPushButton(pWindow); // create the push button
pWindow->show(); // Display the main window and its children.
You're creating a button and a window, but you're not associating them together. Therefore, the button is not part of the main UI. In order to add the button to the main window, you should add the following line-
mWin->setCentralWidget(button);
When creating user interfaces with Qt, it's better to avoid setting the geometry explicitly. Here is a nice page which describes the layouting in Qt.
Also, you seem to be missing a main function.
You are not setting parent child relationship, you need QPushbutton as a child of QMainwindow. Then you can see QPushbutton on QMainwindow.
Please try this, I am not sure what exactly you want to achive..but below code will give some hind about how to proceed..
QApplication a(argc, argv);
QMainWindow *mWin = new QMainWindow();
QPushButton *button = new QPushButton(mWin); // setting parent as QMainwindow
button->setGeometry(0,0,128,56);
// button->show();
//mWin->setCentralWidget( button );
mWin->setGeometry(QRect(300,300,1024,640));
mWin->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint);
mWin->show()
;
Create a central widget for the main window and then use a layout to place the push button on the central widget. For example:
QMainWindow *mWin = new QMainWindow();
// Place the button in a layout
QHBoxLayout *layout = new QHBoxLayout;
QPushButton *button = new QPushButton("Button");
layout->addWidget(button);
// Set up a central widget for the main window
QWidget *centralWidget = new QWidget();
centralWidget->setLayout(layout);
mWin->setCentralWidget(centralWidget);
If you've placed your button into a layout this way (or as a central widget itself, as one of the other answers has indicated), you don't need to set the geometry on the button, nor do you need to call setVisible or show on the button explicitly (but you still need to on the main window).
Consider looking through some of Qt's examples, such as the application example for more information.

Qt - not all widgets refreshed after stylesheet change

I have style manager, so user can change stylesheet and palette in runtime. But after this operation, not all widgets are "restyled". New look is applied when widget is recreated. Same code called from main window constructor is working like expected. Is exists any global signal which notify all widgets that they should refresh palette and stylesheet?
QFile file(":/qss/default.qss");
file.open(QFile::ReadOnly);
QString styleSheet = QLatin1String(file.readAll());
qApp->setStyleSheet(styleSheet);
QPalette p = qApp->palette();
p.setColor(QPalette::Window, QColor(53,53,53));
p.setColor(QPalette::Button, QColor(53,53,53));
p.setColor(QPalette::Highlight, QColor(175,0,0));
p.setColor(QPalette::ButtonText, QColor(255,255,255));
p.setColor(QPalette::WindowText, QColor(255,255,255));
qApp->setPalette(p);

Resources