我正在使用 Qt,試圖制作一個“可點擊的 SVG”小部件的原型。我正在嘗試從 SVG 中獲取特定元素的準確坐標QSvgWidget。
為了弄清楚如何做到這一點,我有以下非常粗略的代碼。我要做的是以編程方式讓“foo”QLabel 與顯示的 SVG 中的“foo”矩形具有相同的位置。
from PySide2.QtWidgets import QApplication, QWidget, QLabel, QMainWindow
from PySide2.QtSvg import QSvgWidget
from PySide2.QtCore import QTimer
import sys
app = QApplication(sys.argv)
window = QMainWindow()
central = QSvgWidget("test_svg.svg")
foo = QLabel("foo", parent=central)
window.setCentralWidget(central)
bound1 = central.renderer().boundsOnElement("foo")
bound2 = central.renderer().transformForElement("foo").mapRect(bound1)
tl = bound2.topLeft()
foo.move(tl.x(), tl.y())
window.show()
app.exec_()
這是SVG:
<svg height="400" width="450" viewbox="0 0 450 400" xmlns="http://www.w3.org/2000/svg">
<circle stroke="red" fill="none" cx="50" cy="50" r="30" />
<rect id="foo" stroke="blue" fill="none" x="100" y="300" width="20" height="5" />
</svg>
這是我在螢屏上看到的:

當我除錯正在發生的事情時,我看到bound1.topLeft()andbound2.topLeft()是相同的,并且等于PySide2.QtCore.QPointF(99.500000, 299.500000). 這幾乎是“foo”元素在 SVG 坐標中的位置。
我不確定正確的術語是什么,但讓我將SVG 坐標系定義為 SVG 檔案中使用的坐標系,將小部件坐標系定義為對應于實際像素位置的坐標系,其中以像素相對到相關小部件的左上角。
所以QSvgWidget似乎給了我SVG坐標而不是“小部件坐標”。
有誰知道我是否有一種規范的方法可以讓 Qt 給我這些目的的“準確”坐標?我可能可以通過使用小部件大小來計算比例因子等來解決它,但 Qt 似乎有比這更好的方法。畢竟,在某些時候 Qt 必須知道實際的縮放坐標才能進行渲染。
uj5u.com熱心網友回復:
看看: https ://github.com/qt/qtsvg/blob/52d3788c7b0116ea3db232dccca5f1e3f1e229ac/src/svg/qsvgrenderer.cpp#L418
渲染器是: https ://github.com/qt/qtsvg/blob/52d3788c7b0116ea3db232dccca5f1e3f1e229ac/src/svg/qsvgrenderer.cpp#L120
所以我們去QSvgTinyDocument的渲染實作: https ://github.com/qt/qtsvg/blob/5.15.2/src/svg/qsvgtinydocument.cpp#L311
然后進行相關方法: https ://github.com/qt/qtsvg/blob/5.15.2/src/svg/qsvgtinydocument.cpp#L462
...
if (m_implicitViewBox || !preserveAspectRatio()) {
...
QTransform transform;
transform.scale(target.width() / source.width(),
target.height() / source.height());
QRectF c2 = transform.mapRect(source);
...
所以 target 是要在像素坐標上繪制的目標表面的矩形,source 是 SVG 坐標驅動的 SVG 源。在我看來,您首先猜測計算從 SVG 坐標到絕對像素坐標的系數正是 Qt 內部所做的。
相關的 QPainter 存盤有關從 SVG 坐標轉換為像素的資訊,后來用于從 SVG 繪制實際像素,但據我所知,您不應該像這樣訪問深層內部框架狀態。猜猜你首先假設計算縮放系數是你應該做的。
請注意,在 Qt::KeepAspectRatio 模式的情況下,事情會變得更加麻煩,SVG 將在保持縱橫比相同的情況下,在小部件目標表面允許的范圍內居中和縮放。從 Qt 5.15 看起來這種情況是可能的: https ://github.com/qt/qtsvg/blob/52d3788c7b0116ea3db232dccca5f1e3f1e229ac/src/svg/qsvgtinydocument.cpp#L474
https://doc.qt.io/qt-5/qsvgrenderer.html#aspectRatioMode-prop
我已將您的示例修改為(非常快速'n'dirty):
- 在視窗調整大小時重新計算標簽位置
- 使用系數從 SVG 映射到像素坐標 https://gist.github.com/mosolovsa/1bcbc2a87dc27869618266bea62a4d76
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/476966.html
