PySide:根据按钮的位置和 window 的边缘创建弹出窗口

PySide: Create popup based on location of button and window's edge

我想在单击按钮的位置创建一个弹出窗口,并沿现有 window.

的左边缘偏移该弹出窗口

现在我可以很好地确定按钮的位置,但 window 的位置似乎有点偏离,因为在创建弹出窗口时它向左偏移了大约 200 像素。我在我的代码中评论了下面的相关部分。感谢任何 help/critiques.

from PySide import QtCore, QtGui
from shiboken import wrapInstance 

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

############################################
class Tool_Window(QtGui.QDialog):
    def __init__(self, parent = get_parent() ):
        super(Tool_Window, 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.button1 = QtGui.QPushButton()
        self.button1.setMaximumWidth(50)
        self.button2 = QtGui.QPushButton()
        self.button2.setMaximumWidth(50)
        self.button3 = QtGui.QPushButton()
        self.button3.setMaximumWidth(50)

    #-------------------------------------------
    def create_layout(self):
        layout = QtGui.QVBoxLayout()
        layout.addWidget(self.button1)
        layout.addWidget(self.button2)
        layout.addWidget(self.button3)
        layout.addStretch()
        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.button1.clicked.connect( self.on_left_click1 )
        self.button2.clicked.connect( self.on_left_click2 )
        self.button3.clicked.connect( self.on_left_click3 )

        # 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_click1(self):
        self.popup = Popup_Window(self, self.button1 )                    # Passing button in so I can get it's position
        self.popup.show()

    def on_left_click2(self):
        self.popup = Popup_Window(self, self.button2 )      
        self.popup.show()

    def on_left_click3(self):
        self.popup = Popup_Window(self, self.button3 )      
        self.popup.show()

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

        self.button_pos = button                                           # Creating variable for the button
        self.toolWindow= mainUIWindow
        self.setAttribute( QtCore.Qt.WA_DeleteOnClose )
        #self.setMinimumWidth(100)                                         # I need a minimum width

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

    #-------------------------------------------
    def move_UI( self ):                                                    # Move popup based on pos of window and buttons
        ''' Moves the UI to the cursor's position '''
        self.setWindowFlags(QtCore.Qt.Popup)                               
        self.line_edit.setFocus()

        # Get button position                                          
        btn_global_point = self.button_pos.mapToGlobal(self.button_pos.rect().topLeft())  

        # Get window position  
        win_global_point = self.mapToGlobal(self.rect().topLeft()) 

        self.move(btn_global_point - win_global_point)                      # Here is where I find the distance between the window edge and button edge 


    #-------------------------------------------
    def create_gui( self ):
        ''' Visible GUI stuff '''
        self.my_label = QtGui.QLabel("default text")
        self.line_edit = QtGui.QLineEdit()
        self.line_edit.setMaxLength( 30 )
        self.push_btn = QtGui.QPushButton( "Hey" )
        self.push_btn.setMaximumWidth( 30 )

    #-------------------------------------------
    def create_layout( self ):
        self.button_layout = QtGui.QVBoxLayout()
        self.button_layout.addWidget( self.my_label )
        self.button_layout.addWidget( self.line_edit )
        self.button_layout.addWidget( self.push_btn )
        self.setLayout(self.button_layout)

    #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
    def create_connections( self ):
        self.line_edit.textChanged.connect( self.on_text_changed )

    #-----#-----#-----#-----#-----#-----#-----#-----#-----#
    def on_text_changed( self ):
        typed_name = self.line_edit.text()
        self.my_label.setText(typed_name)


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

    test_ui = Tool_Window()
    test_ui.show()

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

解法:

# Get button position                                          
btn_global_point = self.button_pos.mapToGlobal(self.button_pos.rect().topLeft())  

# Get window position  
win_global_point = self.toolWindow.mapToGlobal(self.rect().topLeft()) 

self.move(win_global_point.x(), btn_global_point.y())

如果我明白你想要达到什么目的,你只需要保留按钮位置的 y 值x 值 的 window 个位置。

所以试试这个代码:

    # Get y button position                                          
    btn_global_point_y = self.button_pos.mapToGlobal(self.button_pos.rect().topLeft()).y()  

    # Get window position  
    win_global_point_x = self.mapToGlobal(self.rect().topLeft()).x() 

    self.move(win_global_point_x, btn_global_point_y)   

使用此行,您可以将弹出窗口 window 移动到按钮的高度并将其对齐到 window 的左边缘。