Nils
3 years ago
2 changed files with 170 additions and 7 deletions
@ -0,0 +1,159 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
|
|||
############################################################################# |
|||
## |
|||
## Copyright (C) 2013 Riverbank Computing Limited. |
|||
## Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|||
## All rights reserved. |
|||
## |
|||
## This file is part of the examples of PyQt. |
|||
## |
|||
## $QT_BEGIN_LICENSE:BSD$ |
|||
## You may use this file under the terms of the BSD license as follows: |
|||
## |
|||
## "Redistribution and use in source and binary forms, with or without |
|||
## modification, are permitted provided that the following conditions are |
|||
## met: |
|||
## * Redistributions of source code must retain the above copyright |
|||
## notice, this list of conditions and the following disclaimer. |
|||
## * Redistributions in binary form must reproduce the above copyright |
|||
## notice, this list of conditions and the following disclaimer in |
|||
## the documentation and/or other materials provided with the |
|||
## distribution. |
|||
## * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor |
|||
## the names of its contributors may be used to endorse or promote |
|||
## products derived from this software without specific prior written |
|||
## permission. |
|||
## |
|||
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|||
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|||
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|||
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|||
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|||
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|||
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|||
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|||
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|||
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|||
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." |
|||
## $QT_END_LICENSE$ |
|||
## |
|||
############################################################################# |
|||
|
|||
|
|||
from PyQt5.QtCore import QPoint, QRect, QSize, Qt |
|||
from PyQt5.QtWidgets import (QApplication, QLayout, QPushButton, QSizePolicy, |
|||
QWidget) |
|||
|
|||
|
|||
class Window(QWidget): |
|||
def __init__(self): |
|||
super(Window, self).__init__() |
|||
|
|||
flowLayout = FlowLayout() |
|||
flowLayout.addWidget(QPushButton("Short")) |
|||
flowLayout.addWidget(QPushButton("Longer")) |
|||
flowLayout.addWidget(QPushButton("Different text")) |
|||
flowLayout.addWidget(QPushButton("More text")) |
|||
flowLayout.addWidget(QPushButton("Even longer button text")) |
|||
self.setLayout(flowLayout) |
|||
|
|||
self.setWindowTitle("Flow Layout") |
|||
|
|||
|
|||
class FlowLayout(QLayout): |
|||
def __init__(self, parent=None, margin=0, spacing=-1): |
|||
super(FlowLayout, self).__init__(parent) |
|||
|
|||
if parent is not None: |
|||
self.setContentsMargins(margin, margin, margin, margin) |
|||
|
|||
self.setSpacing(spacing) |
|||
|
|||
self.itemList = [] |
|||
|
|||
def __del__(self): |
|||
item = self.takeAt(0) |
|||
while item: |
|||
item = self.takeAt(0) |
|||
|
|||
def addItem(self, item): |
|||
self.itemList.append(item) |
|||
|
|||
def count(self): |
|||
return len(self.itemList) |
|||
|
|||
def itemAt(self, index): |
|||
if index >= 0 and index < len(self.itemList): |
|||
return self.itemList[index] |
|||
|
|||
return None |
|||
|
|||
def takeAt(self, index): |
|||
if index >= 0 and index < len(self.itemList): |
|||
return self.itemList.pop(index) |
|||
|
|||
return None |
|||
|
|||
def expandingDirections(self): |
|||
return Qt.Orientations(Qt.Orientation(0)) |
|||
|
|||
def hasHeightForWidth(self): |
|||
return True |
|||
|
|||
def heightForWidth(self, width): |
|||
height = self.doLayout(QRect(0, 0, width, 0), True) |
|||
return height |
|||
|
|||
def setGeometry(self, rect): |
|||
super(FlowLayout, self).setGeometry(rect) |
|||
self.doLayout(rect, False) |
|||
|
|||
def sizeHint(self): |
|||
return self.minimumSize() |
|||
|
|||
def minimumSize(self): |
|||
size = QSize() |
|||
|
|||
for item in self.itemList: |
|||
size = size.expandedTo(item.minimumSize()) |
|||
|
|||
margin, _, _, _ = self.getContentsMargins() |
|||
|
|||
size += QSize(2 * margin, 2 * margin) |
|||
return size |
|||
|
|||
def doLayout(self, rect, testOnly): |
|||
x = rect.x() |
|||
y = rect.y() |
|||
lineHeight = 0 |
|||
|
|||
for item in self.itemList: |
|||
wid = item.widget() |
|||
spaceX = self.spacing() + wid.style().layoutSpacing(QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Horizontal) |
|||
spaceY = self.spacing() + wid.style().layoutSpacing(QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Vertical) |
|||
nextX = x + item.sizeHint().width() + spaceX |
|||
if nextX - spaceX > rect.right() and lineHeight > 0: |
|||
x = rect.x() |
|||
y = y + lineHeight + spaceY |
|||
nextX = x + item.sizeHint().width() + spaceX |
|||
lineHeight = 0 |
|||
|
|||
if not testOnly: |
|||
item.setGeometry(QRect(QPoint(x, y), item.sizeHint())) |
|||
|
|||
x = nextX |
|||
lineHeight = max(lineHeight, item.sizeHint().height()) |
|||
|
|||
return y + lineHeight - rect.y() |
|||
|
|||
|
|||
if __name__ == '__main__': |
|||
|
|||
import sys |
|||
|
|||
app = QApplication(sys.argv) |
|||
mainWin = Window() |
|||
mainWin.show() |
|||
sys.exit(app.exec_()) |
Loading…
Reference in new issue