Black Friday = Pricewatch Bekijk onze selectie van de beste Black Friday-deals en voorkom een miskoop.

[wxWidgets] Wissen van een DC

Pagina: 1
Acties:

  • maleadt
  • Registratie: Januari 2006
  • Laatst online: 05-11 22:08
Hallo,

Voor de ontwikkeling van een tool in C++, heb ik voor de wxWidgets toolkit gekozen om het zo cross-platform mogelijk te maken. Hierbij heb ik de GUI zelf geschreven, dus geen gebruik gemaakt van een toolset a la wxBuilder. In mijn main form heb ik enkel een wxPanel, die ik dan doorgeef aan een render() functie, of andere functies die er rechtstreekt op tekenen. (Het is misschien mooier om met een wxBitmap te werken en die dan in de render() functie via double-buffering op de DC te tekenen, maar dit is voor later :)).

De DC wordt op twee verschillende manieren beschreven. De eerste is bij het paint event, dit is als wxWidgets besluit dat het wxPanel moet hertekend worden. Ik vang die event zo:
C++:
1
2
3
BEGIN_EVENT_TABLE(DrawPane, wxPanel)
    EVT_PAINT(DrawPane::paintEvent)
END_EVENT_TABLE()


De functie paintEvent() vult dan in wat er moet gebeuren:
C++:
1
2
3
4
5
6
7
// Panel needs to be redrawn
void DrawPane::paintEvent(wxPaintEvent& WXUNUSED(event))
{
    // Force a redraw
    wxPaintDC dc(this);
    this->render(dc);
}

Ik gebruik hier een wxPaintDC en geen wxClientDC, zoals in de documentatie staat (wxPaintDC gebruiken binnen het paint event).

De render functie vangt dan de wxDC op, en geeft hem door aan een data_output_dc() routine, die naast het tekenen ook de DC wist:
code:
1
dc.Clear();


Echter lukt dit niet! Als ik dus mijn applicatie open, een file inlaadt, en het venster resize krijg ik het volgende te zien.


Hier houdt het echter niet op. Want ik call de data_output_dc(dc) ook uit andere situaties, namelijk als de user een bepaalde actie onderneemt (bijvoorbeeld op een knop "Rotate" drukken). Dan wordt dezelfde groep routines uitgevoerd, maar deze keer niet uit een wxPaint event (en dan gebruik ik dus ook wxClientDC). En raar maar waar, deze keer wordt het wxPanel correct gewist.

Wat doe ik mis? Ik heb al geprobeerd om in beide situaties wxClientDC te gebruiken, wat niks oplevert. EVT_SIZE hooken en dan render() callen zou werken (aangezien ik dan render() call zonder in een EVT_PAINT te zitten), maar dan moet ik alle resize logic op mij nemen en dat is nu net een sterk punt van wxWidgets...

Nog een nuance: bij de redraws in EVT_PAINT, zie ik geen progress. De draws zijn dus als het ware buffered (dit terwijl ik niks gedaan heb :P). Draws uit EVT_PAINT zijn niet buffered, ik zie dus alles getekend worden.

De file waar de hele GUI geregeld wordt, en de file die de Output klasse herbergt, met o.a. data_output_dc() in.

Alvast bedankt :)
maleadt

  • maleadt
  • Registratie: Januari 2006
  • Laatst online: 05-11 22:08
Laatste tijd wat op #wxwidgets gezeten om de fout te localiseren, en na 2 dagen was het duidelijk dat dit een bug in wxWidgets moet zijn. Na minimale aanpassingen aan de officiële samples komt de bug ook boven water, dus ik denk niet dat de schuld nog bij mij ligt. Binnenkort nog eens svn trunk uitproberen, en als dat ook op niks uitdraait een minimale testcase schrijven en bug-report invullen :)

Ter informatie, de bugbeschrijving nog wat kunnen specifiëren: elke manier van tekenen op een DC dat plaatsvindt in EVT_PAINT dat op zijn beurt gecallt is door EVT_SIZE slaagt er niet in om de oude data te overschrijven / clearen. Ordinaire EVT_PAINT calls werken dus wel (via panel.Refresh()).

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 13-11 21:11
Niets inhoudelijks hier, wilde je alleen even complimenteren met het feit dat je je bevindingen hier post :)

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.


  • maleadt
  • Registratie: Januari 2006
  • Laatst online: 05-11 22:08
Bedankt :)
Het probleem met hulp van #wxwidgets nog meer kunnen toespitsen: in EVT_SIZE gebruikt men de Update() call, die in realtime zou moeten updaten, terwijl Refresh() dat in idle time doet. Nu blijkt Update() zijn werk niet goed te doen, en die vervangen door Refresh() is een goede work-aorund voor het moment. Testcase is gemaakt, ik wacht nog op de reactie van enkele devs voor het op Trac te zwieren.