How to set StyleSheet for an specific label in QMessageBox? - c++

I Want to have a bigger QMessageBox and centered texts in it but when I increase the size of it by stylsheet it'll be like this:
if I could give it Some Padding or margin it would be fixed but I can't.
void MainWindow::showMsg()
{
QMessageBox m_MsgBox;
m_MsgBox.setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
m_MsgBox.setIcon(QMessageBox::Warning);
m_MsgBox.setText("Your Trial is finished! Please purachase a plan.");
m_MsgBox.setStandardButtons(QMessageBox::Ok);
m_MsgBox.setStyleSheet("QLabel{min-width:200 px; font-size: 13px;} QPushButton{ width:25px; font-size: 13px; }");
if(m_MsgBox.exec() == QMessageBox::Ok)
m_MsgBox.close();
}
I want to give different css properties to each QLabel(QMessageBox::Warning & setText) in this QMessageBox.

You can address specific sub-widgets within a widget by their object name:
QLabel#MyLabel { style... }
QWidget* p_widget = new QWidget;
QLabel* p_label1 = new QLabel;
p_label1->setText("I'm not cool.");
QLabel* p_label2 = new QLabel;
p_label2->setObjectName("coolLabel");
p_label2->setText("I'm VERY cool.");
QVBoxLayout* p_layout = new QVBoxLayout;
p_layout->addWidget(p_label1);
p_layout->addWidget(p_label2);
p_widget->setLayout(p_layout);
p_widget->setStyleSheet("QLabel {color: black;} QLabel#coolLabel {color: red;}");
This example should work.
I want to stress though, that setting sizes and layouts through QSS is a bad idea. Get comfortable with QLayouts, they are very powerful and dynamic!
btw: "Your trial has ended. Please purchase a plan."

I got this answer in qt forum:
Only answering to your topic title, if you look into the source code of QMessageBox, every label has a object name, so that should be easy to set different style to them by using ID selector.
text: "qt_msgbox_label"
icon: "qt_msgboxex_icon_label"
informativeText: "qt_msgbox_informativelabel"
Note: These names may change in future versions.

Related

QObject::findChild returns 0 for QLabels added to statusbar

I created a application running in a QMainWindow using qtcreator, so the typical way.
I added two 'manually' (meaning: not with the Form editor) created qlabels to the statusbar:
in the header:
QLabel *label_timestamp;
QLabel *contentLabel_timestamp;
in the constructor:
MainWin::MainWin(const CmdLineOptions &opts, QWidget *parent)
: QMainWindow(parent),
ui(new Ui::MainWin),
m_connectionStatusLabel(new QLabel),
m_client(new QMqttClient),
m_mqttmanager(new MQTTManager(m_client)),
m_mqttServerName("localhost")
{
ui->setupUi(this);
label_timestamp = new QLabel(this);
contentLabel_timestamp = new QLabel(this);
label_timestamp->setText("system time");
contentLabel_timestamp->setText("dd.mm.yyyy, hh:mm:ss:zzz"); /* just testing output */
statusBar()->addPermanentWidget(label_timestamp);
statusBar()->addPermanentWidget(contentLabel_timestamp);
}
If I do a
Label *label = findChild<QLabel *>(QString("contentLabel_")+objName);
elsewhere in this class implementation with objName being 'timestamp', of course, findChild() returns 0. It's working fine with other QLabels created using QtCreator in the form editor, findChild() finds them all. Isn't the statusbar widget and its content also a child of ui? Does somebody eventually know a way out of there?
I want to use findChild to generically fill my labels following a naming scheme with content I receive over MQTT, this is the background. Would be great if the statusbar content would need a special handling but could also be handled in this dynamic approach.
Thanks a lot
findChild uses the objectName, in the case of Qt Creator this establishes it in the MOC, but in your case you must establish it:
label_timestamp = new QLabel(this);
contentLabel_timestamp->setObjectName("label_timestamp");
contentLabel_timestamp = new QLabel(this);
contentLabel_timestamp->setObjectName("contentLabel_timestamp");
And then you can recover it with:
QLabel *label_1 = findChild<QLabel *>("label_timestamp");
if(label_1){
// some code
}
QLabel *label_2 = findChild<QLabel *>("contentLabel_timestamp");
if(label_2){
// some code
}

Qt: change font weight

I would like to have my text in QLabel somewhere between bold and normal style and I believe that setting font-weight should be the answer to my problem.
In Qt documentation, I have found out that there are two options how to change font-weight:
From cpp side via: QFont::setWeight() method which accepts numbers 0-99
http://doc.qt.io/qt-4.8/qfont.html#Weight-enum
From Qss style via: font-weight attribute, which accepts numbers 100,200,...,900
http://doc.qt.io/qt-4.8/stylesheet-reference.html#font-weight
I have tried both methods and nothing seems to work. I always get only normal or the ordinary bold style and nothing in between.
Example:
QLabel* test1 = new QLabel("Font-weight testing");
test1->show();
QLabel* test2 = new QLabel("Font-weight testing");
QFont font = test2->font();
font.setWeight(40);
test2->setFont(font);
test2->show();
QLabel* test3 = new QLabel("Font-weight testing");
test3->setStyleSheet("font-weight: 400");
test3->show();
In the example above, I have created 3 labels. One without any additional setting, one where I have changed font weight via setWeight method, and one where the font-weight should be changed via Qss style. But all three will end up being exactly the same.
I have even tried to make font bigger, enable antialiasing, or use different font but nothing helped.
The QFont::setWeight method expects its input value to be one of the QFont::Weight enum values.
http://doc.qt.io/qt-5/qfont.html#setWeight
The correct version:
QLabel* test2 = new QLabel("Font-weight testing");
QFont font = test2->font();
font.setWeight(QFont::Bold);
test2->setFont(font);
Also you have two errors in the QSS version. First, you didn't specify a selector for your rule. Second, the value of 400 corresponds to 'normal' font.
https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight
The correct version:
QLabel* test3 = new QLabel("Font-weight testing");
test3->setStyleSheet("QLabel { font-weight: bold; }");
Use function setWeight like this: setWeight(QFont::ExtraBold);
QFont font;
font.setWeight(QFont::ExtraBold); // set font weight with enum QFont::Weight
font.setPixelSize(25); // this for setting font size
ui->label->setFont(font);
void QFont::setWeight(int weight):
Sets the weight the font to weight, which should be a value from the QFont::Weight enumeration.

Qt: How to add two widgets (say QPushButton) to the status bar, one to the left and other to the right side?

I would like to add two widgets (say QPushButton) to the status bar, one to the left and other to the right side.
I am thinking of adding horizontal spacer in between the two widgets, but don't know how to add.
PS: I tried using addWidget() to add to the left and addPermanentWidget() to add to the right but it doesn't look neat and also it doesn't feel right.
You can add two buttons to a layout in a widget and add the widget to the status bar using QStatusBar::addWidget :
QWidget * widget = new QWidget();
QPushButton * leftBut = new QPushButton("Left");
QPushButton * rightBut = new QPushButton("Right");
QGridLayout * layout = new QGridLayout(widget);
layout->addWidget(leftBut,0,0,1,1,Qt::AlignVCenter | Qt::AlignLeft);
layout->addWidget(rightBut,0,1,1,1,Qt::AlignVCenter | Qt::AlignRight);
ui->statusBar->addWidget(widget,1);
I am thinking of adding horizontal spacer in between the two widgets, but don't know how to add.
Here is a way to use a "fake" spacer.
QPushButton *leftButton = new QPushButton("Left");
QPushButton *rightButton = new QPushButton("Right");
QLabel *spacer = new QLabel(); // fake spacer
ui->statusBar->addPermanentWidget(leftButton);
ui->statusBar->addPermanentWidget(spacer, 1);
ui->statusBar->addPermanentWidget(rightButton);
The second parameter in addPermanentWidget is "used to compute a suitable size for the given widget as the status bar grows and shrinks".
Demo:
I think the simplest way is using a QGridLayout (honestly I never tried to modify a status bar anyway) supposing that the status bar is or descends from widget you can do this:
QGridLayout *myGridLayout = new QGridLayout();
statusbar->setLayout(myGridLayout)
QPushButton *button1 = new QPushButton(this);
myGridLayout->addWidget(button1,0,0,1,1);
QPushButton *button2 = new QPushButton(this);
myGridLayout->addWidget(button2,X,0,1,1);
The biggest is X the more space you want to leave in between, I would suggest to start with 3 and then make few tests to see how it looks.

Qt GUI Design - Is there an invisible character suitable for label text?

Okay I'm working on a GUI with Qt Designer for c++, and I have a bunch of labels setup to display some content from a file once it is loaded.
On the labels that are used to display loaded content, I currently have them set to "set later", and in the initial GUI configuration, I call ui->label_id.setText(""); on each of the labels before they can be seen. I really just want them to have some text so I can visually see them in the designer, yet not have any when the program is running before content is loaded.
So my question is: Is this the best way to handle this? Or is there a character I can set the text to in designer that won't appear at runtime?
With more and more labels as my gui expands, I don't want to bog down the loading time of the program setting the text to "" for every one, so that's why I'm here.
One possible solution could be to set a color to that labels with a transparent color (0 alpha value).
This can be handled via a style sheet in the widget constructor:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
setStyleSheet("QLabel { color: qrgba(255, 255, 255, 0); }");
}
If you want to selectively apply a stylesheet to a label, you could use all kinds of Qt Style Sheet Selector Types.
You could use the ID Selector for example. If you've set in QtDesigner the objectName attribute of a label to label_1, you hide this label selectively by setting this style sheet:
setStyleSheet("#label_1 { color: qrgba(255, 255, 255, 0); }");
A more advanced solution would be a method that returns the style sheet for the object names:
QString MainWindow::styleSheetForHiddenLabels(const QStringList &labelObjectNames)
{
QString styleSheet;
foreach (QString labelName, labelObjectNames) {
QString style("#");
style.append(labelName);
style.append(" { color: qrgba(255, 255, 255, 0); }");
styleSheet.append(style);
}
return styleSheet;
}
This method could be used this way:
QStringList labelNames;
labelNames << "label1" << "label2" << "label3";
QString stylesheet = styleSheetForHiddenLabels(labelNames);
setStyleSheet(stylesheet);
An alternative to the stylesheet answer.
QList<QLabel*> widgets = this->findChildren<QLabel*>();
for (QLabel *label : widgets) {
label->setText("");
}
place this in your MainWindow class constructor. It will get a list of all QLabels from your window, you can then cycle through them and set the text to "".
You can use Object inspector. In Object inspector you'll se a list of your labels, and when you click on some of your labels you'll see border around your widget. That way you can see your labels without putting any text in it.

Setting the form lines like iTunes info dialog on Mac with Qt

I'm just a beginner and I wonder if it would be possible to create a form widget on Mac like the info dialog in iTunes.
I tried using:
QGroupBox: I cannot find a way to get rid of the frames.
Creating my own widget: I cannot find a way to fix the spacing between the label and the QLineEdit widget using the QVBoxLayout (actually I'm not sure I understand well the differences between margin/spacing).
QFormLayout: I cannot find a way to reduce the size of the QLabel after using setrowWrapPolicy::WrapAllRows
Also I am not (yet) very comfortable with QtDesigner, so i'd like to avoir using it (for now)
Thanks in advance
Edit: Some precisions on the programs. I use QtCreator 2.6.1 with Qt 4.8.1 and 5.0 on Mac OS X Mountain Lion.
Edit 2: Here is the code.
Subclass of QWidget:
MCLineEdit::MCLineEdit(const QString &header)
{
m_lineEdit = new QLineEdit;
m_lineTitle = new QLabel(header);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(m_lineTitle);
layout->addWidget(m_lineEdit);
layout->setSpacing(0);
setLayout(layout);
}
To display the widget
myView::myView(QWidget *parent) :
QWidget(parent)
{
setFixedSize(600, 500);
MCLineEdit *lineEdit1 = new MCLineEdit("Test 1");
MCLineEdit *lineEdit2 = new MCLineEdit("Test 2");
MCLineEdit *lineEdit3 = new MCLineEdit("Test 3");
MCLineEdit *lineEdit4 = new MCLineEdit("Test 4");
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(lineEdit1);
mainLayout->addWidget(lineEdit2);
mainLayout->addWidget(lineEdit3);
mainLayout->addWidget(lineEdit4);
mainLayout->setSpacing(0);
setLayout(mainLayout);
}
This can be accomplished a ton of ways I am sure. Qt gives you all the possible layouts you could need to achieve this. You could do it with a QGridLayout, and add widgets with different amounts of "cell" spanning, and control the row and column sizes to suit. Or you can just do it with a bunch of nested vertical/horizontal layouts.
For example, you can group a label and a field together in a QVBoxLayout, by adding the widgets with a left alignment, and then setting the spacing to 0 between the items:
layout->setSpacing(0);
layout->addWidget(aLabel, Qt::AlignLeft);
layout->addWidget(aLineEdit, Qt::AlignLeft);
mainVerticalLayout->addLayout(layout);
For something like the track numbers, it is just more nested layouts:
vLayout->addWidget(aLabel);
hLayout->addWidget(aCheckbox);
hLayout->addWidget(aLabel);
hLayout->addWidget(aCheckbox);
vLayout.addLayout(hLayout);
And regarding your bullet points:
QGroupBox lets you remove the frame with setFlat(bool)
With layouts, the margin is the padding around the outside of the contained widgets. What you want is setSpacing(int) to control the amount of space between the items in the layout.
QFormLayout is probably not your best choice here. That is usually for having labels on one side and widgets on the other. Basically it is a 2 column layout. A QGridLayout would be more appropriate. And to reduce the size of the QLabel, you can give it a max or a fix size. Such as using setFixedWidth() or setMaximumWidth() on the label.
So I finally managed to get the expected result after playing a bit with QtCreator.
Here is the code for who might be interested:
myLineEdit:myLineEdit(const QString &header)
{
m_lineEdit = new QLineEdit;
m_groupBox = new QGroupBox;
QFont groupFont;
groupFont.setPixelSize(10);
groupFont.setBold(true);
m_groupBox->setTitle(header);
m_groupBox->setFlat(true);
m_groupBox->setFont(groupFont);
m_groupBox->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
QFont lineFont;
lineFont.setPixelSize(13);
lineFont.setBold(false);
m_lineEdit->setFont(lineFont);
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(m_lineEdit);
layout->setContentsMargins(0, 10, 0, 0);
layout->setSpacing(10);
layout->setSizeConstraint(QLayout::SetMinAndMaxSize);
m_groupBox->setLayout(layout);
QHBoxLayout *mainLayout = new QHBoxLayout;
mainLayout->addWidget(m_groupBox);
setLayout(mainLayout);
}
One comment though: will only work on Qt 5 since on 4.8 the setFlat() method will display a separating line between the header and the QLineEdit.
Thanks to jdi for his help!