pythonpyqt5qlabelqwidgetaction

QWidgetAction:hover in QMenuBar isn't working and doesn't want to hover


I am using class QMainWindow, as hovering doesn't want to work by any way.

Code below: -

#First imports
import PyQt5, sys

from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5.QtCore import QTimer, Qt
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QFileDialog, QMdiSubWindow, QMdiArea, QToolBar, QAction, QTextEdit, QVBoxLayout, QWidget, QMenuBar, QWidgetAction, QMenu
from PyQt5.QtGui import QTextOption, QFont, QPixmap, QImage, QIcon

class UI(QMainWindow):
    def __init__(self):
        super(UI, self).__init__()
    
#The code below is inside QMainWindow class and win = the class UI(QMainWindow) then win.show()

        self.setStyleSheet("""

        QMenuBar {
            background-color: white;
            color: black;
            border: 3px solid silver;
            font-weight: bold;
            font-size: 23px;
        }

        QMenuBar::item {
            background-color: white;
            border: 2px solid silver;
        }

        QMenuBar::item::selected {
            background-color: grey;
        }
        
        QLabel:hover { 
            background-color: grey;
        }

/*note that this is a tag: I tried both QLabel and QWidgetAction :hover method and its not working*/
        
        """)

        self.Menu = QMenuBar(self)
        self.Menu.resize(self.width(), 40)
        self.Menu.move(0, 0)
        
        self.File = self.Menu.addMenu('File')
        
        self.FileNew = QWidgetAction(self.File)
        self.New = QLabel("New")

        self.New.setMouseTracking(True)
        self.New.setAlignment(QtCore.Qt.AlignCenter)
        self.New.setStyleSheet("border: 2px solid silver; "
                       "background-color: white; color: black; "
                       "padding: 4 4 4 4px")
        self.FileNew.setDefaultWidget(self.New)

        self.File.addAction(self.FileNew)

def Start1():
    app = QApplication(sys.argv)
    win = UI()
    win.show()
    app.exec_()

Start1()

I searched in many threads and docs about :hover method and tried it but it didn't work for me. And when I hover with my mouse on the QWidgetAction it stills frozen.


Solution

  • There are lots of issues in your code, affecting the problem to different levels, but the most important one is that you are practically overwriting the style sheet for the label, completely ignoring the style sheets that could be inherited by the parent.

    Your current code also doesn't add the action to the menu, I'm going to assume that you just forgot it, but that's quite important nonetheless.

    When setting style sheets, it's almost always necessary to use property selectors (even in "final widgets" that do not contain further children), especially if pseudo states like :hover may be inherited.

    The following rule is applied on the window:

            QLabel:hover { 
                background-color: grey;
            }
    

    But then, since you're using generic properties in the label style sheet, they will override any previously set rule. Consider the original code:

            self.New.setStyleSheet("border: 2px solid silver; "
                           "background-color: white; color: black; "
                           "padding: 4 4 4 4px")
    

    Which is almost identical to this:

            self.New.setStyleSheet("""
                * { 
                    border: 2px solid silver; 
                    background-color: white; color: black; 
                    padding: 4 4 4 4px;
                }
            """)
    

    The wildcard selector applies the properties to any widget in any state, including the :hover one.

    A more appropriate solution could be to use the correct selector, which sets the default properties for any state, but also specify the case that negates the hover state:

            self.New.setStyleSheet("""
                QLabel { 
                    border: 2px solid silver; 
                    color: black; 
                    padding: 4 4 4 4px;
                }
                QLabel:!hover {
                    background-color: white;
                }
            """)
    

    In reality, both the style sheets (window and label) should probably be merged, and using more correct selectors:

            self.setStyleSheet("""
                /* ...QMenuBar as above */
    
                QMenu > QLabel { 
                    border: 2px solid silver; 
                    color: black; 
                    padding: 4 4 4 4px;
                    background-color: white;
                }
    
                QMenu > QLabel:hover { 
                    background-color: grey;
                }
    

    I strongly recommend you to read the whole QSS documentation, especially the syntax, reference and examples pages (but not excluding the others). In any case, the rule of thumb is that you should always consider selector types, and generic properties should only be used if you are completely sure of what you are doing.

    As said, there are other relevant issues: