[C++/QT] QPainter tekent niet alle lijnen in functie

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • Xerohumoris
  • Registratie: Augustus 2010
  • Laatst online: 18:15
TL;DR: Niet elke QPainter::drawLine in dezelfde functie tekent een lijn.

Mijn vraag
Ik probeer een programma te schrijven waarmee je lijnen kan tekenen op je scherm. Niet heel ingewikkeld zou je denken. Nu tekent hij echter niet alle lijnen die ik wil dat hij tekent. Ik zal eerst mijn class even posten voor ik verder uitleg geef.
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include "trackbuilder.h"

TrackBuilder::TrackBuilder(QWidget *parent)
    : QWidget(parent)
{
    setMouseTracking(true);
    QPalette pal = palette();
    pal.setColor(QPalette::Background, Qt::white);
    setAutoFillBackground(true);
    setPalette(pal);
    Track = new QPainter(this);
}

TrackBuilder::~TrackBuilder()
{
    delete Track;
}

void TrackBuilder::paintEvent(QPaintEvent *event)
{
    Track->begin(this);
    Track->setRenderHint(QPainter::Antialiasing);
    Track->setBackgroundMode(Qt::OpaqueMode);
    Track->setBackground(Qt::white);
    Track->setPen(QPen(QBrush(Qt::black, Qt::SolidPattern), 3));
    buildTrack(QPoint(0,0));
    Track->end();

}

void TrackBuilder::mouseMoveEvent(QMouseEvent *event)
{
    if (Painting){
        buildTrack(event->pos());
    }
}

void TrackBuilder::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton){
        if (Painting){
            drawTrack(event);
        }else{
            savePoint(event);
        }
    }
    if(event->button() == Qt::RightButton){
        Painting = false;
        emit toLog("Press Rightmouse");
    }
}

void TrackBuilder::drawTrack(QMouseEvent *event)
{
    TrackPoints.insertMulti(DrawPoint, gridPoint(event->pos()));
    savePoint(event);
}

void TrackBuilder::savePoint(QMouseEvent *event)
{
    DrawPoint = gridPoint(event->pos());
    Painting = true;
}

QPoint TrackBuilder::gridPoint(QPoint mousePoint)
{
    //Calculate the point on the grid and return a new point
    QPoint gridPoint;
    gridPoint.setX(qFloor(mousePoint.x()/20)*20+10);
    gridPoint.setY(qFloor(mousePoint.y()/20)*20+10);
    emit toLog(QString::number(gridPoint.x()));
    return gridPoint;
}

void TrackBuilder::buildTrack(QPoint pos)
{
    if (pos != QPoint(0,0)){
        emit toLog(QString::number(pos.x()));
        emit toLog(QString::number(pos.y()));
        Track->drawLine(DrawPoint, pos);
    }
    QHashIterator<QPoint, QPoint> i(TrackPoints);
    while (i.hasNext()){
        i.next();
        Track->drawLine(i.key(), i.value());
    }
    update();
}


Op het moment dat je klikt met de linker muis begin je een lijn te teken (mousePressEvent). Pas bij de tweede klik komt er een lijn (logisch). Deze lijnen sla ik op in "QHash TrackPoints" welke ik vervolgens met een iterator bij langs loop. Deze lijnen worden allemaal goed getekend. Ook als ik een tweede lijn begin (eerst rechts dan weer links klikken) is geen probleem.

Het probleem zit echter in regel 80.
C++:
1
Track->drawLine(DrawPoint, pos);

Deze lijn wordt niet getekend. DrawPoint en pos zijn allebei gewoon QPoint En krijg ook geen fout in debug. Heeft iemand een idee wat het probleem is.

Relevante software en hardware die ik gebruik
Ik gebruik QT 5.10, g++ 4.8.5, OpenSuse Leap

Wat ik al gevonden of geprobeerd heb
Bij veel problemen met QPainter wordt er helemaal niet getekend. Bij mij gaat het alleen om de lijn die van het laatste punt naar de huidige aanwijspositie gaat. Welke gewoon in de functie zit met alle andere lijnen.

Ik heb al veel geprobeerd. Ik heb de teken volgorde al omgewisseld. Eerst de opgeslagen lijnen en later pas de volglijn.
Zoals te zien heb ik ook al een code die naar een log schrijft. Hierin komen ook gewoon de nieuwe muisposities te staan. Ik weer dus zeker dat het blok wordt binnen gegaan.
Ik heb de update(); al op veel plekken gehad. Inclusief de mouseEvent blokken. Dit had soms tot gevolg dat hij tweemaal werd geüpdatet.

Iemand een oplossing of iets dat ik niet kan testen?

Vriendelijke groet,
Xero

Beste antwoord (via Xerohumoris op 21-02-2018 17:48)


  • ATS
  • Registratie: September 2001
  • Laatst online: 29-09 11:31

ATS

update scheduled alleen maar, dus dat is niet zo'n punt.

Het grootste probleem is denk ik je gebruik van de painter. Waarom maak je in hemelsnaam je eigen painter in de constructor? Normaal gesproken maak je die pas in je paintEvent. Maar wat jij doet is dat vanuit allerlei plaatsen probeert te tekenen. Je kan alleen tekenen op een widget in je paintEvent, niet daarbuiten. Maar jij probeert dat te doen vanuit je mouse event handler. Dat gaat echt niet werken.

Wat probeer je precies te bereiken? Het lijkt erof alsof wat je probeert te doen, veel makkelijker te doen is met behulp van QGraphicsView & friends.

My opinions may have changed, but not the fact that I am right. -- Ashleigh Brilliant

Alle reacties


Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 27-09 13:03
Zomaar een wilde gok, heb je al vastgesteld de vector DrawPoint -> pos iets is wat in je zichtbare region zit?

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • Xerohumoris
  • Registratie: Augustus 2010
  • Laatst online: 18:15
Ja die zit in de zichtbare regio. Op het moment dat ik klik is de gehele lijn zichtbaar.

Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 27-09 13:03
Hmm, ben niet heel goed bekend met het Qt platform, maar je roept QWidget::update aan vanuit QWidget::paintEvent. Dat lijkt me raar, want volgens de docs wordt paintEvent getriggered door update()/repaint().

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • Xerohumoris
  • Registratie: Augustus 2010
  • Laatst online: 18:15
Helemaal waar. Ik had hem eerste echter in de twee mouseEvents staan. Dit deed/doet niks. Probleem is alleen dat update() twee maal wordt aangeroepen als je klikt. QWidget::mouseMoveEvent() Wordt namelijk ook opgeroepen door de linker muisklik.

Over repaint() Ik heb het geprobeerd. Echter krijg ik bij het starten van de applicatie direct een SIGABORT. Wat daar de reden van is weet ik niet maar dit werkt met update() netzo goed.

Acties:
  • Beste antwoord
  • 0 Henk 'm!

  • ATS
  • Registratie: September 2001
  • Laatst online: 29-09 11:31

ATS

update scheduled alleen maar, dus dat is niet zo'n punt.

Het grootste probleem is denk ik je gebruik van de painter. Waarom maak je in hemelsnaam je eigen painter in de constructor? Normaal gesproken maak je die pas in je paintEvent. Maar wat jij doet is dat vanuit allerlei plaatsen probeert te tekenen. Je kan alleen tekenen op een widget in je paintEvent, niet daarbuiten. Maar jij probeert dat te doen vanuit je mouse event handler. Dat gaat echt niet werken.

Wat probeer je precies te bereiken? Het lijkt erof alsof wat je probeert te doen, veel makkelijker te doen is met behulp van QGraphicsView & friends.

My opinions may have changed, but not the fact that I am right. -- Ashleigh Brilliant


Acties:
  • 0 Henk 'm!

  • Xerohumoris
  • Registratie: Augustus 2010
  • Laatst online: 18:15
Ik maak de Painter object idd al vroeg aan. Als je dit niet doet krijg je bij elke update (elke keer dat de muis beweegt) dat de Painter al bestaat. Je mag er namelijk maar één hebben per widget. Dat is het object al in de constructor maak is geen probleem. Het tekenen zelf QPainter::begin(this) roep ik pas aan in de paintEvent.

Maar ik zie nu wat je bedoelt. De opdracht te tekenen vanuit de muisbeweging met een nieuwe pointer wordt niet verwerkt. Het teken object dat die tekening maakt wordt aangeroepen door de mouseMoveEvent. Ik heb de code daar op aangepast en nu werkt het. Mijn dank is groot.

(QGraohicsView kan te veel voor wat ik nodig heb. De Painter is meer dan voldoende aangezien ik alleen lijnen wil tekenen.)

Acties:
  • 0 Henk 'm!

  • ATS
  • Registratie: September 2001
  • Laatst online: 29-09 11:31

ATS

QPainter maak je daarom ook eigenlijk altijd op de stack, niet op de heap zoals jij doet.

My opinions may have changed, but not the fact that I am right. -- Ashleigh Brilliant

Pagina: 1