0

我的应用程序中有一个带有 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()

如何使其增长/调整大小?

4

2 回答 2

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_()
于 2012-07-15T16:55:58.130 回答
0

resize我至少找到了一个在我的代码中不起作用的原因。将widgetResizableQScroll 区域的属性设置为 false(或在 Qt 设计器中禁用它)使其工作。

于 2012-07-18T19:25:26.757 回答