如何在 Qt 中使用 QGraphicsItem 的 itemChange
How to use itemChange from QGraphicsItem in Qt
我有自定义椭圆 QGraphicsItem
class 和自定义线 class。在现场,我假设有两个椭圆和它们之间用一条线连接起来。 Ellipse 有一个指向这条线的指针并且是可移动的。我的问题是我不知道如何使用 QGraphicsItem
中的 itemChange()
。我想建立会随着椭圆运动而变化的联系。因此,我想使用 itemChange()
方法以始终位于椭圆中心的方式更改线坐标。我阅读了 QGraphicsItem::itemChange() 的文档,但我不知道如何在我的案例中使用它。
正如其他人已经指出的那样,您需要覆盖(重新实现)class 中的方法。
下面是一个完整的示例来证明这一点:
#include "Dialog.h"
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsEllipseItem>
#include <QGraphicsLineItem>
class CustomElipse : public QGraphicsEllipseItem
{
public:
CustomElipse (const QRectF& rect) : QGraphicsEllipseItem(rect) {
setFlag(QGraphicsItem::ItemIsMovable);
setFlag(QGraphicsItem::ItemSendsScenePositionChanges);
}
void addLine(QGraphicsLineItem *line, bool isPoint1) {
this->line = line;
isP1 = isPoint1;
}
QVariant itemChange(GraphicsItemChange change, const QVariant &value)
{
if (change == ItemPositionChange && scene()) {
// value is the new position.
QPointF newPos = value.toPointF();
moveLineToCenter(newPos);
}
return QGraphicsItem::itemChange(change, value);
}
void moveLineToCenter(QPointF newPos) {
// Converts the elipse position (top-left)
// to its center position
int xOffset = rect().x() + rect().width()/2;
int yOffset = rect().y() + rect().height()/2;
QPointF newCenterPos = QPointF(newPos.x() + xOffset, newPos.y() + yOffset);
// Move the required point of the line to the center of the elipse
QPointF p1 = isP1 ? newCenterPos : line->line().p1();
QPointF p2 = isP1 ? line->line().p2() : newCenterPos;
line->setLine(QLineF(p1, p2));
}
private:
QGraphicsLineItem *line;
bool isP1;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsScene scene;
CustomElipse *elipse1 = new CustomElipse(QRectF(30, 30, 15, 25));
scene.addItem(elipse1);
CustomElipse *elipse2 = new CustomElipse(QRectF(70, 70, 25, 15));
scene.addItem(elipse2);
QGraphicsLineItem *line = scene.addLine(QLineF(40, 40, 80, 80));
elipse1->addLine(line, true);
elipse2->addLine(line, false);
QGraphicsView view(&scene);
view.show();
return a.exec();
}
上面的代码绘制了两个可移动的椭圆,在它们之间画了一条线。行位置调整以跟随省略号。
当 运行 时,您会得到如下内容:
对于任何正在寻找 python 代码的人来说,这里是@AntonyG 代码的翻译:
import sys
from PyQt5 import QtWidgets, QtCore
class CustomItem(QtWidgets.QGraphicsEllipseItem):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setFlag(self.ItemIsMovable)
self.setFlag(self.ItemSendsGeometryChanges)
self.line = None
self.isPoint = None
def addLine(self, line, ispoint):
self.line = line
self.isPoint = ispoint
def itemChange(self, change , value):
if change == self.ItemPositionChange and self.scene():
newPos = value
self.moveLineToCenter(newPos)
return super(CustomItem, self).itemChange(change, value)
def moveLineToCenter(self, newPos):
xOffset = self.rect().x() + self.rect().width()/2
yOffset = self.rect().y() + self.rect().height()/2
newCenterPos = QtCore.QPointF(newPos.x()+xOffset, newPos.y()+yOffset)
p1 = newCenterPos if self.isPoint else self.line.line().p1()
p2 = self.line.line().p2() if self.isPoint else newCenterPos
self.line.setLine(QtCore.QLineF(p1, p2))
def main():
app =QtWidgets.QApplication(sys.argv)
scene = QtWidgets.QGraphicsScene()
ellipse = CustomItem(QtCore.QRectF(30, 30, 15, 25))
scene.addItem(ellipse)
ellipse2 = CustomItem(QtCore.QRectF(70, 70, 25, 15))
scene.addItem(ellipse2)
line = scene.addLine(QtCore.QLineF(40, 40, 80, 80))
ellipse.addLine(line, True)
ellipse2.addLine(line, False)
view = QtWidgets.QGraphicsView(scene)
view.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
我有自定义椭圆 QGraphicsItem
class 和自定义线 class。在现场,我假设有两个椭圆和它们之间用一条线连接起来。 Ellipse 有一个指向这条线的指针并且是可移动的。我的问题是我不知道如何使用 QGraphicsItem
中的 itemChange()
。我想建立会随着椭圆运动而变化的联系。因此,我想使用 itemChange()
方法以始终位于椭圆中心的方式更改线坐标。我阅读了 QGraphicsItem::itemChange() 的文档,但我不知道如何在我的案例中使用它。
正如其他人已经指出的那样,您需要覆盖(重新实现)class 中的方法。
下面是一个完整的示例来证明这一点:
#include "Dialog.h"
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsEllipseItem>
#include <QGraphicsLineItem>
class CustomElipse : public QGraphicsEllipseItem
{
public:
CustomElipse (const QRectF& rect) : QGraphicsEllipseItem(rect) {
setFlag(QGraphicsItem::ItemIsMovable);
setFlag(QGraphicsItem::ItemSendsScenePositionChanges);
}
void addLine(QGraphicsLineItem *line, bool isPoint1) {
this->line = line;
isP1 = isPoint1;
}
QVariant itemChange(GraphicsItemChange change, const QVariant &value)
{
if (change == ItemPositionChange && scene()) {
// value is the new position.
QPointF newPos = value.toPointF();
moveLineToCenter(newPos);
}
return QGraphicsItem::itemChange(change, value);
}
void moveLineToCenter(QPointF newPos) {
// Converts the elipse position (top-left)
// to its center position
int xOffset = rect().x() + rect().width()/2;
int yOffset = rect().y() + rect().height()/2;
QPointF newCenterPos = QPointF(newPos.x() + xOffset, newPos.y() + yOffset);
// Move the required point of the line to the center of the elipse
QPointF p1 = isP1 ? newCenterPos : line->line().p1();
QPointF p2 = isP1 ? line->line().p2() : newCenterPos;
line->setLine(QLineF(p1, p2));
}
private:
QGraphicsLineItem *line;
bool isP1;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsScene scene;
CustomElipse *elipse1 = new CustomElipse(QRectF(30, 30, 15, 25));
scene.addItem(elipse1);
CustomElipse *elipse2 = new CustomElipse(QRectF(70, 70, 25, 15));
scene.addItem(elipse2);
QGraphicsLineItem *line = scene.addLine(QLineF(40, 40, 80, 80));
elipse1->addLine(line, true);
elipse2->addLine(line, false);
QGraphicsView view(&scene);
view.show();
return a.exec();
}
上面的代码绘制了两个可移动的椭圆,在它们之间画了一条线。行位置调整以跟随省略号。
当 运行 时,您会得到如下内容:
对于任何正在寻找 python 代码的人来说,这里是@AntonyG 代码的翻译:
import sys
from PyQt5 import QtWidgets, QtCore
class CustomItem(QtWidgets.QGraphicsEllipseItem):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setFlag(self.ItemIsMovable)
self.setFlag(self.ItemSendsGeometryChanges)
self.line = None
self.isPoint = None
def addLine(self, line, ispoint):
self.line = line
self.isPoint = ispoint
def itemChange(self, change , value):
if change == self.ItemPositionChange and self.scene():
newPos = value
self.moveLineToCenter(newPos)
return super(CustomItem, self).itemChange(change, value)
def moveLineToCenter(self, newPos):
xOffset = self.rect().x() + self.rect().width()/2
yOffset = self.rect().y() + self.rect().height()/2
newCenterPos = QtCore.QPointF(newPos.x()+xOffset, newPos.y()+yOffset)
p1 = newCenterPos if self.isPoint else self.line.line().p1()
p2 = self.line.line().p2() if self.isPoint else newCenterPos
self.line.setLine(QtCore.QLineF(p1, p2))
def main():
app =QtWidgets.QApplication(sys.argv)
scene = QtWidgets.QGraphicsScene()
ellipse = CustomItem(QtCore.QRectF(30, 30, 15, 25))
scene.addItem(ellipse)
ellipse2 = CustomItem(QtCore.QRectF(70, 70, 25, 15))
scene.addItem(ellipse2)
line = scene.addLine(QtCore.QLineF(40, 40, 80, 80))
ellipse.addLine(line, True)
ellipse2.addLine(line, False)
view = QtWidgets.QGraphicsView(scene)
view.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()