PySide:根据现有 UI 元素的位置在某个位置创建 window

PySide: Create window at a position based on the position of existing UI elements

我正在 Maya 中创建一个具有一些弹出窗口的工具。我希望弹出窗口出现在基于您单击的 UI 元素的设置位置。

当我 运行 脚本时,该工具出现在我的光标位置(这很好用)。然后,当您左键单击该按钮时,另一个 window 弹出(这不能正常工作)。

问题是弹出窗口 window 出现在我屏幕的左上角,而不是 QPushButton 的位置。我想如果我在我的 Popup_Window class 的 move_ui 方法中用 self.button_popup.pos() 替换 QtGui.QCursor.pos() 它会起作用......但它没有't.

有什么想法吗?这是我到目前为止在右侧评论的关键区域:

from PySide import QtCore, QtGui
from shiboken import wrapInstance 

def get_parent():
    ptr = mui.MQtUtil.mainWindow()
    return wrapInstance( long( ptr ), QtGui.QWidget )

############################################
class RightClickMenuButton(QtGui.QDialog):
    def __init__(self, parent = get_parent() ):
        super(RightClickMenuButton, self).__init__(parent)

        self.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)

        # Commands
        self.move_UI()
        self.create_gui()
        self.create_layout()
        self.create_connections()

    #-------------------------------------------
    def create_gui(self):
        self.button = QtGui.QPushButton()

    #-------------------------------------------
    def create_layout(self):
        layout = QtGui.QHBoxLayout()
        layout.addWidget(self.button)
        self.setLayout(layout)

    #-------------------------------------------
    def move_UI( self ):
        ''' Moves the UI to the cursor's position '''
        pos = QtGui.QCursor.pos()
        self.move(pos.x()+20, pos.y()+15)

    #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-
    def create_connections(self):
        # Left click
        self.button.clicked.connect( self.on_left_click )

        # Right click delete
        delete = QtGui.QAction(self)
        delete.setText("remove")
        delete.triggered.connect(self.remove_button)
        self.addAction(delete)

    #-----#-----#-----#-----#-----#-----#-----#-----#-----#-
    def remove_button(self):
        self.deleteLater()

    def on_left_click(self):
        self.popup = Popup_Window(self, self.button )      # Passing button in so I can get it's position
        self.popup.show()

############################################
class Popup_Window( QtGui.QDialog ):
    def __init__( self, mainUIWindow, button ):
        super( Popup_Window, self ).__init__()

        self.button_pos = button                           # Creating variable 
        self.mainUIWindow = mainUIWindow
        self.setAttribute( QtCore.Qt.WA_DeleteOnClose )

        # Commands
        self.move_UI()
        self.create_gui()
        self.create_layout()

    #-------------------------------------------
    def move_UI( self ):
        ''' Moves the UI to the cursor's position '''
        pos = self.button_pos.pos()                        # Using the button's position to determine window position
        self.move(pos.x()+20, pos.y()+15)

    #-------------------------------------------
    def create_gui( self ):
        ''' Visible GUI stuff '''
        self.push_btn = QtGui.QPushButton( "Create" )

    #-------------------------------------------
    def create_layout( self ):
        self.label = QtGui.QLabel( "Hey" )
        self.button_layout = QtGui.QHBoxLayout()
        self.button_layout.addWidget( self.push_btn )

############################################
if __name__ == '__main__':
    # Things to fix PySide Maya bug
    try:
        test_ui.close()
        test_ui.deleteLater()
    except:
        pass

    test_ui = RightClickMenuButton()
    test_ui.show()

    try:
        test_ui.show()
    except:
        test_ui.close()
        test_ui.deleteLater() 

问题是 widget.pos() 给你的小部件的相对位置(相对于 window)非常小,接近 (0,0),即左上角window space.

如果你想要一个小部件的全局屏幕位置,你必须写:

rel_pos = widget.pos()
pos = widget.mapToGlobal(rel_pos)

所以你在Popup_Windowclass中的move_UI函数变成:

def move_UI( self ):
        ''' Moves the UI to the widget position '''
        rel_pos = self.button_pos.pos()                        # Using the button's position to determine window position
        pos = self.button_pos.mapToGlobal(rel_pos)
        self.move(pos.x()+20, pos.y()+15)