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

Let widget active even if we're clicking onto the MainWindow



  • Hey together,

    what I want to achieve is pretty simple. A main window with an underlying QWidget which is just another window that shows up and allows the user to make settings. When the user is clicking onto the main window, the tool windows opacity is reduced by 50%. If the user clicks onto the tool window it goes back to 100. This is working fine, but the tool window is losing the focus when clicking onto the main window. I want that the tool window does not lose focus even if the user clicks onto the MainWindow, so both windows are active and not grayed out.

    My code looks like this:

    #include "overlaywidget.h"
    
    OverlayWidget::OverlayWidget(QWidget *parent) : QWidget(parent) {
    	this->setFixedSize(200, 25);
    	testLabel = new QLabel("Test", this);
    	layout = new QVBoxLayout(this);
    	layout->addWidget(testLabel);
    	this->setLayout(layout);
    }
    
    OverlayWidget::~OverlayWidget() {
    	delete testLabel;
    	delete layout;
    }
    
    void OverlayWidget::mousePressEvent(QMouseEvent *event) {
    	this->setWindowOpacity(qreal(100)/100);
    }
    

    and for the MainWindow:

    #include "mainwindow.h"
    
    MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
    	this->showMaximized();
    	mainMenuBar = new QMenuBar(this);
    	fileMenu = new QMenu("File", this);
    	editMenu = new QMenu("Edit", this);
    	viewMenu = new QMenu("View", this);
    	helpMenu = new QMenu("Help", this);
    
    	mainMenuBar->addMenu(fileMenu);
    	mainMenuBar->addMenu(editMenu);
    	mainMenuBar->addMenu(viewMenu);
    	mainMenuBar->addMenu(helpMenu);
    
    	this->setMenuBar(mainMenuBar);
    	this->setStyle(QStyleFactory::create("fusion"));
        QPalette darkPalette;
        darkPalette.setColor(QPalette::Window, QColor(53,53,53));
        darkPalette.setColor(QPalette::WindowText, Qt::white);
        darkPalette.setColor(QPalette::Base, QColor(25,25,25));
        darkPalette.setColor(QPalette::AlternateBase, QColor(53,53,53));
        darkPalette.setColor(QPalette::ToolTipBase, Qt::white);
        darkPalette.setColor(QPalette::ToolTipText, Qt::white);
        darkPalette.setColor(QPalette::Text, Qt::white);
        darkPalette.setColor(QPalette::Button, QColor(53,53,53));
        darkPalette.setColor(QPalette::ButtonText, Qt::white);
        darkPalette.setColor(QPalette::BrightText, Qt::red);
        darkPalette.setColor(QPalette::Link, QColor(42, 130, 218));
    
        darkPalette.setColor(QPalette::Highlight, QColor(42, 130, 218));
        darkPalette.setColor(QPalette::HighlightedText, Qt::black);
        
        this->setPalette(darkPalette);
    
        this->setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }");
    	mainMenuBar->setStyle(QStyleFactory::create("windowsvista"));
    	
    	layout = new QVBoxLayout(this);
    	widget = new OverlayWidget(this);
    	QVBoxLayout *widgetLayout = new QVBoxLayout(widget);
    	widget->setWindowFlags(Qt::Tool);
    	widget->show();
    
    }
    
    MainWindow::~MainWindow() {
    	delete mainMenuBar;
    	delete fileMenu;
    	delete editMenu;
    	delete viewMenu;
    	delete helpMenu;
    }
    
    void MainWindow::mousePressEvent(QMouseEvent *event) {
    	widget->setWindowOpacity(qreal(50)/100);
    }
    

    Here is a picture of the output:
    active

    I don't have any starting point on how to achieve this and I hope someone is helping me out on that.

    Kind regards,
    jkx1



  • Hi and welcome to devnet,

    First thing, please don't delete all that stuff in your destructors. Qt has a pattern that is based on parent widget (the parameter "this" in widget constructors) that take care of destructing all the children automatically when the parent is deleted: http://doc.qt.io/qt-5/objecttrees.html

    Now regarding your problem, only one widget can have focus at the same time. For the focus part, you can use setFocusPolicy on your widgets, giving an enum that tells more about the behavior you expect.

    For what I have experienced, playing with opacity and trying to give a modern look to a desktop software is kind of a pain. Long story short: there is no user friendly API to do so, or at least as user friendly as what QML provides. This is either because the widgets part is late compared to the QML one, or because "modern" has been associated with app, browsers, Internet, but not with desktop. Nonetheless, things might evolve in the future, since Qt developers have communicated about resuming the widgets development. This doesn't solve your problem, but could explain why you are having so much trouble trying to code an overlay that behaves with good focus policy, and using low level code such as QPalette that is always a sign you're doing something wrong, or at least not initially intended. Which could be fine, if you really know what you're doing, and you are aware that you'll have to deal with a lot of work to make your application look the same on every platform.

    EDIT:
    So I created a project with your code and here are some remarks:
    1 Do not set a layout to your main window, just set the central widget with, well

    setCentralWidget(widget)
    

    2 qreal is an alias for double, so instead of qreal(100)/100 just write 1.0; same for qreal(50)/100, just write 0.5 and it will be perfectly fine.

    3 No need to use "this->" you are coding in C++, not JAVA ;)

    For your problem, I think I don't really get what you are expecting. Just an overlay when the setting widget pops? If so, maybe working with a QDialog (a modal one) would be better.