Difference between revisions of "Qt/Utilities/HandleItem"
From ProgrammingExamples
< Qt
Daviddoria (Talk | contribs) (→form.cpp) |
Daviddoria (Talk | contribs) (→HandleItem.cpp) |
||
Line 124: | Line 124: | ||
#include <QPointF> | #include <QPointF> | ||
+ | #include <cmath> | ||
#include <iostream> | #include <iostream> | ||
Line 153: | Line 154: | ||
case RightHandle: | case RightHandle: | ||
points << rect.center()+QPointF(3,0) << rect.center()+QPointF(-3,-5) << rect.center()+QPointF(-3,5); | points << rect.center()+QPointF(3,0) << rect.center()+QPointF(-3,-5) << rect.center()+QPointF(-3,5); | ||
+ | paint->drawConvexPolygon( QPolygonF(points) ); | ||
+ | break; | ||
+ | case LeftHandle: | ||
+ | points << rect.center()+QPointF(-3,0) << rect.center()+QPointF(3,-5) << rect.center()+QPointF(3,5); | ||
+ | paint->drawConvexPolygon( QPolygonF(points) ); | ||
+ | break; | ||
+ | case TopHandle: | ||
+ | points << rect.center()+QPointF(0,-3) << rect.center()+QPointF(-5,3) << rect.center()+QPointF(5,3); | ||
+ | paint->drawConvexPolygon( QPolygonF(points) ); | ||
+ | break; | ||
+ | case BottomHandle: | ||
+ | points << rect.center()+QPointF(0,3) << rect.center()+QPointF(-5,-3) << rect.center()+QPointF(5,-3); | ||
paint->drawConvexPolygon( QPolygonF(points) ); | paint->drawConvexPolygon( QPolygonF(points) ); | ||
break; | break; | ||
Line 161: | Line 174: | ||
QRectF HandleItem::boundingRect() const | QRectF HandleItem::boundingRect() const | ||
{ | { | ||
− | |||
− | |||
switch( m_role ) | switch( m_role ) | ||
{ | { | ||
+ | case LeftHandle: | ||
+ | { | ||
+ | QPointF point(m_item->boundingRect().left() - pos().x(), m_item->boundingRect().top() + m_item->boundingRect().height()/2); | ||
+ | return QRectF( point-QPointF(3, 5), QSize( 6, 10 ) ); | ||
+ | } | ||
case RightHandle: | case RightHandle: | ||
− | point | + | { |
+ | QPointF point(m_item->boundingRect().right() - pos().x(), m_item->boundingRect().top() + m_item->boundingRect().height()/2); | ||
return QRectF( point-QPointF(3, 5), QSize( 6, 10 ) ); | return QRectF( point-QPointF(3, 5), QSize( 6, 10 ) ); | ||
+ | } | ||
+ | case TopHandle: | ||
+ | { | ||
+ | QPointF point(m_item->boundingRect().left() + m_item->boundingRect().width()/2, m_item->boundingRect().top() - pos().y()); | ||
+ | return QRectF( point-QPointF(5, 3), QSize( 10, 6 ) ); | ||
+ | } | ||
+ | case BottomHandle: | ||
+ | { | ||
+ | QPointF point(m_item->boundingRect().left() + m_item->boundingRect().width()/2, m_item->boundingRect().bottom() - pos().y()); | ||
+ | return QRectF( point-QPointF(5, 3), QSize( 10, 6 ) ); | ||
+ | } | ||
} | } | ||
Line 184: | Line 212: | ||
switch( m_role ) | switch( m_role ) | ||
{ | { | ||
+ | case LeftHandle: | ||
+ | { | ||
+ | // Prevent the rectangle from collapsing. | ||
+ | //if( fabs(movement.x()) <= 5 ) | ||
+ | if(m_item->rect().width() < 5) | ||
+ | { | ||
+ | std::cout << "too small! " << std::endl; | ||
+ | return QGraphicsItem::itemChange( change, newData ); | ||
+ | } | ||
+ | |||
+ | // Snap the movement to the X direction | ||
+ | newData.setY(0); | ||
+ | |||
+ | movement = newData - pos(); | ||
+ | // Resize the rectangle | ||
+ | newRect.setLeft(m_item->rect().left() + movement.x()); | ||
+ | |||
+ | m_item->setRect(newRect); | ||
+ | |||
+ | break; | ||
+ | } | ||
case RightHandle: | case RightHandle: | ||
− | + | { | |
// Prevent the rectangle from collapsing. | // Prevent the rectangle from collapsing. | ||
− | if( m_item-> | + | //if( fabs(movement.x()) <= 5 ) |
+ | //if(m_item->rect().width() < 5) | ||
+ | if(m_item->rect().width() + movement.x() < 5) | ||
{ | { | ||
std::cout << "too small! " << std::endl; | std::cout << "too small! " << std::endl; | ||
Line 197: | Line 248: | ||
movement = newData - pos(); | movement = newData - pos(); | ||
− | |||
− | |||
− | |||
− | |||
− | |||
// Resize the rectangle | // Resize the rectangle | ||
− | |||
newRect.setRight(m_item->rect().right() + movement.x()); | newRect.setRight(m_item->rect().right() + movement.x()); | ||
− | + | ||
m_item->setRect(newRect); | m_item->setRect(newRect); | ||
− | + | ||
+ | break; | ||
+ | } | ||
+ | case TopHandle: | ||
+ | { | ||
+ | // Prevent the rectangle from collapsing. | ||
+ | //if( fabs(movement.x()) <= 5 ) | ||
+ | if(m_item->rect().height() < 5) | ||
+ | { | ||
+ | std::cout << "too small! " << std::endl; | ||
+ | return QGraphicsItem::itemChange( change, newData ); | ||
+ | } | ||
+ | |||
+ | // Snap the movement to the Y direction | ||
+ | newData.setX(0); | ||
+ | |||
+ | movement = newData - pos(); | ||
+ | // Resize the rectangle | ||
+ | newRect.setTop(m_item->rect().top() + movement.y()); | ||
+ | |||
+ | m_item->setRect(newRect); | ||
+ | |||
+ | break; | ||
+ | } | ||
+ | case BottomHandle: | ||
+ | { | ||
+ | // Prevent the rectangle from collapsing. | ||
+ | //if( fabs(movement.x()) <= 5 ) | ||
+ | if(m_item->rect().height() < 5) | ||
+ | { | ||
+ | std::cout << "too small! " << std::endl; | ||
+ | return QGraphicsItem::itemChange( change, newData ); | ||
+ | } | ||
+ | |||
+ | // Snap the movement to the Y direction | ||
+ | newData.setX(0); | ||
+ | |||
+ | movement = newData - pos(); | ||
+ | // Resize the rectangle | ||
+ | newRect.setBottom(m_item->rect().bottom() + movement.y()); | ||
+ | |||
+ | m_item->setRect(newRect); | ||
+ | |||
break; | break; | ||
+ | } | ||
} // end switch | } // end switch | ||
Line 228: | Line 316: | ||
QGraphicsItem::mouseReleaseEvent( event ); | QGraphicsItem::mouseReleaseEvent( event ); | ||
} | } | ||
+ | |||
</source> | </source> |
Latest revision as of 17:20, 19 November 2011
Contents
HandleItem.cpp
#include <QApplication> #include "form.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); Form form; form.show(); return app.exec(); }
form.h
#ifndef FORM_H #define FORM_H #include "ui_form.h" class Form : public QWidget, private Ui::Form { Q_OBJECT public slots: public: Form(QWidget *parent = 0); }; #endif
form.cpp
#include <QtGui> #include "form.h" #include "HandleItem.h" #include <iostream> Form::Form(QWidget *parent) : QWidget(parent) { setupUi(this); QGraphicsScene* scene = new QGraphicsScene( 0, 0, 200, 200 ); QGraphicsRectItem *rectItem = new QGraphicsRectItem( QRect( 10, 10, 50, 100 ), 0, scene ); // The center handle must know about all of the other handles so it can translate them with the object HandleItem *topHandle = new HandleItem( rectItem, scene, Qt::red, HandleItem::TopHandle ); HandleItem *rightHandle = new HandleItem( rectItem, scene, Qt::red, HandleItem::RightHandle ); HandleItem *leftHandle = new HandleItem( rectItem, scene, Qt::red, HandleItem::LeftHandle ); HandleItem *bottomHandle = new HandleItem( rectItem, scene, Qt::red, HandleItem::BottomHandle ); HandleItem *centerHandle = new HandleItem( rectItem, scene, Qt::red, HandleItem::CenterHandle, QList<HandleItem*>() << topHandle << rightHandle << leftHandle << bottomHandle ); this->graphicsView->setScene( scene ); }
HandleItem.h
#ifndef HANDLEITEM_H #define HANDLEITEM_H #include <QGraphicsItem> #include <QGraphicsRectItem> class HandleItem; class HandleItem : public QGraphicsItem { public: enum HandleRole { CenterHandle, RightHandle, TopHandle, LeftHandle, BottomHandle }; HandleItem( QGraphicsRectItem *item, QGraphicsScene *scene, QColor color, HandleRole role = CenterHandle, QList<HandleItem*> handles = QList<HandleItem*>() ); void paint( QPainter *paint, const QStyleOptionGraphicsItem *option, QWidget *widget ); QRectF boundingRect() const; protected: void mousePressEvent( QGraphicsSceneMouseEvent *event ); void mouseReleaseEvent( QGraphicsSceneMouseEvent *event ); QVariant itemChange( GraphicsItemChange change, const QVariant &data ); private: QGraphicsRectItem *m_item; HandleRole m_role; QColor m_color; QList<HandleItem*> m_handles; bool m_pressed; }; #endif // HANDLEITEM_H
HandleItem.cpp
#include "HandleItem.h" #include <QPainter> #include <QPointF> #include <cmath> #include <iostream> HandleItem::HandleItem( QGraphicsRectItem *item, QGraphicsScene *scene, QColor color, HandleItem::HandleRole role, QList<HandleItem*> handles ) : QGraphicsItem( 0, scene ) { m_role = role; m_color = color; m_item = item; m_handles = handles; m_pressed = false; setZValue( 100 ); setFlag( ItemIsMovable ); setFlag(ItemSendsGeometryChanges); } void HandleItem::paint( QPainter *paint, const QStyleOptionGraphicsItem *option, QWidget *widget ) { paint->setPen( m_color ); paint->setBrush( m_color ); QRectF rect = boundingRect(); QVector<QPointF> points; switch( m_role ) { case RightHandle: points << rect.center()+QPointF(3,0) << rect.center()+QPointF(-3,-5) << rect.center()+QPointF(-3,5); paint->drawConvexPolygon( QPolygonF(points) ); break; case LeftHandle: points << rect.center()+QPointF(-3,0) << rect.center()+QPointF(3,-5) << rect.center()+QPointF(3,5); paint->drawConvexPolygon( QPolygonF(points) ); break; case TopHandle: points << rect.center()+QPointF(0,-3) << rect.center()+QPointF(-5,3) << rect.center()+QPointF(5,3); paint->drawConvexPolygon( QPolygonF(points) ); break; case BottomHandle: points << rect.center()+QPointF(0,3) << rect.center()+QPointF(-5,-3) << rect.center()+QPointF(5,-3); paint->drawConvexPolygon( QPolygonF(points) ); break; } } QRectF HandleItem::boundingRect() const { switch( m_role ) { case LeftHandle: { QPointF point(m_item->boundingRect().left() - pos().x(), m_item->boundingRect().top() + m_item->boundingRect().height()/2); return QRectF( point-QPointF(3, 5), QSize( 6, 10 ) ); } case RightHandle: { QPointF point(m_item->boundingRect().right() - pos().x(), m_item->boundingRect().top() + m_item->boundingRect().height()/2); return QRectF( point-QPointF(3, 5), QSize( 6, 10 ) ); } case TopHandle: { QPointF point(m_item->boundingRect().left() + m_item->boundingRect().width()/2, m_item->boundingRect().top() - pos().y()); return QRectF( point-QPointF(5, 3), QSize( 10, 6 ) ); } case BottomHandle: { QPointF point(m_item->boundingRect().left() + m_item->boundingRect().width()/2, m_item->boundingRect().bottom() - pos().y()); return QRectF( point-QPointF(5, 3), QSize( 10, 6 ) ); } } return QRectF(); } QVariant HandleItem::itemChange( GraphicsItemChange change, const QVariant &data ) { if( change == ItemPositionChange && m_pressed ) { QPointF movement; QPointF newData = data.toPointF(); QRectF newRect = m_item->rect(); switch( m_role ) { case LeftHandle: { // Prevent the rectangle from collapsing. //if( fabs(movement.x()) <= 5 ) if(m_item->rect().width() < 5) { std::cout << "too small! " << std::endl; return QGraphicsItem::itemChange( change, newData ); } // Snap the movement to the X direction newData.setY(0); movement = newData - pos(); // Resize the rectangle newRect.setLeft(m_item->rect().left() + movement.x()); m_item->setRect(newRect); break; } case RightHandle: { // Prevent the rectangle from collapsing. //if( fabs(movement.x()) <= 5 ) //if(m_item->rect().width() < 5) if(m_item->rect().width() + movement.x() < 5) { std::cout << "too small! " << std::endl; return QGraphicsItem::itemChange( change, newData ); } // Snap the movement to the X direction newData.setY(0); movement = newData - pos(); // Resize the rectangle newRect.setRight(m_item->rect().right() + movement.x()); m_item->setRect(newRect); break; } case TopHandle: { // Prevent the rectangle from collapsing. //if( fabs(movement.x()) <= 5 ) if(m_item->rect().height() < 5) { std::cout << "too small! " << std::endl; return QGraphicsItem::itemChange( change, newData ); } // Snap the movement to the Y direction newData.setX(0); movement = newData - pos(); // Resize the rectangle newRect.setTop(m_item->rect().top() + movement.y()); m_item->setRect(newRect); break; } case BottomHandle: { // Prevent the rectangle from collapsing. //if( fabs(movement.x()) <= 5 ) if(m_item->rect().height() < 5) { std::cout << "too small! " << std::endl; return QGraphicsItem::itemChange( change, newData ); } // Snap the movement to the Y direction newData.setX(0); movement = newData - pos(); // Resize the rectangle newRect.setBottom(m_item->rect().bottom() + movement.y()); m_item->setRect(newRect); break; } } // end switch return QGraphicsItem::itemChange( change, newData); } // end if pressed return QGraphicsItem::itemChange( change, data ); } void HandleItem::mousePressEvent( QGraphicsSceneMouseEvent *event ) { m_pressed = true; QGraphicsItem::mousePressEvent( event ); } void HandleItem::mouseReleaseEvent( QGraphicsSceneMouseEvent *event ) { m_pressed = false; QGraphicsItem::mouseReleaseEvent( event ); }
form.ui
<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>Form</class> <widget class="QWidget" name="Form"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>400</width> <height>300</height> </rect> </property> <property name="windowTitle"> <string>Form</string> </property> <widget class="QGraphicsView" name="graphicsView"> <property name="geometry"> <rect> <x>80</x> <y>50</y> <width>256</width> <height>192</height> </rect> </property> </widget> </widget> <resources/> <connections/> </ui>
CMakeLists.txt
cmake_minimum_required(VERSION 2.6) PROJECT(HandleItem) FIND_PACKAGE(Qt4 REQUIRED) INCLUDE(${QT_USE_FILE}) QT4_WRAP_UI(UISrcs form.ui) QT4_WRAP_CPP(MOCSrcs form.h) include_directories(${include_directories} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) ADD_EXECUTABLE(HandleItem main.cpp HandleItem.cpp form.cpp ${MOCSrcs} ${UISrcs}) TARGET_LINK_LIBRARIES(HandleItem ${QT_LIBRARIES})