1

I have made a class wxRectangleDrawing, which has 3 methods, 1 for catching the paint event and creating the dc object, one for drawing my desired rectangle with that dc object, and one for clearing that dc.

The only problem is I cannot clear that dc with my Clear() method, because dc is a local variable and not a class field/member. I looked up online, and as far as I understood you need to catch an EVT_PAINT in your function to create a dc in it (?) Don't know if that's correct.

Here's my .h and .cpp files

wxRectangleDrawing.h

#pragma once
#include <wx/wx.h>

class wxRectangleDrawing : public wxWindow
{
    wxPoint position;
    wxSize size;
    wxBrush brushColor;

public:
    wxRectangleDrawing(wxPanel* parent, wxPoint rectPosition, wxSize rectSize, wxColour rectColor);

    void PaintEvent(wxPaintEvent& evt);
    void DrawRectangle(wxDC& dc);
    void Clear(wxDC& dc);

    DECLARE_EVENT_TABLE()
};

and here's the .cpp one

wxRectangleDrawing.cpp

#include "wxRectangleDrawing.h"

BEGIN_EVENT_TABLE(wxRectangleDrawing, wxPanel)

// catch paint events
EVT_PAINT(wxRectangleDrawing::PaintEvent)

END_EVENT_TABLE()


wxRectangleDrawing::wxRectangleDrawing(wxPanel* parent, wxPoint rectPosition, wxSize rectSize, wxColour rectColor) : wxWindow(parent, wxID_ANY)
{
    position = rectPosition;
    size = rectSize;
    brushColor = wxBrush(rectColor);
    SetMinSize(size);

}

void wxRectangleDrawing::PaintEvent(wxPaintEvent& evt)
{
    // depending on your system you may need to look at double-buffered 
    wxPaintDC dc(this);
    DrawRectangle(dc);
}


void wxRectangleDrawing::DrawRectangle(wxDC& dc)
{
    dc.SetBrush(brushColor);
    dc.DrawRectangle(position.x, position.y, size.x, size.y);
}

void wxRectangleDrawing::Clear(wxDC& dc)
{
    dc.Clear();
}
zoinkers
  • 13
  • 3
  • 1
    Yes, you must create a `wxPaintDC` before you start drawing. And let it get deleted after drawing, or nothing will be shown on the screen. Storing the DC is a bad idea, only used many years (W95 days) ago. – Ripi2 Aug 04 '23 at 17:23
  • @zoinkers, you code seems correct, except.... when you need to clear the panel, set some kind of flag and call `Refresh()`. In the paint event handler, call `dc.Clear()` if the flag is set and then depending on you need either reset the flag or reset it in some other way/place. Remember - you don't know when the OS will send the paint event and so every painting should occur in the handler. – Igor Aug 04 '23 at 17:24
  • @Ripi2, it is bad idea. But some programs still using the following concept: `wxPaintSDC dc(this ); Draw( dc );` this is a bad design for many reasons and should be avoided. – Igor Aug 04 '23 at 17:27
  • @Igor, "your code seems correct" is no joke the best compliment I ever received on stack overflow, thank you. However, perhaps my question was a little off, I want to call 'Clear()' from another class, my *MainWindow* class, the "actual" GUI. In it, I instantiate a wxRectangleDrawing object. That, at first, draws a rectangle of a certain size/color. Then I want to clear the rectangle (using Clear()), but retain the actual object. And then redraw the rectangle, with a different size/color. My problem is that I cannot call Clear() without passing a dc. And I cannot store that dc in the class. – zoinkers Aug 04 '23 at 18:21
  • @Igor not sure what you ment by setting a flag. – zoinkers Aug 04 '23 at 18:21
  • Please, clarify *" I want to clear the rectangle (using Clear()), but retain the actual object"* Do you want more than one rectangle to be displayed simultaneusly? If so, you can avoid clearing the previous, or store it in a wxBitmap and draw again when needed. – Ripi2 Aug 04 '23 at 18:39
  • @zoinkers, add some boolean class member and assign it to false. Create setter on it. In you paint event handler add the following: ``if( some_flag ) { dc.Clear(); some_flag = false; // set the new color, position and size here }`` Then call the setter in the main frame whenever you need. – Igor Aug 04 '23 at 19:24
  • @zoinkers, also let me ask you - arwe you after the moving rectangle effect? – Igor Aug 04 '23 at 19:27
  • @Igor, ah, I understand now, I just needed to add a flag variable within the PaintEvent() method, and from my MainWindow, set that variable to true/false depending on what I want to happen inside that function, then call Refresh(), so PaintEvent() is called again. Just what I needed, thanks! – zoinkers Aug 04 '23 at 20:02
  • @zoinkers, please upvote my comment if everything works. If not - what's is an issue? Thx. – Igor Aug 05 '23 at 08:48
  • There is an up arrow to the left of my comment. Click it to upvote. Thx. – Igor Aug 05 '23 at 08:49
  • @Igor not enough rep to vote on comments – zoinkers Aug 12 '23 at 12:06
  • That's ok. I understand. – Igor Aug 12 '23 at 12:25

0 Answers0