PDA

View Full Version : pyqt scrollarea not resized after dragndrop



freeaks
19th September 2015, 21:12
Hi there,
i'm having trouble figuring how to update my scrollarea to reflect added or modified contents in my application.
my program displays icons, i can dragndrop them.
if i resize the window to be bigger and dragndrop one icon to the bottom,
and then finally size back my window to it's original size,
the scrollarea does not allow me to scroll to the bottom to see my icon.
basicaly, once the app started, scrollarea dimension never change.
how can i make the scrollarea, upon dragndrop, to update to new size ?
it could be bigger like shown in the screenshot below,
or smaller if all my icons are grouped in upper left corner for example..
if the content fit in the window, i will not show the slider.

so basicaly, to reproduce the problem:
- take the code, run it, (all you need is two png icons)
- resize the window to be a lot longer (Y axis)
- dragndrop one of the icon far away (at least 300+ pixels away)
- then resize window back to original size
- then try to scroll to see the icon you dragndropped away.
- you will not be able. because scrollarea is too small.
- why? i mean i thought the layouts were there to communicate with widgets to transfer such info to them?


here's a screenshot showing the problem,
it's the same window, i just resize it, and dragndrop one icon at the bottom:

11384



#!/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.ScrollBarAlwa ysOn)
scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAl waysOff)
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_())

freeaks
19th September 2015, 23:49
i've found out:
the dropEvent() method of DragWidget() class needed to be
updated to get the dropped icon X and Y values and pass them to self.setMinimuSize()
then scrollArea would know about the new dimensions.



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

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


so if the icon new position is greater than
the minimumSize (minimumWidth and minimumHeight),
then add the offset to self.minimumSize