Changing Background color of QCheckBox - c++

I want to have a checkbox with the following style:
For that purpose I have created the follow stylesheet:
QCheckBox { background-color : cyan; }
QCheckBox::indicator { width : 20px; height : 20px; }
sadly the result was not was I expected, here is what I get:
But I want to have all background with the color cyan.
I have checked the Qt Documentation About StyleSheet and have also also checked some old questions, but none of the has served me. When I added QCheckBox::indicator{ background-color : cyan; } the button became all cyan (like on the first image on the state unchecked) on checked and unchecked states. Neither adding other proprieties like border helped me.
I also tried to use QPalette instead, but never changed.
Here is my code:
QWidget* w = new QWidget();
QCheckBox* cb = new QCheckBox(w);
cb->setFixedSize(20, 20);
cb->setStyleSheet(QString("QCheckBox { background-color : cyan; }") + '\n' +
"QCheckBox::indicator { width : 20px; height : 20px; border : }");
w->show();
EDIT 28/09/2020
I have recently figured out that the style of the application has influence on it. I was using the Breeze style, changing to Fusion style made it work as expected. The only problem is that it requires change the theme of the application itself. Anyway, here is the code sample in case it helps anyone:
#include <QApplication>
#include <QWidget>
#include <QCheckBox>
int main(int argc, char** argv)
{
QApplication a(argc, argv);
qApp->setStyle(QStyleFactory::create("Fusion"));
QWidget* w = new QWidget();
QCheckBox* cb = new QCheckBox(w);
cb->setFixedSize(20, 20);
cb->setStyleSheet(QString("QCheckBox { background-color : cyan; }") + '\n' +
"QCheckBox::indicator { width : 20px; height : 20px; border : }");
w->show();
}

I did not solve my problem using the stylesheet commands, I actually think that it is not possible SOURCE.
Anyway, I was I able to achieve my goals using one image for the checked state and another one for the unchecked state as follow.
QWidget* w = new QWidget();
QCheckBox* cb = new QCheckBox(w);
cb->setFixedSize(20, 20);
cb->setStyleSheet("QCheckBox::indicator { width : 20; height : 20; }\n"
"QCheckBox::indicator::unchecked { image : url(/path/**/unchecked.png); }\n"
"QCheckBox::indicator::checked { image : url(/path/**/checked.png); }");
w->show();

Probably
QCheckBox::indicator:unchecked {background-color : cyan;});
is what you wanted to see.
Edit: Too late

Related

How to create custom widget and use it in Qt Designer?

I extremely need to create my custom widget and use it inside QtDesigner ( promoting QWidget to my widget ). I have never done it before, and can't google anything useful. Widget i need to get is just square box with few QLabel and QLineEdit objects. For this moment i have the following code:
#include "customwidget01.h"
#include "qlabel.h"
#include "qlineedit.h"
#include "QGridLayout"
customWidget01::customWidget01(QWidget *parent) : QWidget(parent)
{
QString textSheets = "QLabel,QLineEdit {width:60;height:20;max-width:60;max-height:20;;min-width:60;min-height:20;}";
QString widgetSheet = "customWidget01 {width:200;height:200;max-width:200;max-height:200;;min-width:120;min-height:200;}";
this->setStyleSheet(widgetSheet + textSheets);
QLabel *label1= new QLabel(this);
label1->setText("1st arg");
QLabel *label2 = new QLabel(this);
label2->setText("2nd arg");
QLabel *label3= new QLabel(this);
label3->setText("3rd arg");
QLabel *label4= new QLabel(this);
label4->setText("4th arg");
QLineEdit *line1 = new QLineEdit(this);
line1->setPlaceholderText("enter 1st arg");
QLineEdit *line2 = new QLineEdit(this);
line2->setPlaceholderText("enter 2nd arg");
QLineEdit *line3 = new QLineEdit(this);
line3->setPlaceholderText("enter 3rd arg");
QLineEdit *line4 = new QLineEdit(this);
line4->setPlaceholderText("enter 4th arg");
QGridLayout *layout = new QGridLayout();
this->setLayout(layout);
layout->setVerticalSpacing(10);
layout->setHorizontalSpacing(10);
layout->addWidget(label1,0,0);
layout->addWidget(label2,1,0);
layout->addWidget(label3,2,0);
layout->addWidget(label4,3,0);
layout->addWidget(line1,0,1);
layout->addWidget(line2,1,1);
layout->addWidget(line3,2,1);
layout->addWidget(line4,3,1);
this->setVisible(true);
}
My problems are:
cant draw border around widget itself
vertical and horizontal spacings do not work
Used QtDesigner for GUI all the time - not really familiar with gui creation in plain code.
let me help you in order to get beautiful interface you need to learn CSS
I will show you how it works
that's what you have right now
This means that you do not correctly write the CSS code
QString textSheets = "QLabel,QLineEdit {width:60;height:20;max-width:60;max-height:20;;min-width:60;min-height:20;}";
QString widgetSheet = "customWidget01 {width:200;height:200;max-width:200;max-height:200;;min-width:120;min-height:200;}";
this->setStyleSheet(widgetSheet + textSheets); // does not work
I will exchange these lines for it
QString textSheets = "QLineEdit{ border-width: 2px; border-style: solid; border-color: red green black rgb(127,255,10); }"
"QLabel { border-width: 2px; border-style: solid; border-color: green black rgb(10,255,180) rgb(180,10,158); }" ;
setStyleSheet(textSheets);
and that's what result
to resize you just need to do so
//label1->setMinimumSize(150,50);
label1->setFixedSize(150,50);
//label1->setMaximumSize(150,50);
//label1->setMidLineWidth(150);
and that's what result
Add a QWidget in design mode.
Right click it and select Promote to... from the context menu.
Write the name (customWidget01) of your from QWidget derived class into Promoted class name.
Make sure the generated text in Header file is correct.
Click add.
Select it and click promote.

How to draw line behind buttons in Qt?

Question
In a custom widget, I'd like to draw lines (using QPainter) that connect buttons in a QGridLayout. The lines shall be behind the buttons, in order to
a) not interfere with buttons in between
b) allow starting the lines in the center of the buttons, not the edges
Considering ideas from this question, I could almost realize a simple, basic version running in my GUI application (source code below).
As long as I use QPushButton with the standard Qt style, it works like a charm (left), but, as I want to use a custom style, the lines overlap (right):
What property or mechanism is causing this behavior?
Code
MyFrame.h:
#include <QFrame>
class MyFrame : public QFrame
{
public:
MyFrame();
virtual ~MyFrame() = default;
};
MyFrame.cpp:
#include "MyFrame.h"
#include "LineDrawWidget.h"
#include <QVBoxLayout>
#include <QGridLayout>
#include <QPushButton>
#include <QButtonGroup>
MyFrame::MyFrame()
{
auto* mainLayout = new QVBoxLayout(this);
auto* buttonLayout = new QGridLayout();
QPushButton* button;
auto* buttons = new QButtonGroup();
for (int i = 0; i < 3; ++i) {
button = new QPushButton();
button->setText(QString::number(i+1));
button->setFixedHeight(40);
button->setFixedWidth(40);
button->setStyleSheet("QPushButton { color : black; background-color : white; }");
button->setStyleSheet("QPushButton { border-style : outset; border-color: black; border-width: 2px; border-radius: 6px; }");
buttonLayout->addWidget(button);
buttons->addButton(button, i);
}
auto* lineDraw = new LineDrawWidget(
buttons->button(0),
buttons->button(2));
lineDraw->setLayout(buttonLayout);
mainLayout->addWidget(lineDraw);
}
LineDrawWidget.h:
#include <QWidget>
class LineDrawWidget : public QWidget
{
public:
LineDrawWidget(
QWidget* from,
QWidget* to,
QWidget* parent = nullptr);
virtual ~LineDrawWidget() = default;
protected:
virtual void paintEvent(QPaintEvent* e) final override;
private:
QWidget* _from;
QWidget* _to;
};
LineDrawWidget.cpp:
#include "LineDrawWidget.h"
#include <QPainter>
LineDrawWidget::LineDrawWidget(
QWidget* from,
QWidget* to,
QWidget* parent) :
QWidget(parent),
_from(from),
_to(to)
{
}
void LineDrawWidget::paintEvent(QPaintEvent* e)
{
(void)e;
QPainter painter(this);
QPoint start = _from->mapToGlobal(_from->rect().bottomLeft());
QPoint end = _to->mapToGlobal(_to->rect().topRight());
painter.drawLine(mapFromGlobal(start), mapFromGlobal(end));
}
I think the problem is the two separate calls to setStyle for a single QPushButton -- the second call appears to reset all properties not present in it. Try putting it all in a single call...
button->setStyleSheet("color : black; background-color : white; border-style : outset; border-color: black; border-width: 2px; border-radius: 6px;");
Seems to work for me.

Changing QCheckBox text color

I found the same question there:
how to change QCheckBox text label color in Qt?
But unfortunately, none of it work for me on a mac.
On Linux and Windows, by default the text of a QWidget (QLabel, QCheckBox, QRadioButton) is white.
On the mac, it's black. Unfortunately this cause issues in my screen as the text is unreadable (I have black background)..
I have derived the QCheckBox class so in the constructor you get:
class MPUBLIC MythCheckBox: public QCheckBox
{
Q_OBJECT
public:
MythCheckBox(QWidget *parent = 0, const char *name = "MythCheckBox")
: QCheckBox(parent)
{
setObjectName(name);
#ifdef Q_OS_MAC
// setStyleSheet("QCheckBox { color : white; }; QCheckBox::indicator { color:black; }");
QPalette p = palette();
p.setColor(QPalette::WindowText, Qt::white);
setPalette(p);
#endif
};
If I use stylesheets like:
setStyleSheet("QCheckBox { color : white; }; QCheckBox::indicator { color:black; }");
then my text is white as I want, but the checkmark itself becomes invisible...
If I use the 2nd method:
QPalette p = palette();
p.setColor(QPalette::WindowText, Qt::white);
setPalette(p);
The checkbox text does become white, and the checkmark itself is still black, it looks like it works.
But if I ever move the focus to the QCheckBox, the text becomes black again, and it will remain black forever.
I tried also:
QPalette p = palette();
p.setColor(QPalette::Active, QPalette::WindowText, Qt::white);
p.setColor(QPalette::Inactive, QPalette::WindowText, Qt::white);
setPalette(p);
Mind you, I only get this weird behavior on the mac; if I try the same code in Linux (with different colors like red), then everything behaves like I want it to.
Any ideas on how to change the color of a QCheckBox's text, and only the text?
For some widgets you have to disable a native look (appearance). For example QPushButton (http://doc.qt.io/qt-4.8/stylesheet-reference.html). So, for checkbox you can try to set borders. So checkbox's style looks like:
QCheckBox {
border: none;
color: white;
}
Works for me.

How to render a red push button using QStyle.drawControl()?

With the following code I tried to render a red push button using QStyle.drawControl():
#include <QtCore/QtCore>
#include <QtGui/QtGui>
class Widget : public QWidget
{
virtual void paintEvent(QPaintEvent* event)
{
QStyleOptionButton opt;
opt.palette = QPalette(Qt::red);
opt.state = QStyle::State_Active | QStyle::State_Enabled;
opt.rect = QRect(50, 25, 100, 50);
QPainter painter(this);
style()->drawControl(QStyle::CE_PushButton, &opt, &painter);
}
};
int main(int argc, char** argv)
{
QApplication app(argc, argv);
Widget w;
w.resize(200, 100);
w.show();
return app.exec();
}
However I get the following result:
How do I render a red push button using QStyle.drawControl()?
I'm using Qt 4.8.1 and Visal Studio 2010 on Windows XP.
The buttons are drawn by the native style engine, so the palette might not be used at all (see that question from the FAQ).
You can use an actual button with a stylesheet that you pass as the last parameter to the own button's style drawControl function.
class Widget : public QWidget
{
// To allow the automatic deletion without parenting it
QScopedPointer<QPushButton> button;
public:
Widget() : button(new QPushButton) {
button->setStyleSheet("background-color: red");
}
virtual void paintEvent(QPaintEvent* event)
{
QStyleOptionButton opt;
opt.state = QStyle::State_Active | QStyle::State_Enabled;
opt.rect = QRect(50, 25, 100, 50);
QPainter painter(this);
button->style()->drawControl(QStyle::CE_PushButton, &opt, &painter,
button.data());
}
};
But you will loose the native style, so you'll have to fake it (bali182's answer might be useful for that part).
Or you can use the same button with colorize effect and call its render() function to paint it:
class Widget : public QWidget {
QScopedPointer<QPushButton> button;
public:
Widget() : button(new QPushButton) {
QGraphicsColorizeEffect *effect = new QGraphicsColorizeEffect(button.data());
effect->setColor(Qt::red);
button->setGraphicsEffect(effect);
}
virtual void paintEvent(QPaintEvent* event) {
button->setFixedSize(100, 50);
button->render(this, QPoint(50, 25));
}
};
What you are trying to do, seems overly complicated. If you just want a red button, why not use the setStyleSheet() method of the QPushButton? It takes a QString, and you can define your button similar to CSS. Here i created you a red button, similar to the XP ui buttons:
QPushButton
{
background: qlineargradient(x1:0,y1:0,x2:0,y2:1, stop:0 #f4a3a3,stop: 1 #cc1212);
border-width: 1px;
border-color: #d91414;
border-style: solid;
padding: 5px;
padding-left:10px;
padding-right:10px;
border-radius: 3px;
color:#000;
}
QPushButton:hover
{
border-color: #e36666;
}
QPushButton:pressed
{
background:qlineargradient(x1:0,y1:0,x2:0,y2:1,stop: 0 #de8383, stop: 1 #ad0C0C);
border-color: #d91414;
}
Now you just need to pass the code above as a string to your buttons setStyleSheet() method. If you want to create a button widget, what is red by default, then extend the QPushButton class, create a static QString field with the content above, and set the button as stylesheet in the constructor.
More easy to understand examples on stylesheets:
Stylesheet Examples

Customized color on progressbar delegate

Been trying to do this for quite a while and took advice from every forum post i could find but i still cant solve it. This is my current code and I would really like to change the color of the chunk on the progress bar. Every other setting is working, except the colors.
In my workspace object that fills up one subview on the MainWindow.
Workspace::Workspace( QWidget* parent) : QWidget( parent )
{
QTableView* tableView = new QTableView();
// ...
tableView->setItemDelegate(new ProgressBarDelegate);
}
The delegate.cpp looks like this:
ProgressBarDelegate::ProgressBarDelegate( QObject* parent )
: QStyledItemDelegate(parent)
{
}
void ProgressBarDelegate::paint( QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
if (index.column() == 2)
{
int progressPercentage = index.model()->data(index, Qt::DisplayRole).toInt();
QStyleOptionProgressBarV2 progressBarOption;
progressBarOption.rect = QRect(option.rect.x(), option.rect.y() + 5 , option.rect.width(), option.rect.height() / 1.5);
progressBarOption.minimum = 0;
progressBarOption.maximum = 100;
progressBarOption.progress = progressPercentage;
QPalette pal = progressBarOption.palette;
QColor col = QColor(35, 35,25);
pal.setColor(QPalette::Highlight, col); // or QPalette::Window doesnt matter
progressBarOption.palette = pal;
if(option.state & QStyle::State_Selected)
{
}
QApplication::style()->drawControl( QStyle::CE_ProgressBar,
&progressBarOption,
painter);
}
else
{
QStyledItemDelegate::paint(painter, option, index);
}
}
Currently, no matter what I do the color doesnt change from OSX standard light-gray.
Running OSX 10.6.7 and Qt 4.8.1 if that matters. thank you!
Edit:
I was able to do the following:
app.setStyleSheet("QScrollBar:horizontal { border: 2px solid green;background: cyan;height: 15px;margin: 0px 20px 0 20px;}");
But when I do this:
app.setStyleSheet("QProgressBar:horizontal { border: 1px solid gray; border-radius: 3px; background: white; padding: 1px; }");
NOTHING changes on the progressbar. I am in theory not creating any progressbar objects, im just settings a style how I'm viewing my data in my delegate. But surely, I cant be the first person who would want to do this right?
Also, if this doesnt work, how can I do this (having a styled progressbar) in a tableview?
You should use Qt Style Sheet, which allows us to customize UI of many controls to give unique look and feel across platforms. Check this.
Create a new simple Qt Gui project, open UI Form editor and add a Progress Bar control from under 'Display Widgets' in tool window. Now write following code in constructor of MainWindow..
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
// Customize progress-bar's style..
QString style = "QProgressBar {border: 2px solid grey; border-radius: 5px; text-align: center;}";
style += "QProgressBar::chunk {background-color: #CD96CD; width: 10px; margin: 0.5px;}";
// Assuming objectName is 'progressBar'..
ui->progressBar->setStyleSheet(style);
}
Compile and run.
If you just want to change that single QProgressBar control, then above method is sufficient, but if you want to apply styles at application level (say all QProgressBar controls and some other controls), then proper way is to create a *.css file, write styles using Qt Style Sheet Reference and then read that file in Qt and call
QApplication::setStyleSheet(QString style).
Besides, style sheet uses the same syntax as CSS and also supports various selectors.
Edit:
I agree that above method works only with controls and not delegates. I found something for delegates also. Try following paint function.
void ProgressBarDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if (index.column() == 2)
{
QProgressBar renderer;
int progressPercentage = index.model()->data(index, Qt::DisplayRole).toInt();
// Customize style using style-sheet..
QString style = "QProgressBar { border: 2px solid grey; border-radius: 5px; }";
style += "QProgressBar::chunk { background-color: #05B8CC; width: 20px; }";
renderer.resize(option.rect.size());
renderer.setMinimum(0);
renderer.setMaximum(100);
renderer.setValue(progressPercentage);
renderer.setStyleSheet(style);
painter->save();
painter->translate(option.rect.topLeft());
renderer.render(painter);
painter->restore();
}
else
QStyledItemDelegate::paint(painter, option, index);
}
So here the point is that instead of using QStyleOption, we can use directly the control itself as a renderer. Hope this helps..
Instead of pal.setColor(QPalette::Window, col);
Use pal.setColor(QPalette::Highlight, col);
This should work.
I used the code in Paintevent
void Dialog::paintEvent(QPaintEvent *e)
{
QPainter painter(this);
connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(ShowPrintDialog()));
QStyleOptionProgressBarV2 progressBarOption;
progressBarOption.rect = QRect(20,20,30,30);
progressBarOption.minimum = 0;
progressBarOption.maximum = 100;
progressBarOption.progress = 75;
QPalette pal = progressBarOption.palette;
QColor col = QColor(0,255,0);
pal.setColor(QPalette::Highlight, col);
progressBarOption.palette = pal;
QApplication::style()->drawControl(QStyle::CE_ProgressBar,&progressBarOption, &painter);
}