pyside2qlabelqmenu

How to keep the blue background color after right clicking the selected text in QLabel to generate a QMenu?


I want to keep the selected text keep the blue background color,but when i right clicked the text to generate a menu,the selected text will turn gray.how should i do. when i clicked the qlabel text to make it selected,the result is like this picture. And when i right click the selected text,the blue color turn gray. here is my demo code.

enter image description here

enter image description here

import pyperclip
import sys
from PySide2.QtCore import  Qt
from PySide2.QtGui import QCursor
from PySide2.QtWidgets import QLabel,QMenu,QAction,QHBoxLayout,QApplication,QWidget

class moreInfoLabel(QLabel):
    def __init__(self, *args, **kw):
        super().__init__(*args, **kw)
        self.setTextInteractionFlags(Qt.TextSelectableByMouse)
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.rightMenuShow)#开放右键策略
        self.setStyleSheet('''
        QMenu {
            border: Opx;
            font-size: 9pt;
            width:100px;
            background-color:white
        }

        QMenu::item { 
            width:160px;
            font-family: "Microsoft YaHei";
            border: 0px;
            min-height: 15px;
            max-height: 26px;
            padding:10px 15px 10px 15px;
            font-size: 9pt; 
        }
        
        QMenu::item:selected { 
            background-color: #f9f9f9;
        }
        QLabel{
            font-size:13px;
            font-family:微软雅黑;

        }
        ''')

    def rightMenuShow(self, pos):
        print(self)
        menu = QMenu(self)
        menu.addAction(QAction('复制', menu))
        menu.addAction(QAction('全选', menu))

        menu.triggered.connect(self.menuSlot)
        menu.exec_(QCursor.pos())
        self.setStyleSheet('''
        QMenu {
            border: Opx;
            font-size: 9pt;
            width:100px;
            background-color:white
        }

        QMenu::item { 
            width:160px;
            font-family: "Microsoft YaHei";
            border: 0px;
            min-height: 15px;
            max-height: 26px;
            padding:10px 15px 10px 15px;
            font-size: 9pt; 
        }
        
        QMenu::item:selected { 
            background-color: #f9f9f9;
        }
        QLabel{
            font-size:13px;
            font-family:微软雅黑;
            background-color: #f9f9f9;
        }
        ''')
    
    def menuSlot(self, act):
        if act.text() == '复制':
            pyperclip.copy(self.selectedText())
        elif act.text() == '全选':
            len1 = len(self.text())
            self.setSelection(0,len1)
            self.selectedText = self.text

class Demo(QWidget):

    def __init__(self):
        super(Demo, self).__init__()

        self.moreinfo = moreInfoLabel("YOUJIAN")
        self.layout = QHBoxLayout()
        self.layout.addWidget(self.moreinfo)
        self.setLayout(self.layout)



if __name__ == "__main__":
    app = QApplication()
    demo = Demo()
    demo.show()
    sys.exit(app.exec_())
    

Is there any way to solve this problem


Solution

  • When the menu is shown, the widget uses the Inactive color group of the palette, which is the one normally used when the widget is in a window that is not active.

    The simple solution is to temporarily replace the Highlight and HighlightedText color role for that group and restore the original palette afterwards. This step is necessary for consistency, as the default Inactive colors should be kept in case the window is actually unfocused.

    Note that in the following example I did some changes:

    class MoreInfoLabel(QLabel):
        _defaultPalette = None
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.setTextInteractionFlags(Qt.TextSelectableByMouse|Qt.TextEditable)
            self.setStyleSheet('''
            QMenu {
                border: Opx;
                font-size: 9pt;
                width:100px;
                background-color:white
            }
    
            QMenu::item { 
                width:160px;
                font-family: "Microsoft YaHei";
                border: 0px;
                min-height: 15px;
                max-height: 26px;
                padding:10px 15px 10px 15px;
                font-size: 9pt; 
            }
            
            QMenu::item:selected { 
                background-color: #f9f9f9;
            }
            QLabel{
                font-size:13px;
                font-family:微软雅黑;
            }
            ''')
    
        def contextMenuEvent(self, event):
            oldPalette = self.palette()
            tempPalette = self.palette()
            tempPalette.setBrush(tempPalette.Inactive, tempPalette.Highlight, 
                oldPalette.highlight())
            tempPalette.setBrush(tempPalette.Inactive, tempPalette.HighlightedText, 
                oldPalette.highlightedText())
            self.setPalette(tempPalette)
    
            menu = QMenu(self)
            copyAction = menu.addAction('复制')
            selectAction = menu.addAction('全选')
    
            res = menu.exec_(event.globalPos())
            self.setPalette(oldPalette)
    
            if res == copyAction:
                QApplication.clipboard().setText(self.selectedText())
            elif res == selectAction:
                self.setSelection(0, len(self.text()))
    

    That said, QLabel already provides the menu entries you're trying to replace. If you did that for localization purposes, then overriding the default menu behavior is just wrong, as the problem is elsewhere.