创建一个 Qt 显示
create a Qt display
我正在制作一个项目,它将在字段中使用箭头,如下所示。
我希望对象在接收到一些移动数据时移动 - 例如来自卫星的坐标。
问题是:
- 如何创建对象箭头?
- 我应该使用哪些库?我应该使用 QGraphicsScene Class 来移动它吗?
我从来没有真正使用过这种类型的 Qt 对象。我开始使用 PyQt5 在 Python 中进行编码,但是由于缺少使用该语言使用该库的示例 - 我开始学习 C++ 以更好地理解 Qt5 库。
Qt 的优势在于它允许您使用 low-level 工具(如 QPainter)到 high-level 工具(如 QGraphicsItem、QML 项目)创建视觉元素。在这种情况下,最简单的方法是使用基于 QGraphicsPathItem 的 QGraphicsItem 并覆盖自定义绘制的 paint 方法。对于移动的情况,您只需使用 setPos() 方法,但要获得平滑的移动,则必须使用 QVariantAnimation。
import random
from PyQt5 import QtCore, QtGui, QtWidgets
class ArrowItem(QtWidgets.QGraphicsPathItem):
def __init__(self, parent=None):
super().__init__(parent)
self._length = -1
self._points = QtCore.QPointF(), QtCore.QPointF(), QtCore.QPointF()
self.length = 40.0
@property
def length(self):
return self._length
@length.setter
def length(self, l):
self._length = l
pos_top = QtCore.QPointF(0, l * 4 / 5)
pos_left = QtCore.QPointF(-l * 3 / 5, -l / 5)
pos_right = QtCore.QPointF(
l * 3 / 5,
-l / 5,
)
path = QtGui.QPainterPath()
path.moveTo(pos_top)
path.lineTo(pos_right)
path.lineTo(pos_left)
self.setPath(path)
self._points = pos_top, pos_left, pos_right
def paint(self, painter, option, widget):
pos_top, pos_left, pos_right = self._points
left_color = QtGui.QColor("#cc0000")
right_color = QtGui.QColor("#ff0000")
bottom_color = QtGui.QColor("#661900")
path_left = QtGui.QPainterPath()
path_left.lineTo(pos_top)
path_left.lineTo(pos_left)
path_right = QtGui.QPainterPath()
path_right.lineTo(pos_top)
path_right.lineTo(pos_right)
path_bottom = QtGui.QPainterPath()
path_bottom.lineTo(pos_left)
path_bottom.lineTo(pos_right)
painter.setPen(QtGui.QColor("black"))
painter.setBrush(left_color)
painter.drawPath(path_left)
painter.setBrush(right_color)
painter.drawPath(path_right)
painter.setBrush(bottom_color)
painter.drawPath(path_bottom)
def moveTo(self, next_position, duration=100):
self._animation = QtCore.QVariantAnimation()
self._animation.setStartValue(self.pos())
self._animation.setEndValue(next_position)
self._animation.setDuration(duration)
self._animation.start(QtCore.QAbstractAnimation.DeleteWhenStopped)
self._animation.valueChanged.connect(self.setPos)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.scene = QtWidgets.QGraphicsScene()
view = QtWidgets.QGraphicsView()
view.setRenderHints(QtGui.QPainter.Antialiasing)
view.setScene(self.scene)
view.scale(1, -1)
button = QtWidgets.QPushButton("Click me")
central_widget = QtWidgets.QWidget()
lay = QtWidgets.QVBoxLayout(central_widget)
lay.addWidget(view)
lay.addWidget(button)
self.setCentralWidget(central_widget)
self.resize(640, 480)
self.arrow_item = ArrowItem()
self.scene.addItem(self.arrow_item)
button.clicked.connect(self.handle_clicked)
def handle_clicked(self):
x, y = random.sample(range(300), 2)
print("next position:", x, y)
self.arrow_item.moveTo(QtCore.QPointF(x, y))
if __name__ == "__main__":
app = QtWidgets.QApplication([])
w = MainWindow()
w.show()
app.exec_()
注意:PyQt5(还有PySide2)提供了很多用python编写的示例,这些示例是C++示例的翻译,所以我建议您下载源代码(PyQt5 and PySide2) and study them. I also have a repo 带有一些例子的翻译。
我正在制作一个项目,它将在字段中使用箭头,如下所示。
我希望对象在接收到一些移动数据时移动 - 例如来自卫星的坐标。
问题是:
- 如何创建对象箭头?
- 我应该使用哪些库?我应该使用 QGraphicsScene Class 来移动它吗?
我从来没有真正使用过这种类型的 Qt 对象。我开始使用 PyQt5 在 Python 中进行编码,但是由于缺少使用该语言使用该库的示例 - 我开始学习 C++ 以更好地理解 Qt5 库。
Qt 的优势在于它允许您使用 low-level 工具(如 QPainter)到 high-level 工具(如 QGraphicsItem、QML 项目)创建视觉元素。在这种情况下,最简单的方法是使用基于 QGraphicsPathItem 的 QGraphicsItem 并覆盖自定义绘制的 paint 方法。对于移动的情况,您只需使用 setPos() 方法,但要获得平滑的移动,则必须使用 QVariantAnimation。
import random
from PyQt5 import QtCore, QtGui, QtWidgets
class ArrowItem(QtWidgets.QGraphicsPathItem):
def __init__(self, parent=None):
super().__init__(parent)
self._length = -1
self._points = QtCore.QPointF(), QtCore.QPointF(), QtCore.QPointF()
self.length = 40.0
@property
def length(self):
return self._length
@length.setter
def length(self, l):
self._length = l
pos_top = QtCore.QPointF(0, l * 4 / 5)
pos_left = QtCore.QPointF(-l * 3 / 5, -l / 5)
pos_right = QtCore.QPointF(
l * 3 / 5,
-l / 5,
)
path = QtGui.QPainterPath()
path.moveTo(pos_top)
path.lineTo(pos_right)
path.lineTo(pos_left)
self.setPath(path)
self._points = pos_top, pos_left, pos_right
def paint(self, painter, option, widget):
pos_top, pos_left, pos_right = self._points
left_color = QtGui.QColor("#cc0000")
right_color = QtGui.QColor("#ff0000")
bottom_color = QtGui.QColor("#661900")
path_left = QtGui.QPainterPath()
path_left.lineTo(pos_top)
path_left.lineTo(pos_left)
path_right = QtGui.QPainterPath()
path_right.lineTo(pos_top)
path_right.lineTo(pos_right)
path_bottom = QtGui.QPainterPath()
path_bottom.lineTo(pos_left)
path_bottom.lineTo(pos_right)
painter.setPen(QtGui.QColor("black"))
painter.setBrush(left_color)
painter.drawPath(path_left)
painter.setBrush(right_color)
painter.drawPath(path_right)
painter.setBrush(bottom_color)
painter.drawPath(path_bottom)
def moveTo(self, next_position, duration=100):
self._animation = QtCore.QVariantAnimation()
self._animation.setStartValue(self.pos())
self._animation.setEndValue(next_position)
self._animation.setDuration(duration)
self._animation.start(QtCore.QAbstractAnimation.DeleteWhenStopped)
self._animation.valueChanged.connect(self.setPos)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.scene = QtWidgets.QGraphicsScene()
view = QtWidgets.QGraphicsView()
view.setRenderHints(QtGui.QPainter.Antialiasing)
view.setScene(self.scene)
view.scale(1, -1)
button = QtWidgets.QPushButton("Click me")
central_widget = QtWidgets.QWidget()
lay = QtWidgets.QVBoxLayout(central_widget)
lay.addWidget(view)
lay.addWidget(button)
self.setCentralWidget(central_widget)
self.resize(640, 480)
self.arrow_item = ArrowItem()
self.scene.addItem(self.arrow_item)
button.clicked.connect(self.handle_clicked)
def handle_clicked(self):
x, y = random.sample(range(300), 2)
print("next position:", x, y)
self.arrow_item.moveTo(QtCore.QPointF(x, y))
if __name__ == "__main__":
app = QtWidgets.QApplication([])
w = MainWindow()
w.show()
app.exec_()
注意:PyQt5(还有PySide2)提供了很多用python编写的示例,这些示例是C++示例的翻译,所以我建议您下载源代码(PyQt5 and PySide2) and study them. I also have a repo 带有一些例子的翻译。