QComboBox text renders as white/transparent when item is selected - qt

I have a QComboBox in my program with 5 items + 1 blank (default) item. I implemented a stylesheet to make the background transparent when nothing is changed (i.e. when the item selected is the blank/default one) and light-green, when the item selected, is different. My problem is: when I select a different item, Qt renders the selected item color as white:
When I click on other elements of the application (buttons, the QDateEdit, etc), it renders the value black (expected behavior):
I don't know what I'm missing here. I tried to look for a solution or even a diagnosis of this problem in both StackOverflow and the Qt forums. For reference, my QComboBox's stylesheet is the following:
QComboBox#access_level[changed="false"]{
background-color:"transparent";
}
QComboBox#access_level[changed="true"]{
background-color:rgba(171, 246, 183, 50);
color:rgb(0, 0, 0);
}
I also tried to remove the stylesheet and the problem persisted. Also, to implement the changed variable my code looks like the following:
class MassActionDialog(QDialog):
def __init__(self, parent=None):
'''
super(MassActionDialog, self).__init__(parent)
self.dialog = Ui_MassActionDialog()
self.dialog.setupUi(self)
.
.
self.original_access_level = 60
self.access_level = self.original_access_level
self.dialog.access_level.currentIndexChanged.connect(self.on_access_level_change)
def on_access_level_change(self, idx):
new_access_level = (idx + 1)*10
if new_access_level == self.original_access_level:
# we mark the "changed" property as false
self.dialog.access_level.setProperty("changed", False)
else:
self.dialog.access_level.setProperty("changed", True)
self.access_level = new_access_level
# reload the stylesheet of the object
self.dialog.access_level.style().unpolish(self.dialog.access_level)
self.dialog.access_level.style().polish(self.dialog.access_level)
Any help in this matter would be greatly appreciated!

Your problem is in QSS, just add color property to state with changed="false", like:
QComboBox#access_level[changed="false"]{
background-color:"transparent";
color:rgb(0, 0, 0);
}
QComboBox#access_level[changed="true"]{
background-color:rgba(171, 246, 183, 50);
color:rgb(0, 0, 0);
}
And one more thing - set changed property in __init__ with your default value.

Related

QComboBox retains mouse hover highlight if you close popup

I am having some issues styling my QComboBoxes. I want to have them highlight when mouse over, but it seems they retain the highlight if I click on them and then close the pop-up (either by clicking outside or by selecting something, does not matter). I am using Qt 5.13.1 and I see this issue on macOS and Linux. Haven't tested on others but I guess it would be the same.
My style is this simple, maybe I am missing something:
QComboBox:hover
{
background-color: rgba(0, 0, 0, 0.2);
}
Is this what you're looking for? Or do you mean the hover color of the QComboBox when you did not yet press to view all the other options?
QComboBox QAbstractItemView
{
selection-color: white;
selection-background-color: black;
}
EDIT (after reading the comments):
Right click on the combobox in the designer space and chose go to slot.
Then press CurrentIndexChanged(int) and change the code of the slot to this:
void MainWindow::on_comboBox_currentIndexChanged(int index)
{
ui->comboBox->setStyleSheet("QComboBox:!editable, QComboBox::drop-down:editable {"
"background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,"
"stop: 0 #E1E1E1, stop: 0.4 #DDDDDD,"
"stop: 0.5 #D8D8D8, stop: 1.0 #D3D3D3);}");
}
Ok, I managed to work around this issue, will write it here in case anybody else has this problem. I quit trying to use qss and did it in the code. Subclassed the QComboBox and added the hover events:
bool TrackableComboBox::event(QEvent *event)
{
switch (event->type())
{
case QEvent::Enter:
this->setStyleSheet("background-color: rgba(0, 0, 0, 0.2);");
break;
case QEvent::Leave:
case QEvent::MouseButtonPress:
this->setStyleSheet("background-color: -1;");
break;
default:
break;
}
return QWidget::event(event);
}
The secret here is to add Leave and MouseButtonPress reset the color, otherwise you will have the same issue.

Qt - make selection background have similar background to item

How can I make the background for when an item is selected to be some sort of blend of current cell background?
The default item-selection background is blue and say if my cell is red, then I'd want it to be red with slightly less opacity:
Example image of how it is
Example image of how I'd like it to be
I have tried setting the color to be transparent:
setStyleSheet("selection-background-color: transparent")
And also the rgba feature with opacity 1%:
setStyleSheet("selection-background-color: rgba(255, 255, 255, 1)")
But neither retain the original color
This example will give you some insight how to manage with tablewidgets and item
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
data = {'col1':['red','blue','green']}
class MyTable(QTableWidget):
def __init__(self, data, *args):
QTableWidget.__init__(self, *args)
self.data = data
self.setmydata()
self.resizeColumnsToContents()
self.resizeRowsToContents()
self.setStyleSheet("""QTableView::item:focus
{
selection-background-color: rgba(255, 0, 0, 128);
}""")
def setmydata(self):
horHeaders = []
for n, key in enumerate(sorted(self.data.keys())):
horHeaders.append(key)
for m, item in enumerate(self.data[key]):
newitem = QTableWidgetItem(item)
self.setItem(m, n, newitem)
colorVal = "Qt.%s" % item
self.item(m, n).setBackground(eval(colorVal))
self.setHorizontalHeaderLabels(horHeaders)
def main(args):
app = QApplication(args)
table = MyTable(data, 3, 1)
table.show()
sys.exit(app.exec_())
if __name__=="__main__":
main(sys.argv)

Background colour of child indicator in QTreeWidgetItem?

I'm using a QTreeWidget to show a list of categorized properties. I would like the top level items to be a different background colour; however, the arrow indicating it has children is always the default black on white (Windows 8.1, Qt 5.2.1). Here's how I'm adding the QTreeWidget Item:
QBrush fg(Qt::white);
QBrush bg(Qt::darkGray);
QTreeWidgetItem *header = new QTreeWidgetItem();
header->setText(0, "Sound File");
this->addTopLevelItem(header);
header->setFirstColumnSpanned(true);
header->setData(0, Qt::ForegroundRole, fg);
header->setData(0, Qt::BackgroundRole, bg);
header->setExpanded(true);
Here's a screenshot of how this gets rendered.
How can I give it a solid background across the whole row?
For the indicators you can use StyleSheets something like this:
QTreeWidget::branch::!has-children:selected {background-color: rgb(255, 255, 255);}
QTreeWidget::branch::!has-children:selected:alternate {background-color: rgb(0, 0, 0);}
and set this StyleSheet to the QTreeWidget..
If someone knows any other way to do this for the individual items feel free to share... I have similar situation where I was one of the item that have children to be different color..

When using AlivePDF library in Flex the beginFill method sets font colour rather than background colour

Code sample:
var headerRowBackground:RGBColor = new RGBColor(0);
headerRowBackground.b = 58;
headerRowBackground.g = 28;
headerRowBackground.r = 255;
printPDF.beginFill(headerRowBackground);
printPDF.addCell(30, 20, "Room");
The word "Room" is in red, as is the rest of the text in the PDF. I actually want to make the cell background colour red. Anybody know why this doesn't work?
You should look at the API more:
printPDF.addCell(30, 20, 'Room', 0, 0, '1', 0xFF0000);
The documentation is wrong, the fill parameter is described as "Link can be internal to do document level navigation (InternalLink) or external (HTTPLink)".
The code to get this working is:
printPDF.beginFill(new RGBColor(0xFF0718));
printPDF.textStyle(new RGBColor(0x000000));
printPDF.addCell(30, 10, "Room", 0, 0, Align.LEFT, 1);
A couple of things about the code:
The fill parameter should be 0 or 1
rather than the fill value. It just
either switches on or off the fill
value previously set.
The text style
should be set too otherwise the text
and background will use the same
colour

In a QTableWidget, changing the text color of the selected row

I'm using a QTableWidget to display several rows. Some of these rows should reflect an error and their text color is changed :
Rows reflecting that there is no error are displayed with a default color (black text on white background on my computer).
Rows reflecting that there is an error are displayed with a red text color (which is red text on white background on my computer).
This is all fine as long as there is no selection. As soon as a row is selected, no matter of the unselected text color, the text color becomes always white (on my computer) over a blue background.
This is something I would like to change to get the following :
When a row is selected, if the row is reflecting there is no error, I would like it to be displayed with white text on blue background (default behavior).
If the row is reflecting an error and is selected, I would like it to be displayed with red text on blue background.
So far I have only been able to change the selection color for the whole QTableWidget, which is not what I want !
Answering myself, here is what I ended up doing : a delegate.
This delegate will check the foreground color role of the item. If this foreground color is not the default WindowText color of the palette, that means a specific color is set and this specific color is used for the highlighted text color.
I'm not sure if this is very robust, but at least it is working fine on Windows.
class MyItemDelegate: public QItemDelegate
{
public:
MyItemDelegate(QObject* pParent = 0) : QItemDelegate(pParent)
{
}
void paint(QPainter* pPainter, const QStyleOptionViewItem& rOption, const QModelIndex& rIndex) const
{
QStyleOptionViewItem ViewOption(rOption);
QColor ItemForegroundColor = rIndex.data(Qt::ForegroundRole).value<QColor>();
if (ItemForegroundColor.isValid())
{
if (ItemForegroundColor != rOption.palette.color(QPalette::WindowText))
{
ViewOption.palette.setColor(QPalette::HighlightedText, ItemForegroundColor);
}
}
QItemDelegate::paint(pPainter, ViewOption, rIndex);
}
};
Here is how to use it :
QTableWidget* pTable = new QTableWidget(...);
pTable->setItemDelegate(new MyItemDelegate(this));
What you'll want to do is connect the selectionChanged() signal emitted by the QTableWidget's QItemSelectionModel to a slot, say OnTableSelectionChanged(). In your slot, you could then use QStyleSheets to set the selection colours as follows:
if (noError)
{
pTable->setStyleSheet("QTableView {selection-background-color: #000000; selection-color: #FFFFFF;}");
}
else
{
pTable->setStyleSheet("QTableView {selection-background-color: #FF0000; selection-color: #0000FF;}");
}
It looks ok, but you might want to look at the documentation of QStyleOption it can tell you wether the item drawn is selected or not, you don't have to look at the draw color to do that. I would probably give the model class a user role that returns whether the data is valid or not and then make the color decision based on that. I.e. rIndex.data(ValidRole) would return wether the data at this index is valid or not.
I don't know if you tried overriding data for the BackgroundRole and returning a custom color, Qt might do the right thing if you change the color there
You could, of course, inherit from the table widget and override the paint event, but I don't think that is what you want to do.
Instead, should use the QAbstractItemDelegate functionality. You could either create one to always be used for error rows, and set the error rows to use that delegate, or make a general one that knows how to draw both types of rows. The second method is what I would recommend. Then, your delegate draws the rows appropriately, even for the selected row.
You could use e.g. a proxy model for this where you return a different color if you have an error for the specific modelindex;
QVariant MySortFilterProxyModel::data(const QModelIndex & index, int role = Qt::DisplayRole) {
// assuming error state and modelindex row match
if (role==Qt::BackgroundRole)
return Qt::red;
}

Resources