Static drawing on wxPanel(?)

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
Wojtas
In need of some credit
In need of some credit
Posts: 4
Joined: Sun Mar 31, 2019 2:07 pm

Static drawing on wxPanel(?)

Post by Wojtas »

Hi guys!

I have a simple question - on my app, I'm creating two wxPanels, connecting them to wxEVT_PAINT and then drawing some bitmaps on them. But in this case resizing window slows down the program. Is there some option, to paint on wxPanel without handling event wxEVT_PAINT, and redrawing wxPanel only when I want it? Assuming that while resizing window this panels don't change sizes nor positions.

Thanks a lot!
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7459
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: Static drawing on wxPanel(?)

Post by ONEEYEMAN »

Hi,
Can you show some code - how do you draw those bitmaps?

Thank you.
Wojtas
In need of some credit
In need of some credit
Posts: 4
Joined: Sun Mar 31, 2019 2:07 pm

Re: Static drawing on wxPanel(?)

Post by Wojtas »

So, the method handling Paint event just calls normal method:

Code: Select all

void MyFrame::WxPanelMiniaturek_Repaint( wxPaintEvent& event )
{
    Repaint_miniatures();
}
And Repaint_minatures() (m_miniaturki is pointer to wxPanel object):

Code: Select all

void MyFrame::Repaint_miniatures()
{
    wxClientDC dc(m_miniaturki);
    dc.Clear();
    int x, y;
    main_panel->GetSize(&x, &y);
    dc.SetBrush(wxBrush(*wxWHITE));
    dc.DrawRectangle(0, 0, miniaturka_size_x + 2, miniaturka_size_y * 5 + 7);
    dc.SetBrush(wxBrush(*wxBLACK));
    dc.DrawLine(0, 1 * (miniaturka_size_y + 1) + 1, miniaturka_size_x , 1 * (miniaturka_size_y + 1) + 1);
    dc.DrawLine(0, 2 * (miniaturka_size_y + 1) + 1, miniaturka_size_x , 2 * (miniaturka_size_y + 1) + 1);
    
    (some other paintings...)
}
Where MyFrame is class derived from wxFrame. As I know, wxClientDC can draw on the client area of a window from outside an EVT_PAINT() handler - but when I delete this connection:

Code: Select all

main_panel->Connect( wxEVT_PAINT, wxPaintEventHandler( MyFrame::WxPanel_Repaint ), NULL, this );
It don't draw at all :/
User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2409
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania

Re: Static drawing on wxPanel(?)

Post by evstevemd »

check below link. It might give you a better idea
https://wiki.wxwidgets.org/An_image_panel
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
New Pagodi
Super wx Problem Solver
Super wx Problem Solver
Posts: 466
Joined: Tue Jun 20, 2006 6:47 pm
Contact:

Re: Static drawing on wxPanel(?)

Post by New Pagodi »

Try something like this:

Code: Select all

// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
    #pragma hdrstop
#endif

// for all others, include the necessary headers (this file is usually all you
// need because it includes almost all "standard" wxWidgets headers)
#ifndef WX_PRECOMP
    #include "wx/wx.h"
#endif

#include <wx/splitter.h>
#include <wx/dcbuffer.h>



class MyFrame : public wxFrame
{
    public:
        MyFrame( wxWindow* parent, int id = wxID_ANY, wxString title = "Demo",
                 wxPoint pos = wxDefaultPosition, wxSize size = wxDefaultSize,
                 int style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL );
    private:
        void OnRightPaint( wxPaintEvent& event );
        void Repaint_miniatures(wxDC& dc);

        wxPanel* main_panel;
        int miniaturka_size_x,miniaturka_size_y;
};

MyFrame::MyFrame(wxWindow* parent, int id, wxString title, wxPoint pos,
                wxSize size, int style )
        :wxFrame( parent, id, title, pos, size, style )
{
    miniaturka_size_x=50;
    miniaturka_size_y=30;

    wxSplitterWindow* splitter = new wxSplitterWindow(this, wxID_ANY,
                                        wxDefaultPosition, wxDefaultSize,
                                        wxSP_LIVE_UPDATE);

    wxPanel* panelLeft = new wxPanel(splitter, wxID_ANY, wxDefaultPosition,
                                     wxDefaultSize, wxBORDER_STATIC );

    main_panel = new wxPanel(splitter, wxID_ANY, wxDefaultPosition,
                             wxDefaultSize, wxBORDER_STATIC );

    main_panel->SetBackgroundStyle(wxBG_STYLE_PAINT);
    main_panel->Bind(wxEVT_PAINT, &MyFrame::OnRightPaint , this );

    splitter->SplitVertically( panelLeft, main_panel, GetSize().x/2 );
}

void MyFrame::OnRightPaint( wxPaintEvent& event )
{
    wxAutoBufferedPaintDC dc(main_panel);
    Repaint_miniatures(dc);
}

void MyFrame::Repaint_miniatures(wxDC& dc)
{
    dc.Clear();
    int x, y;
    main_panel->GetSize(&x, &y);
    dc.SetBrush(wxBrush(*wxWHITE));
    dc.DrawRectangle(0, 0, miniaturka_size_x + 2, miniaturka_size_y * 5 + 7);
    dc.SetBrush(wxBrush(*wxBLACK));
    dc.DrawLine(0, 1 * (miniaturka_size_y + 1) + 1, miniaturka_size_x , 1 * (miniaturka_size_y + 1) + 1);
    dc.DrawLine(0, 2 * (miniaturka_size_y + 1) + 1, miniaturka_size_x , 2 * (miniaturka_size_y + 1) + 1);

    //(some other paintings...)
}

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

wxIMPLEMENT_APP(MyApp);
I put the items in a splitter window so that you can see there is no slow down when resizing or moving the window being painted. The important steps are to call SetBackgroundStyle(wxBG_STYLE_PAINT) on the window being painted and to use an wxAutoBufferedPaintDC in the paint handler.
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7459
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: Static drawing on wxPanel(?)

Post by ONEEYEMAN »

Hi,
You absolutely have to create a wxPaintDC object - even if not being used. This is documented and it is because Windows will not work properly without it.

Also, just as suggested above - please try wxAutoBufferedPaintDC.

And finally - you don't have any other choice but to use paint event. Otherwise yhou will lose the painting when the other window will cover the part of the program.

Thank you.
Post Reply