Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Having trouble with QFrame and palette...



  • I have implemented a simple help file viewer using a QTreeView for content navigation and a QListView for bookmarks, both laid out in separate QFrame widgets which themselves are laid out vertically in a QSplitter. These occupy the left-hand part of the main window. The right-hand side has a QTextBrowser laid out in another QFrame, and this is laid out together with the other splitter horizontally in a second splitter. Everything seems to work, except that I would like to give the user visual feedback as to which pane has the current focus.

    I can navigate the panes by using the F6 key. To show the user which pane is current, I tried setting the background color of the frame containing the focussed widget to green and when it loses focus back to light gray, hoping that just the margin around the widget would change color. I have set up an event filter to trap the FocusIn and FocusOut events, which seems to work.

    But, although I have sized the grid layouts which hold the different views so that there is a 6-pixel wide margin between the frame and its widget, I do not see any color change (using the palette of the frame and setting the color role = Background. The only time I see a change is when I tried to set the Base color of the palette, but then everything turns black (including the background of the widgets inside of the frame!)

    I know there must be a way...



  • Now I can see the frame margin after setting the frame's autoFillBackground property to true. However, it is always black.

    Here is the code I have in my event filter:

    bool SbblHelpWindow::eventFilter(QObject *watched, QEvent *event)
    {
      QColor col_in = QColor(Qt::green);
      QColor col_out = QColor(Qt::lightGray);
      QColor col_to_set;
    
      if (event->type() == QEvent::FocusIn) {
        col_to_set = col_in;
      } else if (event->type() == QEvent::FocusOut) {
        col_to_set = col_out;
      }
      if (watched == ui->treeContents) {
        QPalette pal = ui->frameContents->palette();
        pal.setColor(QPalette::Window, col_to_set);
        ui->frameContents->setPalette(pal);
      } else if (watched == ui->lsvBookmarks) {
        QPalette pal = ui->frameBookmarks->palette();
        pal.setColor(QPalette::Window, col_to_set);
        ui->frameBookmarks->setPalette(pal);
      } else if (watched == ui->txtPageView) {
        QPalette pal = ui->framePageView->palette();
        pal.setColor(QPalette::Window, col_to_set);
        ui->framePageView->setPalette(pal);
      }
      return false;
    }
    

  • Lifetime Qt Champion

    Hi
    On what platform ?
    seems to use it on Windows.
    alt text

    You could test if it even uses the palette on your platform

    srand (time(NULL));
     QPalette pal = ui->frame_5->palette();
        for (int var = QPalette::WindowText; var < QPalette::PlaceholderText; ++var) {
            QColor col(rand()%255,rand()%255,rand()%255);
            pal.setColor((QPalette::ColorRole)var, col);
        }
        ui->frame_5->setPalette(pal);
    

    alt text



  • @mrjj ... thanks for looking into this. I am doing this on Linux Ubuntu 18.04.2 LTS with the default Gnome window manager.


  • Lifetime Qt Champion

    @robert-hairgrove
    Hi
    Not all platforms QStyle will draw the same way / use the palette.

    Can you try the last loop code that changes all entries to a random color and see
    if it does change the QFrame look on ubuntu.



  • @mrjj Yes, I tweaked the code a bit and added a wait of 1 second ... something like this:

    void MainWindow::on_btnGo_clicked()
    {
      ui->btnGo->hide();
      srand(time(NULL));
      QPalette pal = ui->frame2->palette();
      for (int var = QPalette::WindowText; var <= QPalette::ToolTipText; ++var) {
        QColor col(rand()%255,rand()%255,rand()%255);
        pal.setColor((QPalette::ColorRole)var, col);
        ui->label->setText(QString::number(var));
        ui->frame2->setPalette(pal);
        ui->frame2->update();
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        QApplication::processEvents();
      }
      ui->btnGo->show();
    }
    

    It always changes color when var==10, which is the QPalette::Window enum value. I suppose there is something else going on??


  • Lifetime Qt Champion

    Hi
    ok super so it does use the QPalette::Window role.

    Do you use stylesheet or anything like that ?



  • @mrjj No, I didn't try the stylesheet way, although I have heard of it.

    It's very strange; I can set the palette of all three frames to green, and it looks fine in Qt Designer. But when I use practically the same code as above, I get all black borders. I have these arranged in splitters, too, maybe that has something to do with it?

    Thanks for your help, BTW!


  • Lifetime Qt Champion

    @robert-hairgrove said in Having trouble with QFrame and palette...:

    I get all black borders.

    The borders ( the frame in QFrame) is black or
    something you see ?

    I not sure if the QSplitter could do anything as it just manages the widgets.
    However , if you use layouts margin feature, you might be seeing through something
    as that is not part of the widgets but "outside" it.

    can you show image of those black borders ?



  • OK, I finally got it to work with style sheets. :) Here is my event filter now:

    bool SbblHelpWindow::eventFilter(QObject *watched, QEvent *event)
    {
      QString col_in = "green;";
      QString col_out = "rgb(238, 238, 236);"; // light gray, this is what Designer gives me
      QString col_to_set = "background-color:";
      bool ok = false;
    
      if (event->type() == QEvent::FocusIn) {
        col_to_set.append(col_in);
        ok = true;
      } else if (event->type() == QEvent::FocusOut) {
        col_to_set.append(col_out);
        ok = true;
      }
    
      if (ok) {
        if (watched == ui->treeContents) {
          ui->frameContents->setStyleSheet(col_to_set);
        } else if (watched == ui->lsvBookmarks) {
          ui->frameBookmarks->setStyleSheet(col_to_set);
        } else if (watched == ui->txtPageView) {
          ui->framePageView->setStyleSheet(col_to_set);
        }
      }
      return false;
    }
    

    Thank you very much for the tip, @mrjj !


Log in to reply