4

我正在开发一个视频播放器,使用 aQGraphicsView来显示视频。QGraphicsView正在显示一个包含当前视频帧的QGraphicsScene单个。QGraphicsPixmapItem视图的背景是黑色的。

只要帧小于视图,一切都好,视频帧显示在视图的中心,视图的其余部分是黑色的。当视图与框架大小相同时,仅显示框架,(显然)没有背景。当视频帧大于视图时,会显示滚动条,以便用户可以滚动查看帧的其他部分。

问题:当显示滚动条时,可以滚动超过视频帧。背景可见的底部和右侧有 8 个像素的边距。如果视频帧大于视图,则不应有可见的背景,并且不应滚动超过视频帧。

我将问题简化为演示问题的简短源代码,QPixmapQGraphicsView绿色背景中显示 200x200 像素的红色。

#include <QtGui/QApplication>
#include <QMainWindow>
#include <QGraphicsScene>
#include <QGraphicsView>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QMainWindow window;

    QPixmap pixmap(200, 200);
    pixmap.fill(QColor(255, 0, 0));

    QGraphicsScene scene(&window);
    scene.addPixmap(pixmap);

    QGraphicsView view(&window);
    view.setBackgroundBrush(QColor(0, 255, 0));
    view.setScene(&scene);

    window.setCentralWidget(&view);
    window.show();
    window.resize(199, 199);

    return app.exec();
}

我还制作了问题的图像(示例代码中不包含黑色边框):http: //imgur.com/4X5eyhC

在左侧窗口中,QGraphicsView与矩形的大小相同,在右侧窗口中它稍微小一些,因此显示了滚动条。而且背景是可见的(它不应该是可见的)。

我已经尝试设置 sceneRect 和其他各种属性,QWidget但没有发现任何改变问题的任何东西。QGraphicsViewQGraphicsScene

我还尝试在虚拟机中运行示例问题,以排除我的 Qt/KDE 版本存在错误的可能性。

我不知道为什么有滚动条时会突然显示背景。我怎样才能摆脱它?如果这是不可能的,你知道我该如何解决这个问题吗?

提前致谢。

4

5 回答 5

3

问题是他们不关心的 QGraphicsView::fitInView() 错误:https ://bugreports.qt.io/browse/QTBUG-11945

无需重新实现您自己的 fitInView,只需在创建视图时从视图中删除边距。

view.setViewportMargins(-2, -2, -2, -2)
view.setFrameStyle(QFrame.NoFrame)
于 2020-01-22T19:38:41.947 回答
2

您看到的是 QGraphicsView 之外的窗口区域。您可能还会发现您可以调整窗口大小并显示更多边框。

要修复它,请将窗口的大小限制为 QGraphicsView 的大小。由于您没有在示例代码中设置它,它将是像素图的大小。

所以在声明窗口后添加这些行: -

window.setMaximumWidth(200);
window.setMaximumHeight(200);

这样做会限制窗口被调整到大于这些值,所以如果你需要调整它的大小,你需要一个更大的 QGraphicsView 和 QGraphicsScene。

于 2013-06-21T08:38:02.147 回答
1

我尝试了问题中的片段,但在 Python 下使用 Qt 周围的 PySide 包装器。代码几乎相同。

import sys
from PySide import QtGui

if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    window = QtGui.QMainWindow()

    pixmap = QtGui.QPixmap(200, 200)
    pixmap.fill(QtGui.QColor(255, 0, 0))

    scene = QtGui.QGraphicsScene(window)
    scene.addPixmap(pixmap)

    view = QtGui.QGraphicsView(window)
    view.setBackgroundBrush(QtGui.QColor(0, 255, 0))
    view.setScene(scene)

    window.setCentralWidget(view)
    window.show()
    window.resize(199, 199)

    sys.exit(app.exec_())

出现滚动条,但我没有看到任何绿色区域!

我猜因为它只是 QT 库的一个包装器,它可能是一个版本或系统相关的缺陷/不是真正的预期行为。用当前版本的 QT 再试一次会很有趣。

(我的规格:Windows 7 64 位、Python 2.7.2 64 位、包装 Qt 4.8 的 PySide 1.2.1)

于 2014-04-04T10:27:53.887 回答
1

这实际上只是变相的这个问题 - 看看并在https://bugreports.qt.io/browse/QTBUG-42331上投票

简而言之,fitInView 具有硬编码的边距,这可能会导致各种破坏——其中最少的是现在您丢失了几个像素的显示区域,并且还可能强制进行不必要的重新缩放。

附言。确保选择一个答案

于 2015-05-05T11:23:39.547 回答
1

我修复了它,创建了我自己的 fitInView() 方法。它与原始的 QGraphicView 方法基本相同,除了边距:

void MyClass::fitInView_fixed(const QRectF &rect, Qt::AspectRatioMode aspectRatioMode)
{
    if (!scene() || rect.isNull())
        return;
    auto unity = transform().mapRect(QRectF(0, 0, 1, 1));
    if (unity.isEmpty())
        return;
    scale(1/unity.width(), 1/unity.height());
    auto viewRect = viewport()->rect();
    if (viewRect.isEmpty())
        return;
    auto sceneRect = transform().mapRect(rect);
    if (sceneRect.isEmpty())
        return;
    qreal xratio = viewRect.width() / sceneRect.width();
    qreal yratio = viewRect.height() / sceneRect.height();

    // Respect the aspect ratio mode.
    switch (aspectRatioMode) {
    case Qt::KeepAspectRatio:
        xratio = yratio = qMin(xratio, yratio);
        break;
    case Qt::KeepAspectRatioByExpanding:
        xratio = yratio = qMax(xratio, yratio);
        break;
    case Qt::IgnoreAspectRatio:
        break;
    }
    scale(xratio, yratio);
    centerOn(rect.center());
}
于 2017-02-26T21:32:32.823 回答