Search code examples
pythonqtpyqtpysidemaya

PySide QPushButton Right-click context menu not assigning per button


I've got a loop generating QPushButtons with context menus, and populating a sub-menu with different values based on text found in an image within a directory (That last part not important)

for self.preview in previewFiles:

self.image = self.dir_path+"/"+self.preview
self.btn = QPushButton()
self.btn.setContextMenuPolicy(Qt.CustomContextMenu)
self.btn.customContextMenuRequested.connect(self.on_context_menu)
self.btn.setMinimumSize(360, 360)
self.btn.setMaximumSize(360, 360)
self.btn.setStyleSheet("background-image: url(" + self.image + ");border:1px solid #333;text-align: bottom center;font: bold 12px;")
#popup menu
self.popMenu = QMenu(self)

# Resolution Drop down
res = QMenu("Resolution")
for reso in albedoRes: # Add resolutions to sub menu based on image res found
    if "256" in reso:
        res.addAction(QAction('256', self, checkable=True))
    if "512" in reso:
        res.addAction(QAction('512', self, checkable=True))
    if "1K" in reso:
        res.addAction(QAction('1024', self, checkable=True))
    if "2K" in reso:
        res.addAction(QAction('2048', self, checkable=True))
    if "4K" in reso:
        res.addAction(QAction('4096', self, checkable=True))
    if "8K" in reso:
        res.addAction(QAction('8192', self, checkable=True))
self.popMenu.addMenu(res)
self.popMenu.addSeparator().setText("Alternate Shaders")
self.popMenu.addAction(QAction('Blinn', self))
self.popMenu.addAction(QAction('Phong', self))
self.popMenu.addSeparator()
self.popMenu.addAction(QAction('Open file(s) location', self))
#self.btn.setMenu(self.popMenu)
self.a_widget.setLayout(self.a_layout)
self.a_layout.addWidget(self.btn) # add rows to main layout

As you can see this should add an action to the menu if it finds a certain string in a file name - and it does

However this isn't saving per-button, instead is just replacing the QAction based on the next image filenames (So realistically the final QActions being shown is just that of the last image in the loop)

Using setMenu() assigns everything correctly, but I'm wanting it within a context menu instead.

I know it's probably something easy that I'm missing, but I'm pretty stumped, any guidance would be appreciated. Thanks.


Solution

  • build your menu by button instead in another function :

    import PyQt4.QtCore as QtCore
    import PyQt4.QtGui as QtGui
    
    class test(QtGui.QDialog):
    
        def __init__(self):
    
            super(test, self).__init__()
            self.setObjectName("test")
            self.resize(574, 203)
            self.setWindowTitle("Clone UI")
    
            self.a_layout = QtGui.QHBoxLayout()
    
            previewFiles = ['blood-lips-lipstick-makeup-red-lips-Favim.com-75480.jpg', 'mins.jpg']
    
            # ABOVE CODE WAS PLACEHOLDER
    
            for preview in previewFiles:
    
                self.image = '/x/path' + preview
                self.btn = QtGui.QPushButton()
                self.btn._name = preview.split('.')[0] # use for my if/else condition menu
    
    
                # create the ocntext
                self.btn.installEventFilter(self)
                self.btn.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
                self.btn.customContextMenuRequested.connect(self.btnClicked)
    
                self.btn.setMinimumSize(360, 360)
                self.btn.setMaximumSize(360, 360)
                self.btn.setStyleSheet("background-image: url(" + self.image + ");border:1px solid #333;text-align: bottom center;font: bold 12px;")
    
                #popup menu
                self.popMenu = QtGui.QMenu(self)
    
                #self.btn.setMenu(self.popMenu)
                self.setLayout(self.a_layout)
                self.a_layout.addWidget(self.btn) # add rows to main layout
    
        def btnClicked(self, QPos):
    
            # the function that create the popup menu
    
            # get the button clicked
            btn = self.sender()
    
            # define where the menu appear on click
            parentPosition = btn.mapToGlobal(QtCore.QPoint(0, 0))
            menuPosition = parentPosition + QPos
    
            #clear the menu at each click to customize
            self.popMenu.clear()
    
            #populate
            self.populateBtnContext(btn._name)
    
            #show
            self.popMenu.move(menuPosition)
            self.popMenu.show()
    
        def populateBtnContext(self, name):
    
            # Do some if here :
            if name == "mins":
                self.popMenu.addAction(QtGui.QAction('256', self, checkable=True))
                self.popMenu.addAction(QtGui.QAction('512', self, checkable=True))
                self.popMenu.addAction(QtGui.QAction('1024', self, checkable=True))
            else:
                self.popMenu.addAction(QtGui.QAction('2048', self, checkable=True))
                self.popMenu.addAction(QtGui.QAction('4096', self, checkable=True))
                self.popMenu.addAction(QtGui.QAction('8192', self, checkable=True))  
    
            self.popMenu.addSeparator().setText("Alternate Shaders")
            self.popMenu.addAction(QtGui.QAction('Blinn', self))
            self.popMenu.addAction(QtGui.QAction('Phong', self))
            self.popMenu.addSeparator()
            self.popMenu.addAction(QtGui.QAction('Open file(s) location', self))
    
    win = test()
    win.show()