在自定义绘图场景上绘制圆和圆弧后,我想选择圆弧。 奇怪的是,当我从侧面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);
}
以下是结果的一些图片:
答案 0 :(得分:0)
图形项不应该像在代码中一样依赖于彼此。它们应该是独立的,特别是关于边界框和绘图(可能是形状)。
相对位置是通过亲子关系实现的。
所以我建议你将你的弧项重新设计为独立于状态视图,并在需要时将其添加为状态视图的子项,并使用适当的偏移量。
边界矩形是项目位置周围的矩形,其中所有绘图都将发生(并且是命中测试的基础)。你如何抵消边界矩形并不重要,但惯例是,项目的位置是边界矩形的中心(例外: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{
/* ... */
}
}
或者,您可以扩展arc的构造函数以获取父项并将其转发到基类(它将成为父类)。
请注意,我没有对此进行测试,并且该坐标可能已关闭