Rysowanie na graficznej scenie Qt

0

Witam

Mam problem ze znalezieniem jakichkolwiek informacji na ten temat.

A mianowicie rysowanie (tak jak w Paint np. ołówkiem) na graficznej scenie QGraphicsScene (jeśli się da).

Całość nie musi być jakaś zaawansowana wystarczy 1 kolor i grubość pisaka 1-2 pixele.

Po rysowaniu chciałbym dalej dodawać obiekty do sceny itp. i co najważniejsze potrzebna mi na koniec tablica tej sceny (aby wiedzieć gdzie jest puste i zamalowane).

Będę wdzięczny za pomoc. Pozdrawiam.

0

albo rysujesz na QPixmap i rysujesz ją za pomocą QGraphicsPixmapItem, albo zapamiętujesz ścieżkę rysowania w QPolygonF i rysujesz za pomocą QGraphicsPolygonItem

0

MarekR22 dzięki za pomoc ale dalej nie wiem jak dokładnie rysować na tej scenie, chodzi mi o to aby użytkownik pokreślił myszką jakieś linie na scenie i to co namalował zostało na tej scenie :) Dokładnie taki paint tylko że z jedną opcją - ołówka:)

Rozumiem że te klasy mogą się przydać ale nie widzę tam samego rysowania np. myszką i nie wiem jak to rozwiązać...

0

Dziedziczysz po QGraphicsWidget (wypełniasz nim cały obszar rysowania) robisz override dla:

  • virtual void mousePressEvent ( QGraphicsSceneMouseEvent * event ) - tu tworzysz nowy obiekt QGraphicsPolygonItem oraz QPolygonF
  • virtual void mouseMoveEvent ( QGraphicsSceneMouseEvent * event ) - tu aktualizujesz QPolygonF
  • virtual void mouseReleaseEvent ( QGraphicsSceneMouseEvent * event ) - tu aktualizujesz QPolygonF
    Nie zapomnij ustawić odpowiednich flag (patrz konstruktor i dokumentacja), potem patrz dokumentacja, patrz dokumentacja, patrz dokumentacja, patrz dokumentacja, ....
0

Dzięki, wygląda sensownie ale wiem że będzie dosyć skomplikowane. Biorę się za robotę, będę pisał jeszcze jak coś :)

0

Ehh mam problem już na starcie

nie wiem jak się odwołać do eventu aby pobrać aktualne współrzędne

na razie klasa wygląda tak :

class MyWidget : public QGraphicsWidget
{
    Q_OBJECT

    QGraphicsPolygonItem *item;
    QPolygonF            *polygon;
    //QGraphicsScene       *scene;

public:
    explicit MyWidget(QGraphicsWidget *parent = 0);

    virtual void mousePressEvent (QGraphicsSceneMouseEvent * event);
    virtual void mouseMoveEvent (QGraphicsSceneMouseEvent * event);
    virtual void mouseReleaseEvent (QGraphicsSceneMouseEvent * event);

    //void setScene(QGraphicsScene *s);
    
signals:
    
public slots:
    
};

i dalej

void MyWidget::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    QGraphicsWidget::mouseMoveEvent(event);
    QPointF point;

    //event->         tutaj
}

pod event-> nic się nie pokazuje...

Kiedyś robiłem coś podobnego z QGraphicsItem i tam dawało się flagę setFlag(ItemIsSelectable), nie wiem jak jest tutaj.

0

Powyższy post nie aktualny :) ale zatrzymałem się i nie wiem czy dobrze robię i co dalej...sama klasa MyWidget tak jak w poście wyżej...

void MyWidget::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    QPen pen(Qt::black);
    QBrush brush(Qt::black,Qt::SolidPattern);
    item = new QGraphicsPolygonItem(0,scene);
    item->setPen(pen);
    item->setBrush(brush);
    polygon = new QPolygonF(0);
    QGraphicsWidget::mousePressEvent(event);
}

void MyWidget::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    QGraphicsWidget::mouseReleaseEvent(event);
    QPointF point;
    point  = event->pos();
    polygon->push_back(point);

    for (int i = 0; i < polygon->size(); i++)
    {
        item->setPolygon(polygon[i]);
    }
}

void MyWidget::setScene(QGraphicsScene *s)
{
    scene = s;
}

void MyWidget::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    QGraphicsWidget::mouseMoveEvent(event);
    QPointF point;
    point  = event->pos();
    polygon->push_back(point);
}
0

źle, i to z wielu powodów.

void MyWidget::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    QGraphicsWidget::mousePressEvent(event);
    QPen pen(Qt::black);
    item = new QGraphicsPolygonItem(this);
    item->setPen(pen);
    item->setBrush(QBrush());  //chcesz linie bez wypełnienia wielokąta, wiec Qt::NoBrush
    // polygon = new QPolygonF(0);  // zmień na pole QPolygonF polygon;
    polygon.clear();
    polygon.append(event->pos());
    item->setPolygon(polygon);
    event->accept();
}
 
void MyWidget::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    QGraphicsWidget::mouseReleaseEvent(event);
    polygon.append(event->pos());
    item->setPolygon(polygon);
}
 
// void MyWidget::setScene(QGraphicsScene *s) // totalnie zbędne
 
void MyWidget::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    QGraphicsWidget::mouseMoveEvent(event);
    polygon.append(event->pos());
    item->setPolygon(polygon);
    item = 0; // tu nie ma wycieku pamięci
}

można uzupełnić o pomijanie niektórych punktów, jeśli dystans jest mały.

0

Jeśli nie możemy ustawić na sztywno sceny to rozumiem że QGraphicsWidget dodajemy tak ?

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    scene = new QGraphicsScene(0,0,500,500);
    view  = new QGraphicsView(scene,ui->graphicsView);
    
    graphics_widget = new MyWidget();
    scene->addItem(graphics_widget);
}

A item = 0; powinien być w mouseReleaseEvent ? bo inaczej program się krzaczy...

Teraz problem z liniami bo na początku powstają dwie linie, pierwsza malowana - ta jest dobrze i druga linia prosta od pierwszego punktu do tego w którym jest aktualnie kursor...

Na obrazku wygląda to tak : linia prosta to zostaje dodana automatycznie - pomiędzy pierwszym a ostatnim punktem, a na liście są wszystkie punkty z polygon i jakoś nie widać po współrzędnych tej prostej tam ;/

user image

0

byłem prawie pewien, że będzie taki kłopot dlatego dodałem to item = 0;.
W tym kodzie jeszcze brakuje paru rzeczy (zmieniłem QPolygonF QPainterPath bo wtedy nie ma konieczności zamknięcia krzywej).
Trzeba sprawdzać stan przycisków itp. Poza tym nadal nie ustaliłeś rozmiaru MyWidget. W konstruktorach MyWidget dodaj setAcceptedMouseButtons(Qt::LeftButton);.

void MyWidget::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    if (event->buttons().test(Qt::LeftButton)) {
        Q_ASSERT(item == 0);
        QPen pen(Qt::black);
        item = new QPainterPath(this);
        item->setPen(pen);
        item->setBrush(QBrush());  //chcesz linie bez wypełnienia wielokąta, wiec Qt::NoBrush
        // polygon = new QPolygonF(0);  // zmień na pole QPainterPath path;
        path.clear();
        path.moveTo(event->pos());
        event->accept();
    }
}
 
void MyWidget::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    // if (event->buttons().test(Qt::LeftButton)) {// sprawdź czy jest potrzebne
    Q_ASSERT(item);
    path.lineTo(event->pos());
    item->setPolygon(path);
}

void MyWidget::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    if (event->buttons().test(Qt::LeftButton)) {
        path.lineTo(event->pos());
        item->setPolygon(path);
        item = 0; // tu nie ma wycieku pamięci
    }
}

W razie dalszych kłopotów, wystaw cały kod pod jakimś linkiem, to wtedy na to dokładniej popatrzę.
Niestety QGraphicsView ma wiele ruchomych część i nie jest zbyt przyjazny dla początkujących.

0

Mam kolejny problem...z rysowaniem wszystko dobrze działa.

Teraz chcę dodać obiekt klasy dziedziczącej po QGraphicsObject do QVector ale z tego co rozumiem wyskakuje że konstruktor kopiujący jest prywatny ?

// dodawanie
MyScene::MyScene(QObject *parent)
{
    setSceneRect(0,0,500,500);
    addTube();

    Piasek *cos = new Piasek(50,50);
    QVector<Piasek*> v;
    v.push_back(cos);   // blad

    // lub

    Piasek cos2(50,50);
    QVector<Piasek> v2;
    v2.push_back(cos2); // blad
}

klasa :

#include <QGraphicsObject>
#include <QPainter>

class Piasek : public QGraphicsObject
{
    Q_OBJECT
public:
    Piasek(QGraphicsObject *parent = 0);
    Piasek(int x, int y);

    int X,Y;
    int zmianaX,zmianaY;

    QRectF boundingRect() const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);

public slots:
    void changePos(int x, int y);
protected:
    void advance(int p);
};

masa odwołań do kodu Qt i ten błąd :

d:\QtSDK\Desktop\Qt\4.8.0\mingw\include\QtGui\qgraphicsitem.h błąd:'QGraphicsItem::QGraphicsItem(const QGraphicsItem&)' is private

Nie chciał bym używać tablic bo nie wiem ile będę miał obiektów na scenie ;/

1 użytkowników online, w tym zalogowanych: 0, gości: 1