Page 1 of 2

wxPanel draws over the scrollbar of wxScrolledWindow

Posted: Fri Sep 14, 2018 7:39 am
by ongledda
I have a wxPanel that is being redrawn when mouse pointer has entered on it.
This panel is in a wxScrollWindow.

The problem is when the wxPanel is re-drawn, while the scrollbar of the wxScrollBarWindow is on top of it, the wxPanel will be drawn over the scrollbar.

This seems to happen only on MacOS.
My environment:
- MacOS X 10.12 Sierra
- wxcocoa (wxWidgets-3.1.1)

I have reproduced this behavior in "scroll" sample code.
I added a wxPanel inside the MyCanvas.

Created a wxPanel button:

Code: Select all

class MyButton : public wxWindow
{
    
public:
    MyButton(wxWindow *parent)
    : wxWindow(parent, wxID_ANY, wxDefaultPosition, wxSize(100, 50))
    {
        Connect(wxEVT_PAINT, wxPaintEventHandler(MyButton::OnPaint));
        Bind(wxEVT_ENTER_WINDOW, &MyButton::mouseEntered, this);
        Bind(wxEVT_LEAVE_WINDOW, &MyButton::mouseLeave, this);
    }
    
private:
    void OnPaint(wxPaintEvent& WXUNUSED(event))
    {
        render();
    }
    
    void mouseEntered(wxMouseEvent& WXUNUSED(evt))
    {
        render(*wxYELLOW);
    }
    
    void mouseLeave(wxMouseEvent& WXUNUSED(evt))
    {
        render();
    }
    
    void render(wxColor color = *wxRED)
    {
        wxClientDC dc(this);
        dc.SetBackground(wxBrush(color));
        
        dc.Clear();
    }
};
In MyCanvass class:

Code: Select all

    // you can use either a single SetScrollbars() call or these 2 functions,
    // usually using them is better because you normally won't need to change
    // the scroll rate in the future and the sizer can be used to update the
    // virtual size automatically
    SetScrollRate( 10, 10 );
    SetVirtualSize( 500, 1000 );

    (void) new wxButton( this, ID_ADDBUTTON,  "add button", wxPoint(10,10) );
    (void) new wxButton( this, ID_DELBUTTON,  "del button", wxPoint(10,40) );
    (void) new wxButton( this, ID_MOVEBUTTON, "move button", wxPoint(150,10) );
    (void) new wxButton( this, ID_SCROLLWIN,  "scroll win", wxPoint(250,10) );
    
    MyButton *btn = new MyButton(this);

    wxPanel *test = new wxPanel( this, wxID_ANY,
                                 wxPoint(10, 110), wxSize(130,50),
                                 wxSIMPLE_BORDER | wxTAB_TRAVERSAL );
    test->SetBackgroundColour( "WHEAT" );
Screenshots:

Scrollbar is over the panel:
scrollbar_over_panel.png
scrollbar_over_panel.png (18.72 KiB) Viewed 2672 times
..when mouse is hovered, the panel is redrawn over the scrollbar:
hovered.png
hovered.png (16.5 KiB) Viewed 2672 times

Thanks for the help!

Re: wxPanel draws over the scrollbar of wxScrolledWindow

Posted: Fri Sep 14, 2018 8:05 am
by catalin
Does it still happen if you move it around so that it will not overlap any of its siblings?

Re: wxPanel draws over the scrollbar of wxScrolledWindow

Posted: Fri Sep 14, 2018 9:27 am
by doublemax

Code: Select all

 void render(wxColor color = *wxRED)
    {
        wxClientDC dc(this);
        dc.SetBackground(wxBrush(color));
       
        dc.Clear();
    }
Don't use wxClientDC in a paint event handler, use wxPaintDC.

Re: wxPanel draws over the scrollbar of wxScrolledWindow

Posted: Fri Sep 14, 2018 9:37 am
by ongledda
Yes, it still happens.

I do not know if I'm missing something on wxPanel drawing or not.
This issue does not seem to happen on windows.

[img]
test_code.png
test_code.png (34.26 KiB) Viewed 2661 times
[/img]

Re: wxPanel draws over the scrollbar of wxScrolledWindow

Posted: Fri Sep 14, 2018 9:52 am
by ongledda
Don't use wxClientDC in a paint event handler, use wxPaintDC.
I tried to use wxPaintDC in the paint event handler, but it still happens.

Code: Select all

class MyButton : public wxWindow
{
    
public:
    MyButton(wxWindow *parent, wxPoint pos)
    : wxWindow(parent, wxID_ANY, pos, wxSize(100, 50))
    {
        Connect(wxEVT_PAINT, wxPaintEventHandler(MyButton::OnPaint));
        Bind(wxEVT_ENTER_WINDOW, &MyButton::mouseEntered, this);
        Bind(wxEVT_LEAVE_WINDOW, &MyButton::mouseLeave, this);
    }
    
private:
    void OnPaint(wxPaintEvent& WXUNUSED(event))
    {
        wxPaintDC dc(this);
        render(dc);
    }
    
    void mouseEntered(wxMouseEvent& WXUNUSED(evt))
    {
        wxClientDC dc(this);
        render(dc, *wxYELLOW);
    }
    
    void mouseLeave(wxMouseEvent& WXUNUSED(evt))
    {
        wxClientDC dc(this);
        render(dc);
    }
    
    void render(wxDC& dc, wxColor color = *wxRED)
    {
        dc.SetBackground(wxBrush(color));
        dc.Clear();
    }
};

Re: wxPanel draws over the scrollbar of wxScrolledWindow

Posted: Fri Sep 14, 2018 9:59 am
by doublemax
You're still using wxClientDC in the mouse enter/leave handlers. Try disabling these for a test.

Re: wxPanel draws over the scrollbar of wxScrolledWindow

Posted: Fri Sep 14, 2018 10:17 am
by ongledda
Disabling the enter/leave handlers and drawing the panel in the paint event using wxPaintDC is working fine, it does not overlap the scrollbar.

But, I'd like to redraw the panel on mouse enter or leave, without overlapping the scrollbar.

Re: wxPanel draws over the scrollbar of wxScrolledWindow

Posted: Fri Sep 14, 2018 10:22 am
by doublemax
Get rid of the render method, do your drawing in the paint event handler only. Use a flag that controls the color.

Code: Select all

bool m_mouse_inside;    // member of class

void OnPaint(wxPaintEvent& WXUNUSED(event))
{
    wxPaintDC dc(this);
    
    dc.SetBackground( m_mouse_inside ? *wxYELLOW : *wxRED );
    dc.Clear();
}

void mouseEntered(wxMouseEvent& WXUNUSED(evt))
{
  m_mouse_inside = true;
  Refresh();
}

void mouseLeave(wxMouseEvent& WXUNUSED(evt))
{
  m_mouse_inside = false;
  Refresh();
}

Re: wxPanel draws over the scrollbar of wxScrolledWindow

Posted: Fri Sep 14, 2018 10:31 am
by ongledda
Your answer worked!

Thank you very much for the help. :D

Re: wxPanel draws over the scrollbar of wxScrolledWindow

Posted: Fri May 22, 2020 8:34 am
by ongledda
Hello everyone,

I ran into a similar problem again, but this time it's the wxTextCtrl's highlight that is overlapping the scroll bars.

I also replicated the issue in the "scroll" sample code of wxWidgets 3.1.3.
I just added a wxTextCtrl in MyCanvas class.

Code: Select all

MyCanvas::MyCanvas(wxWindow *parent)
    : wxScrolled<wxPanel>(parent, wxID_ANY,
                          wxDefaultPosition, wxDefaultSize,
                          wxSUNKEN_BORDER | wxTAB_TRAVERSAL)
{
    // you can use either a single SetScrollbars() call or these 2 functions,
    // usually using them is better because you normally won't need to change
    // the scroll rate in the future and the sizer can be used to update the
    // virtual size automatically
    SetScrollRate( 10, 10 );
    SetVirtualSize( 500, 1000 );

    (void) new wxButton( this, ID_ADDBUTTON,  "add button", wxPoint(10,10) );
    (void) new wxButton( this, ID_DELBUTTON,  "del button", wxPoint(10,40) );
    (void) new wxButton( this, ID_MOVEBUTTON, "move button", wxPoint(150,10) );
    (void) new wxButton( this, ID_SCROLLWIN,  "scroll win", wxPoint(250,10) );

    wxPanel *test = new wxPanel( this, wxID_ANY,
                                 wxPoint(10, 110), wxSize(130,50),
                                 wxSIMPLE_BORDER | wxTAB_TRAVERSAL );
    test->SetBackgroundColour( "WHEAT" );

    wxTextCtrl *myText = new wxTextCtrl(this, wxID_ANY, "This is a text control", wxPoint(300,250), wxSize(150,24));

    SetBackgroundColour( "BLUE" );
}
Screenshot:
scroll.png
My questions are:
1. Do you have any suggestions on how to prevent this issue without modifying the wxWidgets code?
2. Is there a way to remove the blue highlight when the text control is on focus, again without modifying the wxWidgets code?

Thank you.

Re: wxPanel draws over the scrollbar of wxScrolledWindow

Posted: Fri May 22, 2020 6:06 pm
by ONEEYEMAN
Hi,
Did you selected the code inside the wxTextCtrl?

Thank you.

Re: wxPanel draws over the scrollbar of wxScrolledWindow

Posted: Mon May 25, 2020 1:26 am
by ongledda
Hello,
No, I did not make any changes on the library itself.
This is the version I used: https://github.com/wxWidgets/wxWidgets/ ... tag/v3.1.3

Did I answer your question correctly?

Thank you.

Re: wxPanel draws over the scrollbar of wxScrolledWindow

Posted: Mon May 25, 2020 4:44 am
by ONEEYEMAN
Hi,
You are setting the position and the size of the control which overrides the size of the canvas.
You should follow the idea of the button creation.

Thank you.

Re: wxPanel draws over the scrollbar of wxScrolledWindow

Posted: Mon May 25, 2020 5:33 am
by ongledda
Hello,

I do not understand why it would override the size of the canvas.
As you have suggested, I tried to follow the syntax used to create the buttons.

Code: Select all

    //wxTextCtrl *myText = new wxTextCtrl(this, wxID_ANY, "This is a text control", wxPoint(300,250), wxSize(150,24));
    //(void) new wxTextCtrl(this, wxID_ANY, "This is a text control", wxPoint(300,250));
    (void) new wxTextCtrl(this, wxID_ANY, "This is a text control");
Even if I do not set the size and/or the position parameter, I can still reproduce the issue.

Thank you.

Re: wxPanel draws over the scrollbar of wxScrolledWindow

Posted: Mon May 25, 2020 6:03 am
by doublemax
Looks like a bug to me. Try to open a ticket at http://trac.wxwidgets.org , ideally with a minimal patch to any of the samples that shows the issue.