Forum > QT

Setting palettes for specific widgets/widget classes?


What is the correct way to make a QPalette apply to all controls of a specific type? 

Using raw QT objects, I can use QApplication_setPalette(Palette, 'QCheckBox') or QWidget_setPalette(Widget, Palette);  Neither of those work for me for LCL backed controls, and modifying the TQtWidget(Handle).Palette.Handle doesn't seem to have an effect either.  I'm fine with creating any subclasses that would be required.

My specific goal is an application-wide dark mode palette, but at least with the Fusion style, checkboxes use QPaletteWindow for the square indicator frame, so they're almost invisible if the window itself is dark too.  I'd want to override just QPaletteWindow for QCheckBox, QListItem, and ideally TQtThemeServices.DrawElement(tbCheckBox*).

Since TQtThemeServices.DrawElement needs the palette applied using QStyleOption_setPalette, I don't see a way to do that with the existing ThemeServices API.  I could extract the relevant bits though.  Alternatively, would it make sense to query the palette from the context's parent at the top where it's initializing QPainter_setBackground?

For the LCL controls, the project I'm currently testing with is:

1) Create a new LCLQt5 project.
2) Add a TCheckbox and a TListView that has a single item and has Checkboxes := True.
3) Add an OnShow handler that creates a second form using the raw Qt API with matching controls, and sets the application/widget palettes appropriately:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure TForm1.FormShow(Sender: TObject);type  TQPaletteColorRole = QPaletteWindowText..QPaletteToolTipText;const  AppPalette: array[TQPaletteColorRole] of TColorRef = (    $eeeeee, $353535, $4b4b4b, $404040, $232323, $2c2c2c, $eeeeee, $0000ff,    $eeeeee, $282828, $353535, $2d2d2d, $a75824, $ffffff, $ff5500, $ff5500,    $353535, $000000, $2d2d2d, $eeeeee);var  Check: QCheckBoxH;  S: WideString;var  Palette: QPaletteH;  QColor: TQColor;  ColorRole: TQPaletteColorRole;  List: QListWidgetH;  Item: QListWidgetItemH;  RawWindow: QMainWindowH;begin  S := 'Raw QT';  // Create raw window  RawWindow := QMainWindow_Create;  QWidget_resize(RawWindow, Scale96ToScreen(220), Scale96ToScreen(150));  // Raw checkbox  Check := QCheckBox_Create(@S, RawWindow);  QWidget_setGeometry(Check, Scale96ToScreen(10), Scale96ToScreen(10),    Scale96ToScreen(200), Scale96ToScreen(20));  QWidget_show(Check);  // Raw listbox with checkboxes  List := QListWidget_Create(RawWindow);  QWidget_setGeometry(List, Scale96ToScreen(10), Scale96ToScreen(40),    Scale96ToScreen(200), Scale96ToScreen(100));  Item := QListWidgetItem_Create(@S, List);  QListWidgetItem_setFlags(Item, QListWidgetItem_flags(Item) or QtItemIsUserCheckable);  QListWidgetItem_setCheckState(Item, QtUnchecked);  Item := QListWidgetItem_Create(@S, List);  QListWidgetItem_setFlags(Item, QListWidgetItem_flags(Item) or QtItemIsUserCheckable);  QListWidgetItem_setCheckState(Item, QtChecked);  QWidget_show(List);  // Show raw window  QWidget_show(RawWindow);  // Set default application palette  Palette := QPalette_Create();  try    QColor := Default(TQColor);    for ColorRole := Low(ColorRole) to High(ColorRole) do    begin      ColorRefToTQColor(AppPalette[ColorRole], QColor);      QPalette_setColor(Palette, ColorRole, @QColor);    end;    QApplication_setPalette(palette);  finally    QPalette_Destroy(Palette);  end;  // Set control-specific palettes  Palette := QPalette_Create();  try    ColorRefToTQColor(clLime, QColor);    QPalette_setColor(Palette, QPaletteWindow, @QColor);    // Update for all QCheckBoxes and QListViews    QApplication_setPalette(Palette, 'QCheckBox');    QApplication_setPalette(Palette, 'QListView');    // Try to set for LCL checkbox?    QWidget_setPalette(TQtWidget(CheckBox1.Handle).Widget, Palette); // Doesn't work    QPalette_setColor(TQtWidget(CheckBox1.Handle).Palette.Handle, // Doesn't work      QPaletteWindow, @QColor);  finally    QPalette_Destroy(Palette);  end;end; 
With that code the raw QCheckBox and QListWidget have bright green borders, but the TCheckbox and TListView are both still dark-on-dark.

I'd prefer to avoid using stylesheets if possible, since that requires fully specifying the appearance of all of the checkbox states.  Overriding just QCheckbox::indicator's border color isn't enough.

Palette can be setted up at application level (Fusion style), but control by control never worked for me,
I'm afraid that your problem can be fixed only via stylesheets.


[0] Message Index

Go to full version