使用python和PyQt创建可滚动列表

时间:2012-07-15 16:07:45

标签: python-3.x pyqt4

我的应用程序里面有一个带QWidget(content_widget)的QScrollArea。我想在应用程序运行时用图像填充它。如果图像数量超过可以在不滚动的情况下显示的数量,我想要滚动行为。我走到这一步:

children_occupied_width = self.ui.content_widget.childrenRect().width()

image_view = QtGui.QGraphicsView(self.ui.content_widget)
image_view.setGeometry(QtCore.QRect( children_occupied_width, 0, 210, 210 ))
image_view.setObjectName("New Image")

placeholder_image = QtGui.QGraphicsScene()
placeholder_image.addPixmap(QtGui.QPixmap('placeholder.png'))
image_view.setScene(placeholder_image)

image_view.show()

虽然图像显示在右侧位置的列表中,但如果图像开始放在可见区域之外,则不会滚动。即使使用

,content_widget的大小似乎也不会改变
self.ui.content_widget.resize(...)

self.ui.content_widget.adjustSize()

如何让它成长/调整大小?

2 个答案:

答案 0 :(得分:1)

第一部分结果证明不是你真正需要的。我将其留作信息用途,但请参阅底部的更新

问题是QGraphicsView本身就是一种滚动小部件,代表它正在查看的场景的一部分。理想情况下,您只需使用视图并使用自己的滚动条。

但是如果您特别需要将视图的内容大小转发到普通的QWidget滚动,那么您需要做的是让QGraphicsView在场景内容发生变化时始终自行调整大小。 QScrollArea仅响应其设置的窗口小部件的大小更改。视图需要改变大小。过程将是视图需要侦听来自场景的信号以添加或移除项目,然后调整自身大小以完全包围所有这些子项。

以下是QGraphicsView小部件本身如何完全能够用作滚动功能的示例:

from PyQt4 import QtCore, QtGui

app = QtGui.QApplication([])
scene = QtGui.QGraphicsScene()
view = QtGui.QGraphicsView()
view.setScene(scene)

view.resize(600,300)

pix = QtGui.QPixmap("image.png")

w,h = pix.width(), pix.height()
x = y = 0
pad = 5
col = 3

for i in xrange(1,20):
    item = scene.addPixmap(pix)
    item.setPos(x,y)

    if i % col == 0:
        x = 0
        y += h+pad
    else:
        x+=w+pad

view.show()
view.raise_()
app.exec_()

您可以看到,当图像溢出当前视图大小时,您会看到滚动条 如果你真的需要一些父滚动区域作为视图的滚动(出于我不太了解的原因),那么这里有一个更复杂的例子,显示你需要在场景中观察某些事件然后不断更新视图的大小以强制父滚动区上的滚动条。我选择在场景中观察一下它的矩形变化(添加更多孩子)的信号

from PyQt4 import QtCore, QtGui

app = QtGui.QApplication([])

win = QtGui.QDialog()
win.resize(600,300)
layout = QtGui.QVBoxLayout(win)
scroll = QtGui.QScrollArea()
scroll.setWidgetResizable(True)
layout.addWidget(scroll)

view = QtGui.QGraphicsView(scroll)
view.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
view.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
scene = QtGui.QGraphicsScene(scroll)
view.setScene(scene)

scroll.setWidget(view)

pix = QtGui.QPixmap("image.png")

w,h = pix.width(), pix.height()
x = y = i = 0
pad = 5
col = 3

def createImage():
    global x,y,i
    item = scene.addPixmap(pix)
    item.setPos(x,y)

    i+=1
    if i % col == 0:
        x = 0
        y += h+pad
    else:
        x+=w+pad

def changed():
    size = scene.itemsBoundingRect().size()
    view.setMinimumSize(size.width()+pad, size.height()+pad)

scene.changed.connect(changed)

t = QtCore.QTimer(win)
t.timeout.connect(createImage)
t.start(500)

win.show()
win.raise_()
app.exec_()

滚动区域始终会查看已设置为子项的窗口小部件的大小。视图必须调整大小。

<强>更新

从您的评论中可以看出,您并不需要将QGraphics对象用于此方法。它只会让你的任务变得更复杂。只需使用垂直布局并添加QLabel小部件即可:

from PyQt4 import QtCore, QtGui

app = QtGui.QApplication([])

win = QtGui.QDialog()
win.resize(300,300)
layout = QtGui.QVBoxLayout(win)
scroll = QtGui.QScrollArea()
scroll.setWidgetResizable(True)
layout.addWidget(scroll)

scrollContents = QtGui.QWidget()
layout = QtGui.QVBoxLayout(scrollContents)
scroll.setWidget(scrollContents)

pix = QtGui.QPixmap("image.png")

def createImage():
    label = QtGui.QLabel()
    label.setPixmap(pix)
    layout.addWidget(label)

t = QtCore.QTimer(win)
t.timeout.connect(createImage)
t.start(500)

win.show()
win.raise_()
app.exec_()

答案 1 :(得分:0)

我至少找到了resize在我的代码中无效的原因。将QScroll区域的widgetResizable属性设置为false(或在Qt Designer中禁用它)使其工作。