2

我有一个程序可以将 a 的内容绘制为QGraphicsScenePNG 图像。我发现在某些情况下未正确创建 PNG 图像。生成的图像似乎有一定程度的“偏移”,因为 PNG 图像的左上角QGraphicsScene不在 (0,0) 处。

下面的代码演示了这个问题。该createImage函数创建一个QGraphicsScene给定宽度和高度的 a,在坐标 (0, 0) 处绘制一个与场景具有相同宽度和高度的红色实心矩形,将此场景渲染为图像并将图像写入文件。我相信这个函数应该总是写出一个纯红色的图像,不管它给出的宽度和高度如何。但是,是一个示例输出图像,它表明情况并非如此。

testImage函数(依赖于PIL)读取图像并检查最右边的列和底行。如果图像被错误地“偏移”,它将在底行或最右列的某处找到一个白色像素。如果图像已正确生成,则底行和最右列将仅包含红色像素。(PIL 不是问题的一部分;我只是用它来自动测试输出图像。)

#!/usr/bin/env python

import sys
import Image        # Requires PIL
from PyQt4.QtCore import Qt, QRect, QRectF
from PyQt4.QtGui import QPen, QBrush, QGraphicsScene, QGraphicsView, QGraphicsRectItem, QPixmap, QPainter, QApplication

whitebrush = QBrush(Qt.white)
redbrush = QBrush(Qt.red)

RED = (255, 0, 0)

def createImage(width, height):
    scene = QGraphicsScene(0, 0, width, height)
    scene.setBackgroundBrush(whitebrush)

    rectangle = QGraphicsRectItem(0, 0, width, height)
    rectangle.setPen(QPen(Qt.NoPen))
    rectangle.setBrush(redbrush)
    rectangle.show()
    scene.addItem(rectangle)

    view = QGraphicsView()
    view.setScene(scene)

    outputimg = QPixmap(width, height)
    painter = QPainter(outputimg)
    targetrect = QRectF(0, 0, width, height)
    sourcerect = QRect(0, 0, width, height)
    view.render(painter, targetrect, sourcerect)
    outputimg.save("output.png", "PNG")

    painter.end()

def testImage(width, height):
    image = Image.open("output.png")
    ok = True

    for x in range(width):
        if image.getpixel((x, height - 1)) == RED:
            if x > 0:
                print "First red pixel on bottom row is at x = %d" % x
                ok = False

            break
    else:
        print "No red pixels found on bottom row"
        ok = False

    for y in range(height):
        if image.getpixel((width - 1, y)) == RED:
            if y > 0:
                print "First red pixel in rightmost column is at y = %d" % y
                ok = False

            break
    else:
        print "No red pixels found in rightmost column"
        ok = False

    if ok:
        print "Image OK"

def doTest(width, height):
    createImage(width, height)
    testImage(width, height)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    doTest(int(sys.argv[1]), int(sys.argv[2]))

以下是一些示例运行:

$ ./qgraphicssceneimagetest.py 200 200
在底行没有找到红色像素
在最右边的列中没有找到红色像素

在这种情况下,“偏移”的效果非常强烈,以至于整个输出图像都是白色的。

$ ./qgraphicssceneimagetest.py 400 400
底行的第一个红色像素位于 x = 117
最右列的第一个红色像素位于 y = 37

这就是生成我上面链接到的示例图像的情况。

$ ./qgraphicssceneimagetest.py 500 500
底行的第一个红色像素位于 x = 55

此时,图像现在正确地垂直偏移了,但红色矩形仍然被绘制得离右边太远了 55 像素。

$ ./qgraphicssceneimagetest.py 600 600
底行的第一个红色像素位于 x = 5

现在几乎正确...

$ ./qgraphicssceneimagetest.py 700 700
图像正常

因此,如果图像足够大,代码似乎可以正确生成输出图像。

碰巧,我有一个解决这个问题的方法。如果我替换该行,我可以获得createImage正确创建图像的功能

    sourcerect = QRect(0, 0, width, height)

    xoff = 0
    yoff = 0

    if width <= 634 and height <= 474:
        xoff = (634 - width) // 2
        yoff = (474 - height) // 2
    elif width < 610:
        xoff = (610 - width) // 2
    elif height < 450:
        yoff = (450 - height) // 2

    sourcerect = QRect(xoff, yoff, width, height)

我不知道这段代码中“神奇”数字的意义是什么。但是,我已经使用此解决方法运行了大量测试,并验证它们都生成了正确的纯红色图像。

有这个解决方法没问题,但我想了解为什么这些图像没有正确创建。有什么我错过或忘记做的事吗?

4

1 回答 1

2

正在发生的事情是,视图会自动计算场景的矩形,然后以已添加的图形项为中心。根据物品的尺寸,这有时可能会在边缘留下空白区域。

解决方案是为场景显式设置一个矩形:

view = QGraphicsView()
view.setScene(scene)
view.setSceneRect(QRectF(view.viewport().rect()))
于 2011-12-04T01:04:35.183 回答