QLineEdit change text weight on activation - c++

I want to make QLineEdit looks like QLabel with bold text if it's inactive and like QLineEdit with normal weight if active. In my understanding "active" = when text cursor shown and user can enter a text.
I tried to apply this css:
QLineEdit {
font-weight: normal;
border: 1px solid black;
}
QLineEdit:!focus {
font-weight: bold;
border: none;
}
Border works as expected, but font-weight is always bold.
I was thinking of creating my class to handle activation event, but can't found anything related with it.
I will be very thankful if somebody can help me.

You need to get your custom slot for the focusChanged event. There you can change the font like this:
QFont font = ui->lineEdit_search->font();
font.setWeight(QFont::Bold); // or
font.setWeight(QFont::Normal);
ui->lineEdit_search->setFont(font);
An example where I handled a LineEdit search box is here, but you have to customize it with the bold text.
void MainWindow::focusChanged(QWidget* old, QWidget* now)
{
if(now != NULL &&
now->objectName() == "lineEdit_search")
{
if(ui->lineEdit_search->text() == tr("Search..."))
{
ui->lineEdit_search->clear();
QPalette *palette = new QPalette();
palette->setColor(QPalette::Text,Qt::black);
ui->lineEdit_search->setPalette(*palette);
delete palette;
}
}
else if(old != NULL &&
old->objectName() == "lineEdit_search")
{
if(ui->lineEdit_search->text().isEmpty())
{
ui->lineEdit_search->setText(tr("Search..."));
QPalette *palette = new QPalette();
palette->setColor(QPalette::Text,Qt::gray);
ui->lineEdit_search->setPalette(*palette);
delete palette;
}
}
}

When you turn your line edit to inactive,
//Set your line edit to read only
yourLineEdit->setReadOnly(true);
//Get your widget background color
const QColor clr = this->palette().color(QWidget::backgroundRole());
//Set the widget background color to both the line edit background and its border
QString backGroundstyle = "background-color: rgb(%1, %2, %3);";
QString borderStyle = "border: 1px solid rgb(%1, %2, %3);";
yourLineEdit->setStyleSheet(backGroundstyle.arg(clr.red()).arg(clr.green()).arg(clr.blue()) + borderStyle.arg(clr.red()).arg(clr.green()).arg(clr.blue()));
When you turn line edit to active
//Make your line edit read-write
yourLineEdit->setReadOnly(false);
//Bring back your styles.
QString backGroundstyle_active = "background-color: white;";
QString borderStyle_active = "border: 1px solid black;";
yourLineEdit->setStyleSheet(backGroundstyle_active + borderStyle_active);

Related

How to create a QTextEdit with space for a caption in the border?

How i could create a QTextEdit with a space for a caption like seen on gmail:
The result I got with the code below:
I figured a way to calculate where the top border should end (Before Email) and start again (after phone), but I not figured how to clear the border in the area where 'caption' is drawn.
Example:
// textedit.h
class TextEdit : public QTextEdit
{
Q_OBJECT
public:
QLabel* caption;
TextEdit(QWidget* parent = 0) : QTextEdit(parent)
{
caption = new QLabel(this);
caption->setText("Email or phone");
caption->setStyleSheet(R"(
font: 14px;
font-weight: 900;
color: #3762ab;
border-radius: 4px;
background-color: rgba(0, 0, 0, 30);
margin-left: 32px;
)");
caption->adjustSize();
auto caption_rect = caption->contentsRect();
int caption_x = caption_rect.x();
int caption_width = caption_rect.x() + caption_rect.width();
qDebug() << "Position where the left border should end:\n"
<< caption_x << "\n";
qDebug() << "Position where the border start after the caption:\n"
<< caption_width << "\n";
}
};
#include "textedit.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
QTextEdit* textEdit = new TextEdit(this);
ui.centralWidget->setStyleSheet("#centralWidget { background-color: #121212; }");
textEdit->setStyleSheet(R"(
QTextEdit
{
border-radius: 4px;
border: 3px solid #3762ab;
background-color: transparent;
margin-top: 10px;
}
)");
textEdit->setGeometry(100, 50, 300, 70);
}
I think to achieve this I would need to draw the borders in the paintEvent, so i tried:
void paintEvent(QPaintEvent* event)
{
QTextEdit::paintEvent(event);
QPainter painter(viewport());
int borderWidth = 4;
QPen pen;
pen.setWidth(borderWidth);
//pen.setBrush(radialGrad);
painter.setRenderHint(QPainter::Antialiasing, true);
QPoint center = viewport()->rect().center();
auto r = this->contentsRect();
QPainterPath path;
//path.lineTo(0, 0);
//path.moveTo(r.width(), 4);
//painter.setClipPath(path);
// Top border
pen.setColor(Qt::red);
painter.setPen(pen);
// Line before the caption
painter.drawLine(QLine(0, 0, caption_x, borderWidth));
// Line after the caption
painter.drawLine(QLine(caption_width, 0, r.width(), borderWidth));
// Left border
pen.setColor(Qt::white);
painter.setPen(pen);
painter.drawLine(QLine(0, 0, borderWidth, r.height()));
// Bottom border
pen.setColor(Qt::green);
painter.setPen(pen);
painter.drawLine(QLine(0, r.height() - borderWidth, r.width(), r.height()));
// Right border
pen.setColor(Qt::blue);
painter.setPen(pen);
painter.drawLine(QLine(r.width() - borderWidth, 0, r.width(), r.height()));
}
Result:
I use different colors just to figure if each border was being drawn correctly...
Btw, the borders looks weird, looks like they are being drawn with a different thickness, and i'm not sure how to draw the lines curved.
I really recommand you to use QGroupBox and style sheets to adjust all you want.
Here is an example (In QtDesigner, I just put a QLineEdit in a QGroupBox and made the layout of the groupBox horizontal).
ui->groupBox->layout()->setContentsMargins(2,2,2,2);
ui->centralwidget->setStyleSheet("QWidget{"\
"background-color:black;}");
ui->groupBox->setStyleSheet("QGroupBox{"\
"color:blue;"\
"background-color:black;"\
"border: 1px solid;"\
"border-color: blue;"\
"border-radius: 5px;"\
"margin-top: 20px;}"\
"QGroupBox::title{"\
"subcontrol-origin: margin;"\
"left: 20px;"\
"padding: 10px 0px 0px 0px;}");
ui->lineEdit->setStyleSheet("QLineEdit{"\
"color:white;"\
"background-color:black;"\
"border: none;}");
Here is what I've got :

Changing Background color of QCheckBox

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

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.

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.

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