在 QML 中绘制虚线贝塞尔曲线 [英] Draw a dashed and dotted bezier curve in QML

查看:90
本文介绍了在 QML 中绘制虚线贝塞尔曲线的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看到有一个 a Bezier 的示例实现QML 中的曲线,但我正在寻找如何实现虚线或虚线贝塞尔曲线的提示.据我所知,贝塞尔曲线示例的作者正在使用 QSGGeometryNode 来存储 QSGGeometry 并在其上应用 QSGFlatColorMaterial 材料.然后他们只需创建点列表并在它们之间绘制线段.

I've seen there is an example implementation of a Bezier curve in QML, but I'm looking for a hint how to implement dashed or dotted bezier curve line. As far as I see, tha authors of Bezier curve example are using QSGGeometryNode to store inside QSGGeometry with a QSGFlatColorMaterial material applied on it. Then they simply create list of points and draw segments between them.

是否可以编写一个 shader 并将其应用到 QSGFlatColorMaterial (将线条显示为 dasheddotted 等)?

Is it possible to write a shader and apply it to QSGFlatColorMaterial (to display line as dashed, dotted, etc)?

最终,是否可以在 QSGGeometryNode 中存储多个 QSGGeometry?

Eventually, is it possible to store more than one QSGGeometry inside QSGGeometryNode?

更新

我想在纯 QtQuick"中实现这一点 - 而不是在旧"接口(如 QPainter 等)中 - 因为我不想使用某些东西,它切换上下文(openGL 和 CPU).我更喜欢带有自定义着色器的解决方案(如果可行的话)——因为我将有更多的可能性来实现自定义外观(虚线、点点、彩色、可能是动画等).

I would like to implement this in "pure QtQuick" - not in "old" interfaces (like QPainter etc) - because I do not want to use something, which switches context (openGL and CPU). I prefer the solution with custom shader (if is it doable) - because I'll have more possibilities in implementing custom look and feel (dashed, doted, colored, maybe animated etc).

如果不可能,我会使用 QPainter.

If it is not possible, I'll use QPainter.

推荐答案

我不认为这个任务适合使用 QSGGeometryNode 来实现,使用 <基于代码>QPainter 的绘图和一个 QQuickPaintedItem.你仍然会得到 OpenGL 的好处,因为 QPainter 也支持 GL 绘图并且它仍然比软件更快.您可以将库存 QPen 与库存点线或虚线模式一起使用,或者使用简单的 QVector 制作自己的.

I don't think this task is a good candidate for implementing using QSGGeometryNode, it would be much easier to implement it using QPainter based drawing and a QQuickPaintedItem. You will still get the benefits of OpenGL, since QPainter supports GL drawing as well and it is still faster than software. You can use the stock QPen with stock dotted or dashed patterns or make your own with a simple QVector.

或者,您可以使用自定义 GL 绘图方法,而不是使用 Qt 提供的类,这些类在表示高级复合几何时非常有限.您甚至可以使用实例化(如果可用)来进一步提高性能,并且只需沿路径曲线定位虚线或点几何图形.

Alternatively, you can go for a custom GL drawing approach instead of using the classes provided by Qt, which are pretty limited when it comes to representing advanced compound geometry. You can even use instancing (if available) to improve performance even further, and just position dashes or dot geometry along the path curve.

最后但同样重要的是,您可以使用 QML Canvas 元素,它支持与 QPainter 几乎相同的操作,并且可能提供相同的性能.

Last but not least, you can use a QML Canvas element, which supports pretty much the same operations as QPainter and probably offers the same performance.

正如您的更新所暗示的,您错过了我所说的 QPainter 可以在软件和 GL 中绘图的部分,而 GL 绘图通常要快得多.此外,通过绘制到 GL 上下文,您不必将帧缓冲区从 CPU 移动到 GPU 内存,它保存在 GPU 内存中.所以没有开销.至于动画和其他东西,当然,不可能使用 QPainter 你受限于 QPen 提供的任何东西 - 可以使用不同的连接、大写等来修改形状在某种程度上,但没有奇迹......着色器也不可能,只有自定义几何体才有可能.如果你为每个破折号/点元素使用一个基于 QObject 的对象,以便独立地为它们设置动画,那么它最终会非常昂贵,QObject 非常重,不应该用这么轻的手.因此,如果您想要这种灵活性,那么自定义 GL 渲染到 FBO 几乎是可行的方法,但是您必须完全脱离 QtQuick API 并进入 GL 领域.

As your update suggests, you missed the part where I said QPainter can draw in both software and GL, with GL drawing being often significantly faster. Also, by drawing to a GL context, you don't have to move the framebuffer from CPU to GPU memory, it is kept in GPU memory. So no overhead. As for animations and the other stuff, sure, it is not possible with QPainter you are limited to whatever QPen provides - different joins, caps and so on can be used to modify the shape to some extent, but no miracles... It won't be possible with shaders too, it will only be possible with custom geometry. And if you use a QObject based object for each dash/dot element in order to independently animate them, it will end up quite expenssive, QObject is very heavy and should not be used with such light hand. So custom GL rendering to a FBO is pretty much the way to go if you want that kind of flexibility, but you will have to move completely out of the QtQuick API and into GL land.

无论如何,虚线着色器不应该那么复杂,基本上,您可以根据与曲线的距离和沿其长度的周期"为片段着色.我找到了这个例子,自己没试过.您可以为阈值设置动画,甚至使用正弦函数来获得时髦的样式.

At any rate, a dashed line shader should not be all that complex, basically you color the fragment based on the distance from the curve and the "period" along its length. I found this example, haven't tried it myself. You could animate the thresholds, even use a sine function to get funky looking styling.

至于纯"QtQuick 实现,API 并没有真正设计用于处理此类绘图任务,这就是为什么提供 Canvas 元素来填补空白并从 QML/JS 获得高级绘图功能的原因.Canvas 实际上是一个围绕 QPainter 的包装器,用于绘制到 FBO 上.

As for a "pure" QtQuick implementation, the API has not really been designed to handle such type of drawing tasks, that is why the Canvas element was provided to fill the gap and get advanced paining functionality from QML/JS. The Canvas is effectively a wrapper around QPainter that draws onto a FBO.

最后,它并没有归结为可能/不可能,而是哪种方法最有意义,并且在完成工作方面最有效.首先尝试 QQuickPaintedItem 方法,因为它是最简单的,如果您对性能不满意,您可以实现另一个更复杂的解决方案并针对第一个进行配置.毕竟,这就是为什么首先引入 QQuickPaintedItem 的原因 - 处理不方便使用 QQuickItem 类的遗留绘画.

In the end it doesn't boil down to what is possible/impossible but which approach makes the most sense and is most efficient at getting the job done. Try the QQuickPaintedItem approach first, since it is the easiest, if you are not happy with performance, you can implement another more complex solution and profile against the first. After all, that is why QQuickPaintedItem was introduced in the first place - to handle legacy painting that is not convenient to do with the QQuickItem class.

这篇关于在 QML 中绘制虚线贝塞尔曲线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆