QGraphics 中不需要的边距与滚动条视图
Unwanted margin inside QGraphicsView with Scrollbars
我正在开发一个视频播放器,使用QGraphicsView
来显示视频。QGraphicsView
显示一个QGraphicsScene
,其中包含当前视频帧的单个QGraphicsPixmapItem
。视图的背景为黑色。
一切都很好,视频帧显示在视图的中心,视图的其余部分是黑色的。当视图与框架具有相同的大小时,仅显示框架,(显然(没有背景。当视频帧大于视图时,将显示滚动条,以便用户可以滚动以查看帧的其他部分。
问题:显示滚动条时,可以滚动到视频帧之外。在底部和右侧可以看到背景的 8 像素边距。如果视频帧大于视图,则不应有可见的背景,并且无法滚动到视频帧之外。
我将问题简化为演示问题的简短源代码,在绿色背景的QGraphicsView
中显示一个 200x200 像素的红色QPixmap
。
#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();
}
我还制作了问题的图像(示例代码中不包含黑色边框(: https://i.stack.imgur.com/K6I3R.jpg
在左侧窗口中,QGraphicsView
与矩形的大小相同,在右侧窗口中,它略小,因此显示滚动条。而且背景也是可见的(它不应该是可见的(。
我已经尝试设置场景矩形和QWidget
,QGraphicsView
和QGraphicsScene
的各种其他属性,但没有发现任何问题
我还尝试在虚拟机中运行示例问题,以排除我的Qt/KDE版本存在错误的可能性。
我不知道为什么在有滚动条时突然显示背景。我怎样才能摆脱它?如果这是不可能的,你知道我该如何解决这个问题吗?
提前谢谢。
问题是 QGraphicsView::fitInView(( 的一个错误,他们不关心:https://bugreports.qt.io/browse/QTBUG-11945
无需重新实现您自己的 fitInView,只需在创建视图时从视图中删除边距即可。
view.setViewportMargins(-2, -2, -2, -2)
view.setFrameStyle(QFrame.NoFrame)
你看到的是 QGraphicsView 之外的窗口区域。您可能还会发现可以调整窗口大小并显示更多边框。
若要修复此问题,请将窗口的大小限制为 QGraphicsView 的大小。由于您尚未在示例代码中设置此设置,因此它将是像素图的大小。
因此,在声明窗口后添加以下行:-
window.setMaximumWidth(200);
window.setMaximumHeight(200);
这样做将限制窗口的大小调整大于这些值,因此如果您需要调整其大小超过该值,则需要更大的 QGraphicsView 和 QGraphicsScene。
我尝试了问题的片段,但在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位,PySide 1.2.1包装Qt 4.8(
这实际上只是变相的这个问题 - 看看并投票 https://bugreports.qt.io/browse/QTBUG-42331
简而言之,fitInView具有硬编码的边距,这可能会导致各种破坏 - 其中最少的是,现在您丢失了显示区域的几个像素,并且还可能强制进行不必要的重新缩放。
确保选择一个答案
我修复了它,创建了自己的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());
}
- QScrollArea:由垂直滚动条引起的水平滚动条
- 跟踪滚动条上的鼠标事件
- 如何在不使用滚动条的情况下使视图更改
- 通过水平滚动条更改标签
- Qt:无法直接为带有子项的小部件添加滚动条
- OnVScroll : 从 CSpinButtonCtrl 或垂直滚动条调用?
- win32 滚动条在 C/C++ 程序中不起作用
- 外观 MFC 滚动条
- 停止 QTextCursor::insertText() 修改 QTextDocument 滚动条范围
- 如何在wxRadioBox中添加滚动条
- QPainter的QWidget滚动条
- 将水平滚动条添加到控制台
- QT - 如何创建具有长 int(而不是 int)步长的滚动条?
- 如何在移动列表视图中添加滚动条?并且用户只能垂直滚动特定区域
- 列表视图中的 CListCtrl 垂直滚动条
- 当用户将列表视图项拖动到其滚动条上时,执行默认滚动行为
- 如何获取避免滚动条的树视图控件的最小大小
- 禁用列表视图中的水平滚动条
- QGraphics 中不需要的边距与滚动条视图
- 如何访问Qtitan视图的滚动条?