5

他一直困扰着我,主要是因为移动小部件和诸如此类的方法组合有多少。本质上,我有一个简单的小部件,我希望能够在我的应用程序的特定区域弹出。问题是我似乎永远无法让它在我想要的地方弹出。此外,我想以一种方式设置它,我可以根据它是否弹出以指向应用程序左上角的小部件而不是底部的小部件来调整它的“指针”侧 -正确的。

理想情况下,我可以将弹出窗口放置在几乎靠近父小部件边缘的位置,并根据它的位置锚定它。这是我一直在尝试的。

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys

class popup(QWidget):
    def __init__(self, parent = None, widget=None):    
        QWidget.__init__(self, parent)
        layout = QGridLayout(self)
        button = QPushButton("Very Interesting Text Popup. Here's an arrow   ^")
        layout.addWidget(button)
        self.move(widget.rect().bottomLeft())

class Window(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        self.button = QPushButton('Hit this button to show a popup', self)
        self.button.clicked.connect(self.handleOpenDialog)
        self.button.move(250, 50)
        self.resize(600, 200)

    def handleOpenDialog(self):
        self.popup = popup(self, self.button)
        self.popup.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = Window()
    win.show()
    sys.exit(app.exec_())

此代码生成一个随机位于小部件中间的按钮。在这个例子中,我想要得到的是在右上角显示其“枢轴”的按钮下方的弹出窗口,这样弹出按钮中的箭头将指向小部件的右下角。然而,它却在窗口的左上角弹出。在我玩弄 .move、.setGeometry 和玩 QRect 的过程中,我终其一生都无法弄清楚这一点。对能伸出援手的人表示极大的敬意。谢谢!

4

2 回答 2

3

我知道这很旧,但我最近正在寻找这个,这是最好的答案;我有一个有用的补充(对于其他搜索这个食谱的人!)

我将它实现为一个 mixin,我认为它为您的对话框提供了更大的灵活性:

class PopupDialogMixin(object):  # will not work (with PySide at least) unless implemented as 'new style' class. I.e inherit from object
    def makePopup(callWidget):
        """
        Turns the dialog into a popup dialog.
        callWidget is the widget responsible for calling the dialog (e.g. a toolbar button)
        """
        self.setContentsMargins(0,0,0,0)
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.Popup)
        self.setObjectName('ImportDialog')

        # Move the dialog to the widget that called it
        point = callWidget.rect().bottomRight()
        global_point = callWidget.mapToGlobal(point)
        self.move(global_point - QtCore.QPoint(self.width(), 0))

然后,您的自定义对话框将继承自QtCore.QDialogPopupDialogMixin。这使您可以选择以“正常”方式使用对话框或使其成为弹出对话框。例如:

dlg = MyDialog(self)
dlg.makePopup(self.myButton)

我认为将它作为一个 mixin 来实现有很多好处:

  • 无需为您想要作为弹出窗口的每个自定义对话框编写“弹出”代码
  • 保留对话框的“默认”行为 - 例如,如果您想在其他地方重用它作为“常规”对话框,您只需像往常一样使用它
  • 无需将任何额外的东西传递__init__parent.
于 2014-07-25T10:12:10.047 回答
1

给你 - 评论有点解释它背后的逻辑 - 因为问题是一个例子和关于定位,我保持其余代码相同除了弹出类,但只是提到它是一个令人讨厌的 - 你不应该导入 * (永远),但尤其是像 PyQt4.QtCore/QtGui 这样大的东西......

    from PyQt4.QtCore import *
    from PyQt4.QtGui import *
    import sys

    class popup(QWidget):
        def __init__(self, parent = None, widget=None):    
            QWidget.__init__(self, parent)
            layout = QGridLayout(self)
            button = QPushButton("Very Interesting Text Popup. Here's an arrow   ^")
            layout.addWidget(button)

            # adjust the margins or you will get an invisible, unintended border
            layout.setContentsMargins(0, 0, 0, 0)

            # need to set the layout
            self.setLayout(layout)
            self.adjustSize()

            # tag this widget as a popup
            self.setWindowFlags(Qt.Popup)

            # calculate the botoom right point from the parents rectangle
            point        = widget.rect().bottomRight()

            # map that point as a global position
            global_point = widget.mapToGlobal(point)

            # by default, a widget will be placed from its top-left corner, so
            # we need to move it to the left based on the widgets width
            self.move(global_point - QPoint(self.width(), 0))

    class Window(QWidget):
        def __init__(self):
            QWidget.__init__(self)
            self.button = QPushButton('Hit this button to show a popup', self)
            self.button.clicked.connect(self.handleOpenDialog)
            self.button.move(250, 50)
            self.resize(600, 200)

        def handleOpenDialog(self):
            self.popup = popup(self, self.button)
            self.popup.show()

    if __name__ == '__main__':
        app = QApplication(sys.argv)
        win = Window()
        win.show()
        sys.exit(app.exec_())
于 2012-08-20T18:07:50.353 回答