2013-12-17 4 views
3

This is what i mean that happens, first tried a circle, then on the right a square Я хочу нарисовать различные произвольные цифры. Рисование начинается, когда мышь нажата в графическом представлении и заканчивается, когда вы нажимаете на мышь. Однако при запуске в другой точке графического вида для создания нового чертежа или продолжения на предыдущем чертеже линия выводится из последней координаты мыши первого чертежа в первую координату второго чертежа. Чертежи необязательно должны быть разных чертежей, но также могут быть просто корректировки чертежа. Это мой код.Qt: линия соединяет 2 отдельных чертежа

#include "mousedraw.h" 
#include <QDebug> 

MouseDraw::MouseDraw() 
{ 
    setFlag(ItemIsMovable); 
} 

QRectF MouseDraw::boundingRect() const 
{ 
    return QRectF(0,0,300,300); 
} 

void MouseDraw::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,  QWidget *widget) 
{ 
    QPainterPath path; 
    path.addPolygon(polyPoints2); 
    painter->setPen(QPen(QColor(qrand() % 256, qrand() % 256, qrand() % 256),3)); 
    painter->drawPath(path); 
} 

void MouseDraw::mouseMoveEvent(QGraphicsSceneMouseEvent *event) 
{ 
    QPointF point = event->pos(); 
    if (boundingRect().contains(point)) { 
     array1 = point.x(); 
     array2 = point.y(); 
     polyPoints2 << QPoint(array1,array2); 
     update(); 
    } 
} 
+1

Вы должны переопределить '' QGraphicsScene' или события мыши QGraphicsView', а не родитель для виджета из них – dvvrd

+1

Кроме того, 'setMouseTracking (истина)' должна вызываться один раз в конструкторе. И это необходимо, только если вы хотите отслеживать движения мыши, не нажимая кнопки мыши. –

+0

Нет, я не хочу подключения, это моя проблема, но я не знаю, как это решить. Все рисунки нужно сделать за один ход, проблема в том, что, например, рисование квадрата, рисование сначала слева направо , затем справа на верх, и если вы затем отпустите кнопку мыши и щелкните ее еще раз в левом нижнем углу, чтобы нарисовать линию, например, линия также нарисована справа внизу слева. – user3110781

ответ

1

Имеет пользовательский класс MouseDraw, полученный от QGraphicsItem. Существует QGraphicsPathItem, который обрабатывает все это для вас, правильно.

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

Кликните на окне правой кнопкой мыши, чтобы получить контекстное меню с действием, чтобы очистить изображение. Вы также можете переключать, будет ли следующий путь присоединен к предыдущему. Этот код тестируется как с Qt 4.8.5, так и с 5.2.

Когда сцена меньше, чем на вид, точка зрения настаивает на ее центрировании (с использованием свойства alignment). В качестве обхода этой «функции» используется EmptyItem, чтобы ограничить местоположение сцены в представлении, когда сцена меньше, чем вид (в том числе, когда сцена «пуста»).

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

screenshot

// 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" 
+0

Я использовал другой подход, который также работает, но это не позволяет рисовать отдельные цифры, не подключая их. Я также пробовал ваш подход, но я не могу заставить его работать, похоже, вы можете нарисовать несколько firgures без их подключения. Я также не могу изменить цвет своего пера. – user3110781

+0

У меня есть еще один вопрос об этом, как это работает с кнопками? Обычно я иду в дизайн и просто перетаскиваю кнопки, а затем соединяю их. Но с этой настройкой, которая, похоже, не работает? – user3110781

+0

@ user3110781: Я не знаю, что вы имеете в виду. Вы имеете в виду, как интегрировать «окно» в виджет/диалог, созданный как файл .ui? –

0

Создать класс, унаследованный от QGraphicsItem или QGraphicsObject, если вы хотите, сигналы и слоты.

Храните QPainterPath в качестве члена класса. Когда вы обнаружите нажатую кнопку мыши, вызовите функцию moveTo() пути живописца, указав координату. При получении событий перемещения мыши вызовите функцию lineTo() линии живописца с координатами.

Перегружает функцию boundingRect, чтобы возвращать прямой путь живописца, а также перегружать функцию shape(), чтобы вернуть правильную форму для столкновения.

Наконец, в функции краски класса, нарисуйте путь художника. Вот скелетный класс, который вы можете использовать.

class MouseDraw : public QGraphicsItem 
{ 
    public: 
     QRectF boundingRect() const 
     { 
      return m_painterpath.boundingRect(); 
     } 

     QPainterPath shape() const 
     { 
      return m_painterpath; 
     } 

     void QGraphicsItem::paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) 
     { 
      // setup pen and brush 
      // .... 
      // draw the path 

      painter->drawPath(m_painterpath); 
     } 

    private: 
     QPainterPath m_painterpath; 
}; 

Обрабатывать события mousePress, MouseMove и mouseRelease добавить необходимые точки на пути художника, а затем создать объект класса и добавить его на сцену: -

MouseDraw* mouseDraw = new MouseDraw; 
scene->addItem(mouseDraw); 

Обратите внимание, что объект добавляется только один раз к сцене и создается динамически.

Смежные вопросы