【问题标题】:pyqt scrollarea not resized after dragndroppyqt滚动区域在拖放后未调整大小
【发布时间】:2015-09-20 06:22:29
【问题描述】:

短版:
- 获取代码,运行它,(您只需要两个 png 图标)
- 将窗口大小调整为更大
- 将其中一个图标拖放到远处(至少 300+ 像素)
- 然后将窗口大小调整回原始大小
- 然后尝试滚动查看您拖放的图标。
- 你将无法。因为滚动区域太小了。
- 为什么?

长版:
我无法确定如何更新滚动区域以反映应用程序中添加或修改的内容。
我正在显示图标,我可以拖放它们。
如果我让窗口变大,将一个图标拖放到底部,
然后缩小我的窗口,
滚动区域不允许我滚动到底部以查看我的图标。
基本上,一旦应用启动,滚动区域的尺寸就不会改变。
如何使滚动区域在拖放后更新为新大小?
它可能会更大,如下面的屏幕截图所示,
例如,如果我的所有图标都在左上角分组,则更小..
如果内容适合窗口,我不会显示滑块。

这是显示问题的屏幕截图,
这是同一个窗口,我只是调整它的大小,然后在底部拖放一个图标:

(scrollarea 没有更新,所以我无法向下滚动到我放在底部的图标)


这是到目前为止的代码:

#!/usr/bin/python3

from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sys


class DragWidget(QFrame):

    def __init__(self, parent=None):
        super(DragWidget, self).__init__(parent)

        self.setMinimumSize(200, 200)
        self.setAcceptDrops(True)

        test_icon1 = QLabel(self)
        test_icon1.setPixmap(QPixmap('./images/closeicon.png'))
        test_icon1.move(20, 20)
        test_icon1.show()
        test_icon1.setAttribute(Qt.WA_DeleteOnClose)

        test_icon2 = QLabel(self)
        test_icon2.setPixmap(QPixmap('./images/openicon.png'))
        test_icon2.move(60, 20)
        test_icon2.show()
        test_icon2.setAttribute(Qt.WA_DeleteOnClose)

    def dragEnterEvent(self, event):
        if event.mimeData().hasFormat('application/x-dnditemdata'):
            if event.source() == self:
                event.setDropAction(Qt.MoveAction)
                event.accept()
            else:
                event.acceptProposedAction()
        else:
            event.ignore()

    dragMoveEvent = dragEnterEvent

    def dropEvent(self, event):
        if event.mimeData().hasFormat('application/x-dnditemdata'):
            itemData = event.mimeData().data('application/x-dnditemdata')
            dataStream = QDataStream(itemData, QIODevice.ReadOnly)

            pixmap = QPixmap()
            offset = QPoint()
            dataStream >> pixmap >> offset

            newIcon = QLabel(self)
            newIcon.setPixmap(pixmap)
            newIcon.move(event.pos() - offset)
            newIcon.show()
            newIcon.setAttribute(Qt.WA_DeleteOnClose)

            if event.source() == self:
                event.setDropAction(Qt.MoveAction)
                event.accept()
            else:
                event.acceptProposedAction()
        else:
            event.ignore()

    def mousePressEvent(self, event):
        child = self.childAt(event.pos())
        if not child:
            return

        pixmap = QPixmap(child.pixmap())

        itemData = QByteArray()
        dataStream = QDataStream(itemData, QIODevice.WriteOnly)
        dataStream << pixmap << QPoint(event.pos() - child.pos())

        mimeData = QMimeData()
        mimeData.setData('application/x-dnditemdata', itemData)

        drag = QDrag(self)
        drag.setMimeData(mimeData)
        drag.setPixmap(pixmap)
        drag.setHotSpot(event.pos() - child.pos())

        tempPixmap = QPixmap(pixmap)
        painter = QPainter()
        painter.begin(tempPixmap)
        painter.fillRect(pixmap.rect(), QColor(127, 127, 127, 127))
        painter.end()

        child.setPixmap(tempPixmap)
        if drag.exec_(Qt.CopyAction | Qt.MoveAction) == Qt.MoveAction:
            child.close()
        else:
            child.show()
            child.setPixmap(pixmap)


class Window(QWidget):

    def __init__(self, parent=None):
        super(Window, self).__init__()

        widget = QWidget()
        palette = QPalette()
        palette.setBrush(QPalette.Background, QBrush(QPixmap("images/pattern.png")))
        widget.setPalette(palette)
        layout = QVBoxLayout(self)
        layout.addWidget(DragWidget())
        widget.setLayout(layout)
        scroll = QScrollArea()
        scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        scroll.setWidgetResizable(True)
        scroll.setWidget(widget)
        vlayout = QVBoxLayout(self)
        vlayout.setContentsMargins(0, 0, 0, 0)
        vlayout.setSpacing(0)
        vlayout.addWidget(scroll)
        self.setLayout(vlayout)
        self.show()

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

【问题讨论】:

    标签: pyqt qscrollarea


    【解决方案1】:

    原来,我需要修改 dropEvent 方法,
    获取放置图标的 X 和 Y 并将这些值用于 setMinimumSize()。
    像这样:

    #!/usr/bin/python3
    
    from PyQt5.QtGui import *
    from PyQt5.QtCore import *
    from PyQt5.QtWidgets import *
    import sys
    
    
    class DragWidget(QFrame):
    
        def __init__(self, parent=None):
            super(DragWidget, self).__init__(parent)
    
            self.setMinimumSize(200, 200)
            self.setAcceptDrops(True)
    
            self.test_icon1 = QLabel(self)
            self.test_icon1.setPixmap(QPixmap('./images/closeicon.png'))
            self.test_icon1.move(20, 20)
            self.test_icon1.show()
            self.test_icon1.setAttribute(Qt.WA_DeleteOnClose)
    
            self.test_icon2 = QLabel(self)
            self.test_icon2.setPixmap(QPixmap('./images/openicon.png'))
            self.test_icon2.move(60, 20)
            self.test_icon2.show()
            self.test_icon2.setAttribute(Qt.WA_DeleteOnClose)
    
        def dragEnterEvent(self, event):
            if event.mimeData().hasFormat('application/x-dnditemdata'):
                if event.source() == self:
                    event.setDropAction(Qt.MoveAction)
                    event.accept()
                else:
                    event.acceptProposedAction()
            else:
                event.ignore()
    
        dragMoveEvent = dragEnterEvent
    
        def dropEvent(self, event):
            if event.mimeData().hasFormat('application/x-dnditemdata'):
                itemData = event.mimeData().data('application/x-dnditemdata')
                dataStream = QDataStream(itemData, QIODevice.ReadOnly)
    
                pixmap = QPixmap()
                offset = QPoint()
                dataStream >> pixmap >> offset
    
                newIcon = QLabel(self)
                newIcon.setPixmap(pixmap)
                newIcon.move(event.pos() - offset)
                newIcon.show()
                newIcon.setAttribute(Qt.WA_DeleteOnClose)
    
                if newIcon.y()+32 > self.minimumHeight():
                    self.setMinimumHeight(newIcon.y()+32)
    
                if newIcon.x()+32 > self.minimumWidth():
                    self.setMinimumWidth(newIcon.x()+32)
    
                if event.source() == self:
                    event.setDropAction(Qt.MoveAction)
                    event.accept()
                else:
                    event.acceptProposedAction()
            else:
                event.ignore()
    
        def mousePressEvent(self, event):
            child = self.childAt(event.pos())
            if not child:
                return
    
            pixmap = QPixmap(child.pixmap())
    
            itemData = QByteArray()
            dataStream = QDataStream(itemData, QIODevice.WriteOnly)
            dataStream << pixmap << QPoint(event.pos() - child.pos())
    
            mimeData = QMimeData()
            mimeData.setData('application/x-dnditemdata', itemData)
    
            drag = QDrag(self)
            drag.setMimeData(mimeData)
            drag.setPixmap(pixmap)
            drag.setHotSpot(event.pos() - child.pos())
    
            tempPixmap = QPixmap(pixmap)
            painter = QPainter()
            painter.begin(tempPixmap)
            painter.fillRect(pixmap.rect(), QColor(127, 127, 127, 127))
            painter.end()
    
            child.setPixmap(tempPixmap)
            if drag.exec_(Qt.CopyAction | Qt.MoveAction) == Qt.MoveAction:
                child.close()
            else:
                child.show()
                child.setPixmap(pixmap)
    
    
    class Window(QWidget):
    
        def __init__(self, parent=None):
            super(Window, self).__init__()
            self.pattern = "images/pattern.png"
            self.widget = QWidget()
            self.palette = QPalette()
            self.palette.setBrush(QPalette.Background, QBrush(QPixmap(self.pattern)))
            self.widget.setPalette(self.palette)
            layout = QVBoxLayout(self)
            layout.addWidget(DragWidget())
            self.widget.setLayout(layout)
            scroll = QScrollArea()
            scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
            scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
            scroll.setWidgetResizable(True)
            scroll.setWidget(self.widget)
            vlayout = QVBoxLayout(self)
            vlayout.setContentsMargins(0, 0, 0, 0)
            vlayout.setSpacing(0)
            vlayout.addWidget(scroll)
            self.setLayout(vlayout)
            self.show()
    
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        window = Window('./')
        window2 = Window('./')
        sys.exit(app.exec_())
    

    注意 DragWidget() 类的 dropEvent() 方法。

        if newIcon.y()+32 > self.minimumHeight():
            self.setMinimumHeight(newIcon.y()+32)
    
        if newIcon.x()+32 > self.minimumWidth():
            self.setMinimumWidth(newIcon.x()+32)
    

    所以如果图标新位置大于
    minimumSize(最小宽度和最小高度),
    然后将偏移量添加到 self.minimumSize

    感谢来自#pyqt 频道的Avaris 的帮助:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-26
      • 1970-01-01
      • 2014-05-09
      • 1970-01-01
      • 1970-01-01
      • 2019-08-13
      • 2016-09-08
      • 1970-01-01
      相关资源
      最近更新 更多