Пользовательский графический элемент не может быть выбран из GraphicScene - PullRequest
0 голосов
/ 24 мая 2018

После рисования круга и дуги на пользовательской сцене рисования я бы хотел выбрать дугу.Как ни странно, выбор дуги работает нормально, когда я выбираю ее на боковой панели QTreeView (отображает список элементов, присутствующих на сцене), но я не могу выбрать дугу, щелкнув по ней на сцене ...

У меня проблемы с определением источника проблемы, поэтому любая ориентация была бы более чем приветствована:)

Вот код некоторых реализованных классов:

GraphicArcItem.cpp:

#include "graphicarcitem.h"
#include "state.h"
#include "link.h"
#include <QPainter>
#include <QDebug>
#include <QPen>
#include <QStyle>
#include <QStyleOption>

GraphicArcItem::GraphicArcItem(Link *link){
    setFlags(ItemIsMovable | ItemIsSelectable);
    setFlag(QGraphicsItem::ItemSendsScenePositionChanges);
    m_link = link;
    setStartAngle(0);
    setSpanAngle(270 * 16);
    link->setArcView(this);
}

void GraphicArcItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *){
    QColor myLineColor = Qt::black;
    QPen pen(myLineColor);
        if (option->state & QStyle::State_Selected) {
        pen.setColor(Qt::blue);
        pen.setStyle(Qt::DashLine);
        pen.setWidth(2);
    }
    painter->setPen(pen);

    StateView* sview = m_link->getStart()->getStateView();
    QPointF top_left = mapFromItem(sview,
                        sview->getCenterEllipse());
    double x = top_left.rx() - 60.0 - 15.0;
    double y = top_left.ry() - 60.0 - 15.0;
    QRectF rectangle = QRectF(x,y,50.0,50.0);
    painter->drawArc(rectangle, startAngle(), spanAngle());
    x = top_left.rx() - 60.0 - 15.0 - 5;
    y = top_left.ry() - 60.0 - 15.0 - 5;
    QRectF rectangle2 = QRectF(x,y,60.0,60.0);
    painter->drawRect(rectangle2);
}

/*Return the center point of the arc in the parent coordinates*/
QPointF GraphicArcItem::getCenter(){
    int xCenter = rect().x() + rect().width()/2;
    int yCenter = rect().y() + rect().height()/2;
    QPointF center = QPointF(xCenter,yCenter);
    return center;
}

QRectF GraphicArcItem::boundingRect() const{
    StateView* sview = m_link->getStart()->getStateView();
    QPointF top_left = mapFromItem(sview,
                        sview->getCenterEllipse());
    double x = top_left.rx() - 60.0 - 15.0 - 5;
    double y = top_left.ry() - 60.0 - 15.0 - 5;
    QRectF rectangle = QRectF(x,y,60.0,60.0);
    qreal extra = (pen().width() + 50) / 2.0;
    return rectangle
         .normalized()
         .adjusted(-extra, -extra, extra, extra);
}

StateView.cpp:

#include "stateview.h"
#include "state.h"

#include <QGraphicsScene>
#include <QPen>
#include <QStyle>
#include <QStyleOption>

StateView::StateView(State *state, QRectF rect) : QGraphicsEllipseItem(rect){
    setFlags(ItemIsMovable | ItemIsSelectable);
    setFlag(QGraphicsItem::ItemSendsScenePositionChanges);
    m_state = state;
    m_rectangle = rect;
    state->setStateView(this);
}
QPointF StateView::getCenterEllipse(){
    int xCenter = rect().x() + rect().width()/2;
    int yCenter = rect().y() + rect().height()/2;
    return QPointF(xCenter,yCenter);
}

QRectF StateView::boundingRect() const{
    qreal extra = (pen().width() + 50) / 2.0;
    return m_rectangle
         .normalized()
         .adjusted(-extra, -extra, extra, extra);
}

void StateView::paint(QPainter *painter,
              const QStyleOptionGraphicsItem *option,
              QWidget */*widget*/){
    QColor myOutlineColor = Qt::black;
    QColor myBackgroundColor = Qt::white;
    QPen pen(myOutlineColor);
    if (option->state & QStyle::State_Selected) {
        pen.setColor(Qt::blue);
        pen.setStyle(Qt::DashLine);
        pen.setWidth(2);
    }
    painter->setPen(pen);
    painter->setBrush(myBackgroundColor);
    painter->drawEllipse(m_rectangle.center(), 60,60);
    QString name = getState()->getName();
    painter->drawText(this->rect(), Qt::AlignCenter, name);
}

DrawingScene.cpp:

#include "drawingscene.h"

DrawingScene::DrawingScene(QObject *parent)
: QGraphicsScene(parent){
    m_mode = MoveItem;
    m_line = 0;
    m_number_states = 0;
}

/*
 * Creates the stateView element corresponding to the
 * state and adds it to the scene
*/
void DrawingScene::on_drawState(State *state){
    QRectF rectangle(80+ (150 * (m_number_states % 3)),
                 80 + (50 * ((m_number_states / 3) % 7)),
                 120.0, 120.0);
    StateView *sview = new StateView(state, rectangle);
    addItem(sview);
    ++m_number_states;
}
/*
 * Creates the linkView element corresponding to the
 * link and adds it to the scene
*/
void DrawingScene::on_drawLink(Link *link){
    if(link->getStart() == link->getEnd()){
        GraphicArcItem *lview = new GraphicArcItem(link);
        addItem(lview);
    }else{
        LinkView *lview = new LinkView(link);
        addItem(lview);
    }
}

void DrawingScene::mousePressEvent(QGraphicsSceneMouseEvent *event){
    if (m_mode == InsertLine){
        m_line = new QGraphicsLineItem(QLineF(event->scenePos(),
                                        event->scenePos()));
        m_line->setPen(QPen(QColor(Qt::black),2));
        addItem(m_line);
    }
    QGraphicsScene::mousePressEvent(event);
}

void DrawingScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event){
    if (m_mode == InsertLine && m_line != 0){
        QLineF newLine(m_line->line().p1(), event->scenePos());
        m_line->setLine(newLine);
    }else{
        QGraphicsScene::mouseMoveEvent(event);
    }
}

void DrawingScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event){
    if(m_line != 0 && m_mode == InsertLine){
        QList<QGraphicsItem *> startItems = items(m_line->line().p1());
        if (startItems.count() && startItems.first() == m_line){
            startItems.removeFirst();
        }
        QList<QGraphicsItem *> endItems = items(m_line->line().p2());
        if (endItems.count() && endItems.first() == m_line){
            endItems.removeFirst();
        }
        removeItem(m_line);
        delete m_line;

        if (startItems.count() > 0 && endItems.count() > 0){
            StateView *first = dynamic_cast<StateView *>(startItems.first());
            StateView *last = dynamic_cast<StateView *>(endItems.first());
            if(first && last){
                if(first != last){
                    emit createLink(first->getState(), last->getState());
                }else{
                    emit createLink(first->getState());
                }
            }
        }
    }
    m_line = 0;
    QGraphicsScene::mouseReleaseEvent(event);
}

А вот некоторые изображения результата:

Заранее благодарю за помощь или ориентацию :) enter image description hereenter image description hereenter image description here

1 Ответ

0 голосов
/ 24 мая 2018

Графика Элементы не должны зависеть друг от друга, как вы делаете в своем коде.Они должны быть автономными, особенно в отношении ограничивающих рамок и рисунка (и, возможно, формы).

Относительное позиционирование достигается посредством отношений родитель-потомок.

Поэтому я предлагаю вам изменить дизайн элемента дуги, чтобы он был независимым от представления состояния, и при необходимости добавьте его в качестве потомка представления состояния,с оценочным смещением.

Ограничивающий прямоугольник - это прямоугольник вокруг позиции элемента, в котором будет происходить весь рисунок (и является основой для тестов попадания).На самом деле не имеет значения, как вы смещаете ограничивающий прямоугольник, но общепринятым является то, что позиция элемента является центром ограничивающего прямоугольника (исключение: QGraphicsPixampItem), например,

void GraphicArcItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *){
    /* setup painter */

    QRectF rectangle = QRectF(-25.0,-25.0,50.0,50.0);
    painter->drawArc(rectangle, startAngle(), spanAngle());
    QRectF rectangle2 = QRectF(-30.0,-30.0,60.0,60.0);
    painter->drawRect(rectangle2);
}

QRectF GraphicArcItem::boundingRect() const{
    QRectF rectangle = QRectF(-30.0,-30.0,60.0,60.0);
    qreal extra = (pen().width() + 50) / 2.0;
    return rectangle
         .normalized()
         .adjusted(-extra, -extra, extra, extra);
}

При добавлении дуги создайте ее какдочерний элемент и смещение при необходимости:

void DrawingScene::on_drawLink(Link *link){
    if(link->getStart() == link->getEnd()){
        GraphicArcItem *lview = new GraphicArcItem(link);
        lview->setParentItem(link->getStart()->getStateView());
        lview->setPos(-37.5,-37.5)
        addItem(lview);
    }else{
        /* ... */
    }
}

В качестве альтернативы, вы можете расширить конструктор дуги, чтобы взять родительский элемент и переслать его в базовый класс (он станет родительским).

Обратите внимание, что я не проверял это, и что координаты могут быть отключены

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...