Drawing on child window outside OnPaint failed. (Issue #23208)

82 views
Skip to first unread message

Mark Yang

unread,
Jan 31, 2023, 9:06:08 PM1/31/23
to wx-...@googlegroups.com, Subscribed

Description

Drawing on the child window outside OnPaint failed. Below is the sample code.

#include <wx/wx.h>

class MyChildWindow : public wxWindow
{
public:
    MyChildWindow(wxWindow* parent) : wxWindow(parent, wxID_ANY)
    {
        Bind(wxEVT_PAINT, &MyChildWindow::OnPaint, this);
    }

    void DrawRectangle()
    {
        wxClientDC dc(this);       
        dc.DrawRectangle(10, 10, 50, 50);        
    }

private:
    void OnPaint(wxPaintEvent& event)
    {
    }
};

class MyFrame : public wxFrame
{
public:

    MyChildWindow* child;
    wxButton* button;

    MyFrame() : wxFrame(NULL, wxID_ANY, "Child Window Example")
    {
        child = new MyChildWindow(this);
        child->SetSize(100, 100);

        Bind(wxEVT_BUTTON, &MyFrame::OnButtonClick, this);
        button = new wxButton(this, wxID_ANY, "Update Child Window");
        button->SetPosition(wxPoint(150, 150));
    }

private:
    void OnButtonClick(wxCommandEvent& event)
    {
        child->DrawRectangle();
    }
};

class MyApp : public wxApp
{
public:
    bool OnInit()
    {
        MyFrame* frame = new MyFrame();
        frame->Show();
        return true;
    }
};

wxIMPLEMENT_APP(MyApp);

When I press the button, a rectangle should be drawn on the child window.
But it shows nothing.
When I draw something in OnPaint it's OK.

Platform and version information

  • wxWidgets version 3.2.1 you use:
  • wxWidgets port wxMSW you use:
  • OS Windows 11 and its version:


Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23208@github.com>

oneeyeman1

unread,
Jan 31, 2023, 9:53:40 PM1/31/23
to wx-...@googlegroups.com, Subscribed

How can you be sure that the system didn't send paint event which will overpaint whatever yo painted?

There is a reason the event called EVT_PAINT...


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23208/1411380522@github.com>

PB

unread,
Feb 1, 2023, 1:36:08 AM2/1/23
to wx-...@googlegroups.com, Subscribed

As have been noted, the code in the op is incorrect:

  1. The paint event handler should always be able to draw everything needed (i.e, receiving paint event). Here, the rectangle could be easily cleared by drawing the window background during a refresh.
  2. The pain event handler must always create a paint DC, even if it does not draw anything (e.g., on Windows, doing that ensures calling ::BeginPaint(), which clears the update region to prevent generating subsequent WM_PAINT messages).

Moreover, the client and window DCs are basically unusable in modern OSes, where composition is used, and generally using them is to be avoided.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23208/1411533772@github.com>

VZ

unread,
Feb 1, 2023, 2:16:26 PM2/1/23
to wx-...@googlegroups.com, Subscribed

Yes, this code is invalid. Please see wxOverlay for a replacement to wxClientDC.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23208/1412585177@github.com>

VZ

unread,
Feb 1, 2023, 2:16:26 PM2/1/23
to wx-...@googlegroups.com, Subscribed

Closed #23208 as not planned.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issue/23208/issue_event/8413765348@github.com>

Mark Yang

unread,
Feb 1, 2023, 9:27:06 PM2/1/23
to wx-...@googlegroups.com, Subscribed

Thank you for your comments.
Then How could I draw something outside of OnPaint?


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23208/1413061229@github.com>

oneeyeman1

unread,
Feb 1, 2023, 10:12:09 PM2/1/23
to wx-...@googlegroups.com, Subscribed

Hi,


On Wed, Feb 1, 2023 at 8:27 PM Mark Yang ***@***.***> wrote:
>
> Thank you for your comments.
> Then How could I draw something outside of OnPaint?

Short answer - you can't.
Long answer - you can't because every time the OS will send a paint event,
it will paint on top of what you draw.
Is there a reason you want to?

Thank you.


>
> —
> Reply to this email directly, view it on GitHub, or unsubscribe.
> You are receiving this because you commented.Message ID: ***@***.***>


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23208/1413086268@github.com>

Mark Yang

unread,
Feb 2, 2023, 1:13:58 AM2/2/23
to wx-...@googlegroups.com, Subscribed

Thank you!
I am making a video player which decodes a video file in a separate thread and
draws that result in the same thread (directly on the child window with wxClientDC)
Is that the wrong way?
p.s many books about wxWidgets tell I can draw from anywhere with wxClientDC. Is that wrong?


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23208/1413207501@github.com>

PB

unread,
Feb 2, 2023, 1:54:48 AM2/2/23
to wx-...@googlegroups.com, Subscribed

Firstly, I don't think you are supposed to use any GUI object in a secondary thread, it may work or it may cause issues, it's a gamble.

Secondly, how many books about wxWidgets do you have? I have heard only about one and that one is very old. wxClientDC was usable back then, but AFAIK, now it works only on Windows and even there only when composition is disabled.

Normally, if one needs to draw on a window, he changes the state of the window (so the window knows what it needs to draw) and asks the window to redraw itself immediately calling its Refresh() + Update(). Again, a worker thread should not call any GUI methods, so it needs to either queue a thread event to the worker thread or use CallAfter(). However, this may be tricky if the code is timing- or performance-sensitive...

This is a simple example of obtaining a picture in a secondary thread and drawing it in the GUI thread, but I don't think it would work for an actual video player (e.g., flawlessly syncing audio and video, or even just getting FPS right). Video players are rather tricky to write and people usually use a third party video player library where a wxWidgets window just hosts the player. wxWidgets has wxMediaPlayerCtrl, and IME, integrating libvlc was not difficult (tried only on Windows).


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23208/1413233119@github.com>

Mark Yang

unread,
Feb 2, 2023, 2:34:12 AM2/2/23
to wx-...@googlegroups.com, Subscribed

Thank you very much !!!


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23208/1413273806@github.com>

Reply all
Reply to author
Forward
0 new messages