add graphics of bus/bay/transformer/cable block

This commit is contained in:
baiYue 2025-08-08 17:47:31 +08:00
parent 729492a5a6
commit 834759aad5
8 changed files with 378 additions and 46 deletions

View File

@ -417,7 +417,8 @@ enum class EditorItemType //组态编辑中的图形项类型
{
bus = 0, //母线
bay, //间隔
Trans, //变压器
trans, //变压器
line, //连接线
none //空白占位图
};

View File

@ -50,6 +50,7 @@ public:
QList<DiagramEditorBaseBlock*> getTargetLevelBlocks(int nLevel,int nType); //返回指定层数的对应blocktype:1母线,2间隔,3变压器
QList<DiagramEditorBaseBlock*> getTargetLevelBlocks_all(int nLevel);
DiagramEditorStructContainer* getContainerByBlock(int nLevel,int nType,QString sName); //根据block名称返回container nType:1母线2间隔3变压器
DiagramEditorStructContainer* getContainerByBlock_all(QString sName);
DiagramEditorBaseBlock* getBlockByName(int nLevel,int nType,QString sName); //根据名称返回block
DiagramEditorBaseBlock* getBlockByName_all(QString sName);
bool removeBlockByName(int nLevel,int nType,const QString& sName); //依据名称删除block

View File

@ -39,6 +39,7 @@ class EditBusItem: public EditBaseItem
public:
EditBusItem(QGraphicsItem *parent = nullptr);
virtual ~EditBusItem();
virtual void setGeometry(const QRectF &rect) override;
protected:
virtual void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) override;
};
@ -65,4 +66,29 @@ protected:
virtual void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) override;
};
/********************连线*********************/
class EditLineItem : public EditBaseItem
{
public:
EditLineItem(QGraphicsItem *parent = nullptr);
virtual ~EditLineItem();
void setStartPoint(const QPointF& p);
void setEndPoint(const QPointF& p);
QPainterPath getPoints(void) const { return m_points; }
void calculatePath(int nSeg = 2); //划分段数2段3段
void resetCurLine(){_curLine = QPoint();}
protected:
virtual QPainterPath shape() const override;
virtual void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) override;
private:
QPainterPath m_points;
QPainterPath m_pointsBoundingRect; //包裹点的矩形集合
QList<QPointF> m_lstPoints;
QPoint _curLine; //参数1用点序号表示的当前线段起始点,参数2表示线段方向
};
#endif

View File

@ -2,6 +2,7 @@
#define EDITPANEL_H
//编辑文本项生成组态图
#include <QWidget>
#include <QPointer>
#include "global.h"
class EditView;
@ -15,6 +16,7 @@ class EditRowData;
class EditContainerItem;
class DiagramEditorWizard;
class DiagramEditorBaseBlock;
class EditBaseItem;
class EditPanel : public QWidget
{
@ -24,7 +26,8 @@ public:
~EditPanel();
void initByWizardInfo();
void setOperateWizard(DiagramEditorWizard* p) {_curWizard = p;}
void initBlockConnection(); //初始化block之间的连接信息
void setOperateWizard(QPointer<DiagramEditorWizard> p) {_curWizard = p;}
public slots:
void onWidthChanged(int width);
void onContainerSizeChanged(EditContainerItem*); //容器大小改变时调整内部大小
@ -32,19 +35,19 @@ private:
void initial();
void calculateContainerWidth(EditContainerItem*); //根据间隔数量计算容器宽度 todo:区分上下间隔
int getContainerBusType(QMap<int,QList<DiagramEditorBaseBlock*>>); //返回容器中母线类型(单双)
EditBaseItem* getItemByName(const QString&); //根据名称获取指定item
private:
EditView* m_pEditView;
EditScene* m_pEditScene;
QVBoxLayout* _layout;
EditMainRect* _mainWidget;
//QGraphicsGridLayout* _widgetLayout;
QGraphicsLinearLayout* _widgetLayout;
QGraphicsProxyWidget* m_addBtnPro;
int _maxWidth;
int _maxHeight;
QList<EditRowData*> _lstData;
QMap<int,QMap<int,EditContainerItem*>> _mapStruct;
DiagramEditorWizard* _curWizard;
QPointer<DiagramEditorWizard> _curWizard;
};
#endif

View File

@ -521,6 +521,10 @@ void DiagramEditorWizard::onAddBayFinished(DiagramEditorWizardBayInfo info)
}
}
}
else if(info.nType == BayType::outcomingBay){ //出线间隔
auto pContainer = getContainerByBlock(curIndex,1,info.lstBindObj.first());
pContainer->insertBlock(0,pBlock);
}
else{ //其他间隔
auto pContainer = getContainerByBlock(curIndex,1,info.lstBindObj.first());
pContainer->insertBlock(3,pBlock);
@ -811,6 +815,22 @@ DiagramEditorStructContainer* DiagramEditorWizard::getContainerByBlock(int nLeve
return pContainer;
}
DiagramEditorStructContainer* DiagramEditorWizard::getContainerByBlock_all(QString sName)
{
DiagramEditorStructContainer* pContainer = nullptr;
for(auto iter = _mapSturctContainer.begin(); iter != _mapSturctContainer.end();++iter){
auto lstBlock = getTargetLevelBlocks_all(iter.key());
for(auto& block:lstBlock){
if(block->getName() == sName){
pContainer = block->getCurContainer();
break;
}
}
}
return pContainer;
}
DiagramEditorBaseBlock* DiagramEditorWizard::getBlockByName(int nLevel,int nType,QString sName)
{
auto lstBlock = getTargetLevelBlocks(nLevel,nType);

View File

@ -30,6 +30,14 @@ EditBusItem::~EditBusItem()
}
void EditBusItem::setGeometry(const QRectF &rect)
{
prepareGeometryChange();
QGraphicsWidget::setGeometry(rect);
}
void EditBusItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
painter->fillRect(m_boundingRect,Qt::black);
@ -73,3 +81,110 @@ void EditTransItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* opt
painter->drawRect(m_boundingRect);
painter->drawText(QPointF(-10,0),sName);
}
/********************连线*********************/
EditLineItem::EditLineItem(QGraphicsItem *parent)
: EditBaseItem(parent)
{
m_boundingRect = QRectF();
m_lstPoints.push_back(QPointF()); //起点
m_lstPoints.push_back(QPointF()); //终点
_curLine = QPoint();
}
EditLineItem::~EditLineItem()
{
}
void EditLineItem::setStartPoint(const QPointF& p)
{
int n = m_lstPoints.size();
if(n)
{
if(n >2)
{
if(m_lstPoints[0].x() == m_lstPoints[1].x()) //相邻点在垂直方向,水平移动,否则垂直移动
{
m_lstPoints[1].setX(p.x());
}
else
{
m_lstPoints[1].setY(p.y());
}
}
m_lstPoints[0] = p;
}
}
void EditLineItem::setEndPoint(const QPointF& p)
{
int n = m_lstPoints.size();
if(n)
{
if(n >2)
{
if(m_lstPoints[n-1].x() == m_lstPoints[n-2].x()) //相邻点在垂直方向,水平移动,否则垂直移动
{
m_lstPoints[n-2].setX(p.x());
}
else
{
m_lstPoints[n-2].setY(p.y());
}
}
m_lstPoints[n-1] = p;
}
}
QPainterPath EditLineItem::shape() const
{
QPainterPath path;
path.addPath(m_pointsBoundingRect);
return path;
}
void EditLineItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
painter->setPen(Qt::black);
painter->drawPath(m_points);
}
void EditLineItem::calculatePath(int nSeg)
{
prepareGeometryChange();
m_points.clear();
m_pointsBoundingRect.clear();
if(m_lstPoints.size() == 2 && (m_lstPoints.first().x() != m_lstPoints.last().x()) && (m_lstPoints.first().y() != m_lstPoints.last().y()))
{
if(nSeg == 2)
{
/*if(m_lstPoints.first().y() < m_lstPoints.last().y())
m_lstPoints.insert(1,QPointF(m_lstPoints.first().x(),m_lstPoints.last().y()));
else
m_lstPoints.insert(1,QPointF(m_lstPoints.last().x(),m_lstPoints.first().y()));*/
m_lstPoints.insert(1,QPointF(m_lstPoints.last().x(),m_lstPoints.first().y()));
}
else
{
const QPointF p1 = m_lstPoints.first();
const QPointF p2 = m_lstPoints.last();
const qreal dx = (p2.x() - p1.x()) / 3;
const qreal dy = (p2.y() - p1.y()) / 3;
m_lstPoints.insert(1, QPointF(p1.x(), p1.y() + dy));
m_lstPoints.insert(2, QPointF(p2.x(), p1.y() + dy));
}
}
m_points.moveTo(m_lstPoints.first());
QPointF pLast = m_lstPoints.first();
for(int i = 1;i <m_lstPoints.size();++i)
{
m_points.lineTo(m_lstPoints[i]);
m_pointsBoundingRect.addRect(QRectF(QPointF(pLast.x()-1,pLast.y()-1),QPointF(m_lstPoints[i].x()+1,m_lstPoints[i].y()+1)));
pLast = m_lstPoints[i];
}
m_boundingRect = m_points.boundingRect();
}

View File

@ -2,6 +2,7 @@
#include <QGraphicsWidget>
#include <QGraphicsGridLayout>
#include <QPushButton>
#include <QTimer>
#include <QGraphicsProxyWidget>
#include "diagramEditor/editPanel.h"
#include "diagramEditor/editScene.h"
@ -49,7 +50,7 @@ void EditPanel::initByWizardInfo()
continue;
QGraphicsLinearLayout* layoutRowData = new QGraphicsLinearLayout(Qt::Horizontal);
layoutRowData->setSpacing(20);
//layoutRowData->setMinimumHeight(300);
layoutRowData->setMaximumHeight(300);
EditRowData* pRow = new EditRowData();
pRow->setId(QString::number(iter.key()));
auto& mapCon = iter.value();
@ -122,14 +123,21 @@ void EditPanel::initByWizardInfo()
pSpace->setBoundingRect(QRectF(0,0,g_dEditorItem_Width,g_dEditorItem_Height));
layH->addItem(pSpace);
}
layV->insertStretch(3);
layV->insertStretch(1);
if(layV->count() == 4){
layV->insertStretch(3);
layV->insertStretch(1);
}
else if(layV->count() == 2)
{
layV->insertStretch(1);
}
calculateContainerWidth(pContain);
int n = getContainerBusType(mapBlock);
/*int n = getContainerBusType(mapBlock);
if(n == 1){
layoutRowData->setMaximumHeight(210);
}
}*/
}
_lstData.append(pRow);
//layoutRowData->addStretch();
@ -168,7 +176,7 @@ void EditPanel::initByWizardInfo()
if(nType == 3){ //变压器
auto pTrans = new EditTransItem();
pTrans->setType(EditorItemType::Trans);
pTrans->setType(EditorItemType::trans);
pTrans->setBoundingRect(QRectF(0,0,g_dEditorItem_Width,g_dEditorItem_Width));
pItem = pTrans;
}
@ -192,6 +200,124 @@ void EditPanel::initByWizardInfo()
}
}
_widgetLayout->addStretch();
QTimer::singleShot(300, [&]() { // 1000 毫秒 = 1 秒
qDebug() << "一次性定时器触发!";
initBlockConnection();
});
}
void EditPanel::initBlockConnection()
{
if(_curWizard){
auto mapCon = _curWizard->getConnection();
//todo:添加过的不再添加
for(auto& con:mapCon){
auto item1 = _curWizard->getBlockByName_all(con.con1.sName);
auto item2 = _curWizard->getBlockByName_all(con.con2.sName);
auto con1 = _curWizard->getContainerByBlock_all(con.con1.sName);
auto con2 = _curWizard->getContainerByBlock_all(con.con2.sName);
auto pItem1 = getItemByName(item1->getName());
auto pItem2 = getItemByName(item2->getName());
/*QRectF rect1 = pItem1->geometry();
QRectF rect2 = pItem2->geometry();
QPointF center1 = pItem1->mapToScene(rect1.center());
QPointF center2 = pItem2->mapToScene(rect2.center());*/
EditLineItem* pLine = new EditLineItem();
pLine->setName(con.uid.toString());
pLine->setType(EditorItemType::line);
m_pEditScene->addItem(pLine);
if(con1 && con2){
int nT1 = item1->getType();
int nT2 = item2->getType();
QPointF center1 = pItem1->scenePos();
QPointF center2 = pItem2->scenePos();
if(con1 == con2){ //两个block在同一个容器中(上下连接)
center1 += QPointF(pItem1->boundingRect().width()*0.5,0);
center2 += QPointF(pItem2->boundingRect().width()*0.5,0);
if((nT1 == 1 && nT2 == 2) || (nT2 == 1 && nT1 == 2)){ //对象是母线段母线横坐标与同容器Block相同
if(nT1 == 1){ //pItem1是母线
center1.setX(center2.x());
}
else{ //pItem2是母线
center2.setX(center1.x());
}
if(center1.y() < center2.y()){ //item1在item2上 2的上边连接1下边
center1 += QPointF(0,pItem1->boundingRect().height()); //将1的点移动到下边
}
else{ //2在1上
center2 += QPointF(0,pItem2->boundingRect().height()); //将2的点移动到下边
}
pLine->setStartPoint(center1);
pLine->setEndPoint(center2);
pLine->calculatePath();
}
}
else{
if((nT1 == 1 && nT2 == 2) || (nT2 == 1 && nT1 == 2)){ //分段连接(左右连接)
center1 += QPointF(0,pItem1->boundingRect().height()*0.5);
center2 += QPointF(0,pItem2->boundingRect().height()*0.5);
if(center1.x() < center2.x()){ //item1在item2左边 1右连2左
center1 += QPointF(pItem1->boundingRect().width(),0);
}
else{ //1在2右 2右连1左
center2 += QPointF(pItem2->boundingRect().width(),0);
}
pLine->setStartPoint(center1);
pLine->setEndPoint(center2);
pLine->calculatePath();
}
else if((nT1 == 3 && nT2 == 2) || (nT2 == 2 && nT1 == 3)){ //变压器连间隔
center1 += QPointF(pItem1->boundingRect().width()*0.5,0);
center2 += QPointF(pItem2->boundingRect().width()*0.5,0);
DiagramEditorTransformerBlock* pTrans = nullptr;
DiagramEditorBayBlock* pBay = nullptr;
if(nT1 == 3){
pTrans = dynamic_cast<DiagramEditorTransformerBlock*>(item1);
pBay = dynamic_cast<DiagramEditorBayBlock*>(item2);
}
else if(nT2 == 3){
pTrans = dynamic_cast<DiagramEditorTransformerBlock*>(item2);
pBay = dynamic_cast<DiagramEditorBayBlock*>(item1);
}
if(pTrans && pBay){
TransformerType typTrans = pTrans->getTransType();
BayType typBay = pBay->getBayType();
if(typTrans == TransformerType::twoWinding){ //两绕组
if(typBay == BayType::incomingBay){ //进线间隔,在高压侧
center2 += QPointF(0,pItem2->boundingRect().height());
}
else if(typBay == BayType::outcomingBay){ //出线间隔,在低压侧
center1 += QPointF(0,pItem1->boundingRect().height());
}
}
else{ //三绕组 //todo:手动区分三绕组
}
}
pLine->setStartPoint(center1);
pLine->setEndPoint(center2);
pLine->calculatePath(3);
}
}
}
}
}
}
void EditPanel::onWidthChanged(int width)
@ -293,3 +419,17 @@ int EditPanel::getContainerBusType(QMap<int,QList<DiagramEditorBaseBlock*>> map)
return 1;
}
}
EditBaseItem* EditPanel::getItemByName(const QString& sName)
{
auto lstItems = m_pEditScene->items();
for(auto& item:lstItems){
auto pBase = dynamic_cast<EditBaseItem*>(item);
if(pBase){
if(pBase->getName() == sName){
return pBase;
}
}
}
return nullptr;
}

View File

@ -142,45 +142,11 @@
<number>20</number>
</property>
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout" rowstretch="1,1,1,0" columnstretch="1,2">
<layout class="QGridLayout" name="gridLayout" rowstretch="1,1,1,0,0,0" columnstretch="1,2">
<property name="verticalSpacing">
<number>10</number>
</property>
<item row="2" column="1">
<widget class="QComboBox" name="cb_target"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>间隔位置</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>间隔类型</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="cb_level"/>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="cb_bayType">
<item>
<property name="text">
<string>进线间隔</string>
</property>
</item>
<item>
<property name="text">
<string>出线间隔</string>
</property>
</item>
</widget>
</item>
<item row="3" column="0" colspan="2">
<item row="5" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="spacing">
<number>10</number>
@ -208,6 +174,66 @@
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>间隔位置</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>间隔类型</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="cb_target"/>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="cb_bayType">
<item>
<property name="text">
<string>进线间隔</string>
</property>
</item>
<item>
<property name="text">
<string>出线间隔</string>
</property>
</item>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="cb_level"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>连接到</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="cb_toPos">
<item>
<property name="text">
<string>高压侧</string>
</property>
</item>
<item>
<property name="text">
<string>中压侧</string>
</property>
</item>
<item>
<property name="text">
<string>低压侧</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item row="0" column="1" rowspan="2">