What's best way to implement this?
What's best way to implement this?
Hi,
I'm trying to get a following:
A class derived from wxPanel, which will display wxStaticBitmap and wxStaticText in the vertical box sizer.
The set of the panels should be displayed in the dialog.
Only one panel should be "selected" at a time.
A selection can be done by the mouse click anywhere on the pane, including the control it displays.
The "selection" will be indicated by changing the background color of the static text.
I am going to probably try to bind the mouse click in the dialog to the panel, but how to catch the clicks on the controls (static bitmap and static text)?
It looks like static bitmap does not react to mouse clicks.
Thank you.
I'm trying to get a following:
A class derived from wxPanel, which will display wxStaticBitmap and wxStaticText in the vertical box sizer.
The set of the panels should be displayed in the dialog.
Only one panel should be "selected" at a time.
A selection can be done by the mouse click anywhere on the pane, including the control it displays.
The "selection" will be indicated by changing the background color of the static text.
I am going to probably try to bind the mouse click in the dialog to the panel, but how to catch the clicks on the controls (static bitmap and static text)?
It looks like static bitmap does not react to mouse clicks.
Thank you.
Re: What's best way to implement this?
At least under Windows i get mouse click events from both wxStaticBitmap and wxStaticText.
Code: Select all
::wxInitAllImageHandlers();
wxPanel *panel = new wxPanel(this, wxID_ANY);
wxBitmap bmp("d:\\test.png", wxBITMAP_TYPE_PNG);
wxStaticBitmap *sbmp = new wxStaticBitmap(panel, wxID_ANY, bmp, wxPoint(20,20));
sbmp->Bind(wxEVT_LEFT_DOWN, &MyFrame::OnMouse, this);
wxStaticText *st = new wxStaticText(panel, wxID_ANY, "click me", wxPoint(200, 20) );
st->Bind(wxEVT_LEFT_DOWN, &MyFrame::OnMouse, this);
// *********************
void MyFrame::OnMouse(wxMouseEvent &event)
{
wxLogDebug("mouse event: %d %p", event.GetEventType(), event.GetEventObject() );
event.Skip();
}
Use the source, Luke!
Re: What's best way to implement this?
doublemax,
So I think all I need to do is to bind the left mouse click to static bitmap and call event,skip().
And then I bind the mouse click on the dialog, because I have to groups of those panels.
Is it what you meant?
Thank you.
So I think all I need to do is to bind the left mouse click to static bitmap and call event,skip().
And then I bind the mouse click on the dialog, because I have to groups of those panels.
Is it what you meant?
Thank you.
Re: What's best way to implement this?
That's one way. But for proper encapsulation i would keep the mouse event handling inside the custom control and send a custom wxCommandEvent upwards that indicates that this panel got selected.
Use the source, Luke!
Re: What's best way to implement this?
doublemax,
Apparently it looks like I was wrong.
So I have following:
wxDialog->wxPanel->MyPanel (with bitmap and label)
Inside MyPanel I bound mouse click to the bitmap and called event.Skip()
Now inside the dialog I bound the mouse click to the MyPanel and call the handler inside the dialog.
So while the MyPanel::OnBitmapClicked is called the dialog handler is not.
I will try to see what is going on. If nothing comes up I will probably follow your advice.
Thank you.
Apparently it looks like I was wrong.
So I have following:
wxDialog->wxPanel->MyPanel (with bitmap and label)
Inside MyPanel I bound mouse click to the bitmap and called event.Skip()
Now inside the dialog I bound the mouse click to the MyPanel and call the handler inside the dialog.
So while the MyPanel::OnBitmapClicked is called the dialog handler is not.
I will try to see what is going on. If nothing comes up I will probably follow your advice.
Thank you.
Re: What's best way to implement this?
doublemax,
NM, I think I got it.
Thank you.
NM, I think I got it.
Thank you.
Re: What's best way to implement this?
doublemax,
It works partially.
This same code works properly on *nix/GTK, but doesn't work on Windows (8.1) with MSVC 2017 Community.
Any idea?
Thank you.
It works partially.
Code: Select all
MyPanel::MyPanel(wxWindow *parent, const wxBitmap &bitmap, const wxString &label) : wxPanel(parent)
{
m_bitmap = new wxStaticBitmap( this, wxID_ANY, bitmap );
m_label = new wxStaticText( this, wxID_ANY, label );
do_layout();
m_bitmap->Bind( wxEVT_LEFT_DOWN, &MyPanel::OnBitmapClicked, this );
}
void MyPanel::do_layout()
{
wxBoxSizer *sizer1 = new wxBoxSizer( wxHORIZONTAL );
wxBoxSizer *sizer2 = new wxBoxSizer( wxVERTICAL );
wxBoxSizer *sizer3 = new wxBoxSizer( wxVERTICAL );
sizer1->Add( 5, 5, 0, wxEXPAND, 0 );
sizer3->Add( 5, 20, 0, wxEXPAND, 0 );
sizer3->Add( m_bitmap, 0, wxEXPAND, 0 );
sizer3->Add( 5, 5, wxEXPAND, 0 );
sizer3->Add( m_label, 0, wxALIGN_CENTER_HORIZONTAL, 0 );
sizer3->Add( 5, 20, wxEXPAND, 0 );
sizer2->Add( sizer3, 0, wxEXPAND, 0 );
sizer1->Add( sizer2, 0, wxEXPAND, 0 );
sizer1->Add( 5, 5, 0, wxEXPAND, 0 );
SetSizer( sizer1 );
}
void MyPanel::OnBitmapClick(wxMouseEvent &event)
{
event.ResumePropagation( wxEVENT_PROPAGATE_MAX );
event.SetEventObject( this );
event.Skip();
}
void MyDialog::OnMyPanelClick(wxMouseEvent &event)
{
bool found = false;
for( int i = 0; i < 4 || !found; ++i )
{
if( event.GetEventObject () == m_panels[i] )
{
if( i + 1 != m_source )
{
m_panels[m_source - 1]->GetLabel()->SetBackgroundColour( m_panel->GetBackgroundColour() );
m_source = i + 1;
m_panels[m_source - 1]->GetLabel()->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
found = true;
}
}
}
event.Skip();
}
Any idea?
Thank you.
Re: What's best way to implement this?
Usually mouse events don't propagate and i don't know if setting wxEVENT_PROPAGATE_MAX is enough to override that.
My idea was to send a (new) wxCommandEvent. You could also re-use an existing one that has a similar meaning, e.g. wxEVT_LISTBOX.
This is of course a little dirty, as the event object is not a wxListBox, so code relying on that would crash. For a clean solution, define a new event type.
My idea was to send a (new) wxCommandEvent. You could also re-use an existing one that has a similar meaning, e.g. wxEVT_LISTBOX.
Code: Select all
void MyPanel::OnBitmapClick(wxMouseEvent &event)
{
wxCommandEvent cmd(wxEVT_LISTBOX, GetId() );
cmd.SetEventObject( this );
GetEventHandler()->ProcessEvent(cmd);
}
Use the source, Luke!
Re: What's best way to implement this?
doublemax,
Calling Refresh() at the end of the dialog handler fixed it for Windows. Background color is now reflects properly.
Which makes me curious - shouldn't library do that?
I will try to build the widgets sample and check and maybe submit a patch/PR.
Thank you.
Calling Refresh() at the end of the dialog handler fixed it for Windows. Background color is now reflects properly.
Which makes me curious - shouldn't library do that?
I will try to build the widgets sample and check and maybe submit a patch/PR.
Thank you.