2014-06-11 4 views
1

나는 8 개의 핸들러를 사용하여 상호 작용하는 QGraphicsItem 크기를 조정하는 https://github.com/cesarbs/sizegripitem 프로젝트를 포크했습니다. 문제는 내가 메인 QGraphicsItem을 선택 가능하게 설정하면 핸들러를 끌 때 주 QGraphicsItem이 움직이는 것이 아니라 크기 조정, 울부 짖는 소리는 SizeGripItem :: HandleItem에서 부모의 위치를 ​​설정 SizeGripItem.cppQGraphicsItem 대화 형 크기 조정

/* 
* SizeGripItem - A size grip QGraphicsItem for interactive resizing. 
* 
* Copyright (c) 2011 Cesar L. B. Silveira 
* 
* Permission is hereby granted, free of charge, to any person obtaining a 
* copy of this software and associated documentation files (the "Software"), 
* to deal in the Software without restriction, including without limitation 
* the rights to use, copy, modify, merge, publish, distribute, sublicense, 
* and/or sell copies of the Software, and to permit persons to whom the 
* Software is furnished to do so, subject to the following conditions: 
* 
* The above copyright notice and this permission notice shall be included 
* in all copies or substantial portions of the Software. 
* 
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 
* IN THE SOFTWARE. 
*/ 

#include <QBrush> 
#include "SizeGripItem.h" 

SizeGripItem::HandleItem::HandleItem(int positionFlags, SizeGripItem* parent) 
    : QGraphicsRectItem(-4, -4, 8, 8, parent), 
     positionFlags_(positionFlags), 
     parent_(parent) 
{ 
    setBrush(QBrush(Qt::lightGray)); 
    setFlag(ItemIsMovable); 
    setFlag(ItemSendsGeometryChanges); 
} 

int SizeGripItem::HandleItem::positionFlags() const 
{ 
    return positionFlags_; 
} 

QVariant SizeGripItem::HandleItem::itemChange(GraphicsItemChange change, 
               const QVariant &value) 
{ 
    QVariant retVal = value; 

    if (change == ItemPositionChange) 
    { 
     retVal = restrictPosition(value.toPointF()); 
    } 
    else if (change == ItemPositionHasChanged) 
    { 
     QPointF pos = value.toPointF(); 

     switch (positionFlags_) 
     { 
      case TopLeft: 
       parent_->setTopLeft(pos); 
       break; 
      case Top: 
       parent_->setTop(pos.y()); 
       break; 
      case TopRight: 
       parent_->setTopRight(pos); 
       break; 
      case Right: 
       parent_->setRight(pos.x()); 
       break; 
      case BottomRight: 
       parent_->setBottomRight(pos); 
       break; 
      case Bottom: 
       parent_->setBottom(pos.y()); 
       break; 
      case BottomLeft: 
       parent_->setBottomLeft(pos); 
       break; 
      case Left: 
       parent_->setLeft(pos.x()); 
       break; 
     } 
    } 

    return retVal; 
} 

QPointF SizeGripItem::HandleItem::restrictPosition(const QPointF& newPos) 
{ 
    QPointF retVal = pos(); 

    if (positionFlags_ & Top || positionFlags_ & Bottom) 
     retVal.setY(newPos.y()); 

    if (positionFlags_ & Left || positionFlags_ & Right) 
     retVal.setX(newPos.x()); 

    if (positionFlags_ & Top && retVal.y() > parent_->rect_.bottom()) 
     retVal.setY(parent_->rect_.bottom()); 
    else if (positionFlags_ & Bottom && retVal.y() < parent_->rect_.top()) 
     retVal.setY(parent_->rect_.top()); 

    if (positionFlags_ & Left && retVal.x() > parent_->rect_.right()) 
     retVal.setX(parent_->rect_.right()); 
    else if (positionFlags_ & Right && retVal.x() < parent_->rect_.left()) 
     retVal.setX(parent_->rect_.left()); 

    return retVal; 
} 

SizeGripItem::SizeGripItem(Resizer* resizer, QGraphicsItem* parent) 
    : QGraphicsItem(parent), 
     resizer_(resizer) 
{ 
    if (parentItem()) 
     rect_ = parentItem()->boundingRect(); 

    handleItems_.append(new HandleItem(TopLeft, this)); 
    handleItems_.append(new HandleItem(Top, this)); 
    handleItems_.append(new HandleItem(TopRight, this)); 
    handleItems_.append(new HandleItem(Right, this)); 
    handleItems_.append(new HandleItem(BottomRight, this)); 
    handleItems_.append(new HandleItem(Bottom, this)); 
    handleItems_.append(new HandleItem(BottomLeft, this)); 
    handleItems_.append(new HandleItem(Left, this)); 
    updateHandleItemPositions(); 
} 

SizeGripItem::~SizeGripItem() 
{ 
    if (resizer_) 
     delete resizer_; 
} 

QRectF SizeGripItem::boundingRect() const 
{ 
    return rect_; 
} 

void SizeGripItem::paint(QPainter* painter, 
         const QStyleOptionGraphicsItem* option, 
         QWidget* widget) 
{ 
} 

#define IMPL_SET_FN(TYPE, POS)     \ 
    void SizeGripItem::set ## POS (TYPE v)  \ 
    {           \ 
     rect_.set ## POS (v);     \ 
     doResize();        \ 
    } 

IMPL_SET_FN(qreal, Top) 
IMPL_SET_FN(qreal, Right) 
IMPL_SET_FN(qreal, Bottom) 
IMPL_SET_FN(qreal, Left) 
IMPL_SET_FN(const QPointF&, TopLeft) 
IMPL_SET_FN(const QPointF&, TopRight) 
IMPL_SET_FN(const QPointF&, BottomRight) 
IMPL_SET_FN(const QPointF&, BottomLeft) 

void SizeGripItem::doResize() 
{ 
    if (resizer_) 
    { 
     (*resizer_)(parentItem(), rect_); 
     updateHandleItemPositions(); 
    } 
} 

void SizeGripItem::updateHandleItemPositions() 
{ 
    foreach (HandleItem* item, handleItems_) 
    { 
     item->setFlag(ItemSendsGeometryChanges, false); 

     switch (item->positionFlags()) 
     { 
      case TopLeft: 
       item->setPos(rect_.topLeft()); 
       break; 
      case Top: 
       item->setPos(rect_.left() + rect_.width()/2 - 1, 
          rect_.top()); 
       break; 
      case TopRight: 
       item->setPos(rect_.topRight()); 
       break; 
      case Right: 
       item->setPos(rect_.right(), 
          rect_.top() + rect_.height()/2 - 1); 
       break; 
      case BottomRight: 
       item->setPos(rect_.bottomRight()); 
       break; 
      case Bottom: 
       item->setPos(rect_.left() + rect_.width()/2 - 1, 
          rect_.bottom()); 
       break; 
      case BottomLeft: 
       item->setPos(rect_.bottomLeft()); 
       break; 
      case Left: 
       item->setPos(rect_.left(), 
          rect_.top() + rect_.height()/2 - 1); 
       break; 
     } 

     item->setFlag(ItemSendsGeometryChanges, true); 
    } 
} 
+0

주 GraphicsItem의 ItemIsMoveable 플래그를 제거하는 것은 어떻습니까? – TheDarkKnight

+0

Ok는 부분적으로 작동합니다. 주 GraphicsItem을 선택하면 핸들러가 크기를 조정하지만, 이제는 Moveable이 아니기 때문에 움직일 수 없습니다. 그러나 나는 마우스 보도/릴리스/이동 이벤트와 함께 움직일 수 있다고 생각합니다. –

답변

2

에 대한 소스입니다 :: itemChange 여기에 이상한 보인다. itemChange 함수는 아마도 상위 항목의 위치를 ​​설정하면 안된다고 생각합니다. 좌표 만 조정하고 값을 반환해야합니다.

과거에는 조금 다른 방식으로 시도했습니다. 먼저, HandleItem의 ItemSendGeometryChanges 플래그를 제거하십시오.

그런 다음 HandleItem에 대해 mousePressEvent, mouseMoveEvent 및 mouseReleaseEvent를 구현하십시오. mouseMoveEvent에서 핸들이 이동 될 때 부모의 경계 사각형을 업데이트합니다.

이렇게하면 주 GraphicsItem과 해당 핸들을 모두 선택 가능하고 움직일 수 있도록 설정할 수 있습니다.

관련 문제