PySide:改变窗口的调整大小/增长方向

时间:2015-07-25 18:18:14

标签: popup resize pyside direction

我在窗口的边缘创建了弹出窗口,我希望它在用户键入文本字段时展开弹出窗口。这当前有效,但窗口向右扩展。相反,我希望弹出窗口向左扩展(并保持右边缘固定到位)。

我最接近的例子就是下面的工作。在其中,我将获得每个文本输入的弹出窗口大小,然后根据其新大小移动弹出窗口。我觉得这应该有效,但事实并非如此。

在第一个文本输入上,弹出窗口跳转到屏幕的左边缘(仅限x转换)。在第二个文本输入上,弹出窗口跳回其原始位置。在第三个文本输入上,弹出窗口跳回屏幕的左边缘。在第四个输入......你明白了。我还想提一下,窗口的整体增长看起来像是从弹出窗口的中心而不是从右边缘开始增长。

我注意到点击按钮后它会一直突出显示,直到我的鼠标经过它。这会导致这个问题吗?

实现这种效果的任何想法或更好的方法都会很棒,谢谢!

from PySide import QtCore, QtGui
import maya.OpenMayaUI as mui
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)

        # 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)
        blank_layout = QtGui.QVBoxLayout()
        main_layout = QtGui.QHBoxLayout( self )
        main_layout.addLayout(blank_layout)
        main_layout.addLayout(layout)
        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.__popup_filter = ClosePopupFilter()
        self.installEventFilter(self.__popup_filter) 
        self.setWindowFlags(QtCore.Qt.Popup)
        '''
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint |
                            QtCore.Qt.WindowStaysOnTopHint |
                            QtCore.Qt.CustomizeWindowHint |
                            QtCore.Qt.Tool)    
        '''
        self.button_pos = button       
        self.toolWindow = toolWindow                                        
        self.setAttribute( QtCore.Qt.WA_DeleteOnClose )
        self.resize(100, 100) 

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

    #-------------------------------------------
    def move_UI( self ):                                                        # Method that I use to place the popup window initially  
        self.line_edit.setFocus() 
        # Get button position                                          
        self.btn_global_point = self.button_pos.mapToGlobal(self.button_pos.rect().topLeft())  
        print self.btn_global_point
        # Get window position  
        self.win_global_point = self.toolWindow.mapToGlobal(self.rect().topLeft()) 
        print self.win_global_point
        # Get popup Size
        self.popup_size = self.mapToGlobal(self.rect().topRight())
        print self.popup_size
        # Move the window
        self.move((self.win_global_point.x()-self.popup_size.x()), self.btn_global_point.y())

    #-------------------------------------------
    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.button_layout.setContentsMargins(0, 0, 0, 0)
        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) 
        self.move_UI()                                                          # I reuse the move method to move the ui on text edit

############################################
class  ClosePopupFilter(QtCore.QObject):
    ''' Close popup window '''
    def  eventFilter(self, target, event):
        if event.type() == QtCore.QEvent.WindowDeactivate:
            target.close()
        return  False



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()

1 个答案:

答案 0 :(得分:1)

我已经修改了你在OP中提供的一些代码,并试图整理一个解决你的特定问题的例子。

我对代码所做的一些修改:

  • 触发move_UI; {/ li>的resizeEvent内的Popup_Window
  • 更正了move_UI中的方法Popup_Window,以便弹出窗口不会闪烁到一个位置到另一个位置;
  • 直接在eventFilter;
  • 中移动Popup_Window
  • 合并处理Tool_Window中的button.clicked.connect事件的函数。

解决方案并不完美,当它在Ubuntu中扩展和移动时,弹出窗口仍然有一点“闪烁”。然而,这在Windows7中并不十分明显。如果我想到另一种解决方案,我会做更新。

from PySide import QtCore, QtGui
import sys

class Tool_Window(QtGui.QDialog): #=============================================
    def __init__(self, parent=None): 
        super(Tool_Window, self).__init__(parent)

        self.create_gui()
        self.create_layout()
        self.create_connections()

    def create_gui(self): #=====================================================

        self.button1 = QtGui.QPushButton('Button 1')
        self.button2 = QtGui.QPushButton('Button 2')
        self.button3 = QtGui.QPushButton('Button 3')

    def create_layout(self): #==================================================

        layout = QtGui.QVBoxLayout()
        layout.addWidget(self.button1)
        layout.addWidget(self.button2)
        layout.addWidget(self.button3)
        self.setLayout(layout)

    def create_connections(self): #=============================================

        self.button1.clicked.connect(self.on_lef_click )
        self.button2.clicked.connect(self.on_lef_click )
        self.button3.clicked.connect(self.on_lef_click )

    def on_lef_click(self): #===================================================

        button = self.sender()

        self.popup = Popup_Window(self, button)
        self.popup.show()


class Popup_Window( QtGui.QWidget ): #==========================================
    def __init__( self, parent, button):
        super(Popup_Window, self ).__init__(parent)

        self.setWindowFlags(QtCore.Qt.Popup)

        self.button = button       
        self.parent = parent

        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)

        #---- set layout key dimension ----

        self.min_width = 100
        self.frame_thick = 10
        self.setFixedWidth(self.min_width)

        #---- init GUI ----

        self.installEventFilter(self)

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

        self.line_edit.setFocus()


    def create_gui( self ): #===================================================

        self.my_label = QtGui.QLabel("default text")
        self.my_label.setAlignment(QtCore.Qt.AlignRight)
        self.line_edit = QtGui.QLineEdit()
        self.line_edit.setAlignment(QtCore.Qt.AlignRight)
        self.line_edit.setMaxLength( 50 )


    def create_layout( self ): #================================================

        button_layout = QtGui.QGridLayout()

        button_layout.addWidget(self.my_label, 0, 0)
        button_layout.addWidget(self.line_edit, 1, 0)

        button_layout.setContentsMargins(self.frame_thick, self.frame_thick,
                                         self.frame_thick, self.frame_thick)

        self.setLayout(button_layout)


    def create_connections(self): #=============================================
        self.line_edit.textChanged.connect(self.line_edit_text_changed)


    def line_edit_text_changed(self, text):  #==================================

        #---- set the text in label ----

        self.my_label.setText(text)

        #---- determine new width of popup ----

        fm = self.line_edit.fontMetrics()
        txtWidth = fm.boundingRect(text).width() + 10 # Padding to the left.
                                                      # Value is arbitrary.

        newWidth = max(txtWidth + self.frame_thick * 2, self.min_width)

        self.setFixedWidth(newWidth)


    def eventFilter(self, source, event): #=====================================

        if event.type() == QtCore.QEvent.WindowDeactivate:
            self.close()

        return QtGui.QWidget.eventFilter(self, source, event)

    def resizeEvent(self, event): #=============================================

        self.move_UI()        
        QtGui.QWidget.resizeEvent(self, event)


    def move_UI(self): # =======================================================

        y_btn = self.button.mapToGlobal(QtCore.QPoint(0, 0)).y()        
        x_win = self.parent.mapToGlobal(QtCore.QPoint(0, 0)).x()

        w_pop = self.frameGeometry().width()

        x = x_win - w_pop - 12 # 12 is an arbitrary value.
        y = y_btn

        self.move(QtCore.QPoint(x, y))


if __name__ == '__main__':

    app = QtGui.QApplication(sys.argv)
    instance_1 = Tool_Window()
    instance_1.show()
    sys.exit(app.exec_())

这导致:

enter image description here

更新(2015-07-30):弹出窗口缩小到内容的宽度

我已经扩展了示例,现在弹出窗口以最小值100开始,当文本宽度超过此值时会延伸。此外,如果删除文本,弹出窗口的宽度将缩小,最小值为100。

这是通过计算QLineEdit中内容更改时的文本宽度并使用该值为方法line_edit_text_changed中的弹出窗口指定固定宽度来完成的。