在Qt中实现无限可缩放的画布
Implementing an infinite zoomable canvas in Qt
我正在从事一个需要无限表面(样条曲线和文本(的项目,该项目也需要可扩展。"虚拟图面"的要求是:
- 能够在表面上滚动和移动
- 能够动态调整其高度(可能到无穷大,但实际上高达 200000 "像素"(
- 固定宽度
- 能够绘制矢量路径、文本和图像
- 可缩放(使用捏合缩放。此外,当比例更改时,所有矢量都应以新比例渲染。
- 能够部分更新表面区域
看看Qt,我列出了3个主要选项来实现这一点,但我不完全确定其中哪个最适合我的需求(或者即使我错过了另一种选择:
- QGraphicsView,它可以轻松地为我提供一个可滚动的视口,并具有几个内置的渲染策略来实现我的目标(尤其是这个 https://doc.qt.io/qt-5/qgraphicsview.html#ViewportUpdateMode-enum(。这也将自动为我提供轻拂和调整内容大小的工具。唯一的问题是这个类是Qt小部件的一部分,我真的很想使用QML(。 使用
QQuickPaintedItem
作为我的图面的视口,并在使用滚动和缩放时动态绘制它。这将需要我从QML更新视口(可能使用可轻拂和PinchArea的组合(。但是,我不确定使用此选项滚动是否足够流畅,因为我需要大量重绘该项目才能实现 60fps。通过将已绘制的区域存储在某些 QImage 对象中,然后在需要时绘制它们(本质上是基于磁贴的自定义渲染解决方案,需要大量时间才能正确实现(,可以缓解这种情况。- 使用
QQuickItem
而不是QQuickPaintedItem
来实现更好的性能,但是如果没有 QPainter,绘制路径、形状和文本将非常困难,并且需要使用QSG
类进行大量工作。
Qt还有其他方法可以实现这一点吗?
我在 64.000 像素的水平可滚动区域中绘制时遇到了同样的问题。为了解决这个问题,我使用 ListView 将区域划分为段,每个段 8.000 像素。计算的段计数用作模型,委托是用于C++绘画的 QQuickPainted项目。但这也适用于 QML-Canvas。
ListView {
id: graphicView
anchors.fill: parent
orientation: Qt.Horizontal
spacing: 0
// always repaint items on scroll
reuseItems: false
// the width of the scrollable area
readonly property real displayWidth: 64000
// define a max width for segmentation to avoid the contentWidth limitation of qml
readonly property int segmentWith: 8000
readonly property int segmentCount: Math.max(1, Math.round(displayWidth / segmentWith))
onSegmentCountChanged: {
console.log("OsziGraphic: displayWidth = " + displayWidth + ", segmentCount = " + segmentCount);
}
model: graphicView.segmentCount
delegate:
TestGraphicModel {
height: ListView.view.height
width: graphicView.displayWidth / graphicView.segmentCount
segmentIndex: index
}
}
在后端,我继承了 QQuickPaintedItem 的属性,为当前段索引和要绘制的渲染区域添加属性。我平移渲染的坐标进行绘制,就好像使用了整个区域一样。
void QQuickSegmentedPaintedItem::paint(QPainter *painter)
{
if (m_segmentIndex == -1)
return;
// calculate the current render rect inside the drawing area
m_renderRect = QRect(m_segmentIndex * boundingRect().width(), 0, boundingRect().width(), boundingRect().height());
// move the drawing area relative to the current render area
painter->translate(-m_renderRect.left(), 0);
}
这很好地满足了我的需求。我希望你明白这个想法。
干杯!
相关文章:
- UE4-如何在给定4个屏幕坐标的情况下缩放纹理或材质
- 计算缩放多边形的比例,得到给定的多边形面积
- QwtPlot具有相等的轴和自动缩放
- 如何在directx/c++中进行平移/缩放操作
- 在Qt中实现无限可缩放的画布
- 是否可以为 QPixmap 派生类嵌入缩放方法?
- 形状对象的旋转和缩放不正确C++
- 如何在 OpenSceneGraph 中缩放/旋转/移动资产
- 如何在OpenGL(GLFW,很高兴)中进行2D缩放?
- 改变或缩放两个正态分布以具有特定的相关系数
- SDL2 调整窗口大小后如何缩放鼠标坐标?
- 如何在OpenGL中正确旋转和缩放对象?
- 仅当类型为 std::complex 时,才进行缩放
- 将 VS Code 用于跨平台可缩放C++项目
- 根据帧速率缩放/缩小数字
- 在 c++ 中缩放浮点值
- 如何防止 DirectX C++程序的拉伸/缩放
- 使用提升几何缓冲区缩放多边形时的冗余折点
- 为什么我不能使用 Sphere 来缩放字形?
- 我在QChartView中找不到缩放图形的鼠标滚轮滚动事件