着色器本身是微不足道的,基本上你将片段位置 x 和 y 除以 qr 代码大小和得到行和列的地板,然后通过将两者相加找到 1d 索引,然后查找 qt 数据数组在该索引处,如果包含 0,则片段颜色为白色,如果包含 1,则颜色为黑色。
但是,QML 着色器目前不提供传递常规一维数组的工具。
您必须将数组转换为位图图像,并将其传递给数组,这意味着您还必须实现图像提供程序以使QImage 与 QML 一起使用,因为令人惊讶的是,它仍然默认情况下不会。
我不会太在意性能,这是过早的优化,在 99% 的情况下都是不好的。即使是简单的 100% QML 解决方案也足够快:
ApplicationWindow {
id: main
visible: true
width: 640
height: 480
color: "darkgray"
property var qrdata: []
MouseArea {
anchors.fill: parent
onClicked: {
qrdata = []
for (var i = 0; i < (100 * 100); ++i) qrdata.push(Math.round(Math.random()))
code.requestPaint()
}
}
Canvas {
id: code
width: 300
height: 300
onPaint: {
console.time("p")
var c = getContext("2d")
c.fillStyle = Qt.rgba(1, 1, 1, 1);
c.fillRect(0, 0, width, height)
c.fillStyle = Qt.rgba(0, 0, 0, 1);
var l = qrdata.length
var step = Math.sqrt(l)
var size = width / step
for (var i = 0; i < l; ++i) {
if (qrdata[i]) {
var rw = Math.floor(i / step), cl = i % step
c.fillRect(cl * size, rw * size, size, size)
}
}
console.timeEnd("p")
}
}
}
在我的系统上,绘制一个 100 x 100 的二维码大约需要 2 毫秒。 IMO 足够好,花时间制作更复杂的低级解决方案并不值得。
但是,我个人会做的是实现image provider,将二维码数据转换为图像,然后使用smooth: false 将图像缩放到我想要的任意大小,这将避免模糊并保持清晰的结果。这是迄今为止最直接、最有效和最直接的解决方案。