맞춤형 MouseDraw
은 QGraphicsItem
에서 파생 된 클래스가 필요하지 않습니다. 모든 것을 정확하게 처리하는 QGraphicsPathItem
이 있습니다.
생성되는 항목 내에서 마우스 상호 작용을 처리하는 것은 개념 상 올바르지 않습니다. 큰 경계 사각형은 작동에 필요한 해킹이지만 잘못된 방법입니다. 항목을 마우스와 상호 작용하지 않으려는 경우 장면을 마우스와 상호 작용하여 즉시 작성해야합니다. 기존 항목을 편집하는 경우에만 마우스를 사용하고 싶지만 편집중인 항목에 수정 된 상호 작용을 처리하기 위해 별도의 편집기 항목을 추가하는 것이 좋습니다.
마우스 오른쪽 버튼으로 창을 클릭하면 그림을 지우는 작업과 함께 상황에 맞는 메뉴가 나타납니다. 후속 경로가 이전 경로에 조인되는지 여부를 전환 할 수도 있습니다. 이 코드는 Qt 4.8.5 및 5.2에서 테스트되었습니다.
장면이 뷰보다 작 으면 뷰는 가운데에 놓기를 원합니다 (alignment
속성 사용). EmptyItem
은 장면이보기보다 작을 때 (장면이 "비어있는 경우"포함)보기 내의 장면 위치를 제한하기 위해이 "기능"의 일시적인 해결책으로 사용됩니다.
코드는 각 분리 경로에 대해 별도의 항목을 만듭니다. QGraphicsScene
은 일반적으로 중첩되지 않는 여러 항목에 대해 가장 잘 수행합니다.물론 하나의 항목 만 남기고 각 마우스 누르기마다 새로운 세그먼트를 계속 추가 할 수는 있습니다.하지만 결국에는 성능에 영향을 미칩니다. 특히 장면을 확대 할 때 성능이 더 좋아질 것으로 예상되는 경우 가 표시됩니다.
// https://github.com/KubaO/stackoverflown/tree/master/questions/gscene-paint-20632209
#include <QtGui>
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
#include <QtWidgets>
#endif
class EmptyItem : public QGraphicsItem
{
public:
EmptyItem(QGraphicsItem * parent = nullptr) : QGraphicsItem{parent} {}
QRectF boundingRect() const override { return {0, 0, 1, 1}; }
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) override {}
};
class Scene : public QGraphicsScene
{
Q_OBJECT
Q_PROPERTY(bool joinFigures READ joinFigures WRITE setJoinFigures)
bool m_joinFigures = false;
QGraphicsPathItem * m_item = nullptr;
QPainterPath m_path;
void newItem() {
addItem(m_item = new QGraphicsPathItem);
m_item->setPen(QPen{{qrand() % 256, qrand() % 256, qrand() % 256}});
m_path = QPainterPath{}; // using std::swap; swap(m_path, QPainterPath());
}
void newPoint(const QPointF& pt) {
if (! m_item) {
newItem();
m_path.moveTo(pt);
} else {
m_path.lineTo(pt);
m_item->setPath(m_path);
}
}
void mousePressEvent(QGraphicsSceneMouseEvent * ev) override {
if (ev->buttons() != Qt::LeftButton) return;
if (! m_joinFigures) m_item = nullptr;
newPoint(ev->scenePos());
}
void mouseMoveEvent(QGraphicsSceneMouseEvent *ev) override {
if (ev->buttons() != Qt::LeftButton) return;
newPoint(ev->scenePos());
}
void mouseReleaseEvent(QGraphicsSceneMouseEvent *) override {
if (! m_path.isEmpty()) return;
delete m_item; // Empty items are useless
m_item = nullptr;
}
public:
Scene(QObject *parent = nullptr) : QGraphicsScene{parent}
{
addItem(new EmptyItem{});
}
Q_SLOT void setJoinFigures(bool j) { m_joinFigures = j; }
bool joinFigures() const { return m_joinFigures; }
};
class Window : public QWidget
{
Q_OBJECT
QGridLayout m_layout{this};
QGraphicsView m_view;
QCheckBox m_join{"Join Figures (toggle with Spacebar)"};
QAction m_toggleJoin{this};
public:
Window(QWidget * parent = 0) : QWidget{parent}
{
m_layout.addWidget(&m_view);
m_layout.addWidget(&m_join);
m_view.setAlignment(Qt::AlignLeft | Qt::AlignTop);
m_toggleJoin.setShortcut(QKeySequence(Qt::Key_Space));
connect(&m_toggleJoin, SIGNAL(triggered()), &m_join, SLOT(toggle()));
addAction(&m_toggleJoin);
m_view.addAction(new QAction{"Clear", this});
m_view.setContextMenuPolicy(Qt::ActionsContextMenu);
connect(m_view.actions().at(0), SIGNAL(triggered()), SLOT(newScene()));
// Create a new scene instead of clear()-ing it, since scenes can only grow their
// sceneRect().
newScene();
}
Q_SLOT void newScene() {
if (m_view.scene()) m_view.scene()->deleteLater();
m_view.setScene(new Scene);
m_view.scene()->connect(&m_join, SIGNAL(toggled(bool)), SLOT(setJoinFigures(bool)));
}
};
int main(int argc, char *argv[])
{
QApplication a{argc, argv};
Window w;
w.show();
return a.exec();
}
#include "main.moc"
당신은 다시 정의해야한다는'QGraphicsScene' 또는'QGraphicsView' 마우스 이벤트가 아니라 부모 – dvvrd
은 또한,'setMouseTracking은 (참)'생성자에 한 번 호출 할 필요가 사람을 widget's. 또한 마우스 버튼을 누르지 않고 마우스 움직임을 추적하려는 경우에만 필요합니다. –
아니, 내가 원하는 연결을 내 문제는 연결하지만,이 문제를 해결하는 방법을 모릅니다 .. 모든 도면을 한 이동으로 만들 필요가있다, 문제는 예를 들어 사각형을 그릴 때 처음부터 왼쪽에서 오른쪽으로 그립니다. , 오른쪽에서 위로, 그리고 나서 마우스 단추를 놓고 왼쪽 하단에서 다시 한 번 클릭하여 줄을 그리려면 예를 들어, 오른쪽 상단에서 왼쪽 아래로도 그려집니다. – user3110781