Qt5/C++: change style of a QIcon inside a QToolBar - c++

I'm adding actions to a QToolBar only using icons and an empty text, and I want to change each action style when it is triggered (specifically, changing its border color):
toolbar = new QToolBar;
action1 = toolbar->addAction(my_icon1, "");
action2 = toolbar->addAction(my_icon2, "");
QObject::connect(action1, &QAction::triggered, [this]{
// change border color of action1
// unset border color of action2
});
QObject::connect(action2, &QAction::triggered, [this]{
// change border color of action2
// unset border color of action1
});
But since a QIcon is not a widget (not a QAction of course), I don't know where to set the style of a specific action, and QAction::associatedWidget() returns the QToolBar widget and not the associated button that owns the icon.
I'm using only C++ code, without QML or ui files.

Since QAction::parentWidget and QAction::associatedWidgets both contain the QToolBar instead of the actual action widget, I didn't give initial credit to QToolBar::widgetForAction (I thought it would be some kind of convenient function for the QAction:: methods above). But it deserves it, because it returns the actual widget for that action, as the function name says:
toolbar->widgetForAction(action1)->setStyleSheet
("QWidget { border: 1px solid blue; }");

Related

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.

Qt - Get QPushButton icon name

I have a two state QPushButton. I want to associate an icon to each state.
It is like Play|Pause buttons in music players.
To do so, I would like to get the current icon name in order to know what the next icon to set will be.
I could subclass QPushButton but is it worth it?
Instead of setting an icon based on the QPushButton's state, set one QIcon that has two states, Qt will select the correct icon if you use it with a checkable QPushButton.
QIcon icon = QIcon();
// 'Off' state corresponds to unchecked state of QPushButton
icon.addPixmap( QPixmap( ":/img/play.png" ), QIcon::Normal, QIcon::Off );
// 'On' state corresponds to checked state of QPushButton
icon.addPixmap( QPixmap( ":/img/pause.png" ), QIcon::Normal, QIcon::On );
QPushButton * button = new QPushButton();
button->setIcon( icon );
button->setCheckable( true );
Use QPushButton::icon() and QIcon::name() to get the icon name.

Qt: How to display selected text in an inactive window

I have an inactive QMainWindow with a QTabWidget as CentralWidget which holds multiple QPlainTextEdits. Beside that I have a seperate QWidget flagged with Qt::WindowStaysOnTopHint and Qt::Tool which I want to use as a find/replace tool for the QPlainTextEdits.
Now when I use the tool widget the QMainWindow is shown as inactive like it should and the selection background of the selected text in the active QPlainTextEdit is rendered as inactive (slightly grey) but I want the selection to be rendered like the QMainWindow would be active, with the default selection color w/o loosing the focus on the tool widget.
How do I achieve that?
Try something this:
QPalette p = myInactiveWidget->palette();
for (int colorRole=0; colorRole<QPalette::NColorRoles; colorRole++) p.setColor(QPalette::Inactive, colorRole, p.color(QPalette::Active, colorRole));
myInactiveWidget->setPalette(p);
That should make (myInactiveWidget)'s inactive-color-palette the same as its active-color-palette, so that it no longer looks inactive. Or if all you care about is the color of the text-selection-block, then this would probably be sufficient:
QPalette p = myInactiveWidget->palette();
p.setColor(QPalette::Inactive, QPalette::Highlight, p.color(QPalette::Active, QPalette::Highlight));
p.setColor(QPalette::Inactive, QPalette::HighlightedText, p.color(QPalette::Active, QPalette::HighlightedText));
myInactiveWidget->setPalette(p);

Disabling a QCheckbox in a tricky way

I want to make a QCheckBox named "Show Captions" disable another QCheckBox named "Show captions if no title" when the first is checked, but my problem is that how I can make it disabled immediately when the user checks the first checkbox.
SetupSlideShow::SetupSlideShow(QWidget* parent)
: QScrollArea(parent), d(new SetupSlideShowPriv)
{
QWidget* panel = new QWidget(viewport());
setWidget(panel);
setWidgetResizable(true);
QVBoxLayout* layout = new QVBoxLayout(panel);
d->showComment = new QCheckBox(i18n("Show captions"), panel);
d->showComment->setWhatsThis( i18n("Show the image caption at the bottom of the screen."));
d->showTitle = new QGroupBox(i18n("Show title"), panel);
d->showTitle->setWhatsThis( i18n("Show the image title at the bottom of the screen."));
d->showTitle->setCheckable(true);
d->showCapIfNoTitle = new QCheckBox(i18n("Show captions if no title"), panel);
d->showCapIfNoTitle->setWhatsThis( i18n("Show the image caption at the bottom of the screen if no titles existed."));
QVBoxLayout *vbox = new QVBoxLayout;
vbox->addWidget(d->showCapIfNoTitle);
d->showTitle->setLayout(vbox);
layout->addWidget(d->showLabels);
layout->addWidget(d->showComment);
layout->addWidget(d->showTitle);
}
Doesn't this work?
connect(d->showComment, SIGNAL(toggled(bool)), d->showCapIfNoTitle, SLOT(setDisabled(bool)));
The call to paintEvent() isn't really doing anything for you regarding immediacy. Nothing will be repainted until control returns to the event loop (after your constructor exits). It is more typical to call update() but even this is unnecessary when changing the properties of built in widgets.
To link the check boxes, define a slot for the stateChanged() signal of showComment, connect the signal to your slot in your constructor above (by calling connect(), and in that slot, call d->showCapIfNoTitle->setCheckState(d->showComment->checkState()).

Extrend QAbstractListModel to display custom background color?

Greetings all,
I have extended my own QAbstractListModel to change the background color of QCombobox.
As seen it the image ,I have two issues.
1) As shown in the first image snapshot , background color doesnt appear for the selected item.
2) When selecting items , the background turns in to default highlight color (light blue)
Is there anyway to fix these two issues ?
Here is my QAbstractListModel implementation.
RzContourLabelModel::RzContourLabelModel(RzContourLabelContext *contourLabelCtx,int max,QObject *parent) : QAbstractListModel(parent){
contourCtx=contourLabelCtx;
QList contourLabels=contourLabelCtx->getLabels();
for(int i=0;i= colorLabels.size())
return QVariant();
if (role == Qt::DisplayRole){
QString str;
str.setNum(colorLabels.at(index.row()));
return str;
}
if (role == Qt::BackgroundRole)
{
int labelNum=colorLabels.at(index.row());
QColor col= contourCtx->getLabelColor(labelNum);
return col;
}
return QVariant();
}
Both features (background of the selected item and highlighting color) are controlled by the view. Here is a quote from the docs:
For the text and icon in the combobox label, the data in the model that has the Qt::DisplayRole and Qt::DecorationRole is used.
So the background of the selected item wont be easy to change. Instead you might want to make color icons and return them as the Qt::DecorationRole in the model.
For the highlighting color - you can reimplement this with a custom item delegate. See QComboBox::setItemDelegate
You may try to play with Qt CSS...
Not sure this help you but it may:
QComboBox QAbstractItemView {
selection-background-color: Transparent;
selection-color: Black;
}
it prevents from colorizing selection, the only thing i am not sure about - will it paint your widget's background or your item's background in case of selection. If it will paint widget's background - it is useless :(