What I want to achieve mouse motion inside the wxImagePanel widget (which I grabbed from here). When the user drags on the wxImagePanel, then the application draws onto the wxImagePanel. The source is here:
wxImagePanel.hpp:
Code: Select all
#ifndef WX_IMAGE_PANEL_HPP
#define WX_IMAGE_PANEL_HPP
#include <wx/wx.h>
#include <wx/sizer.h>
class wxImagePanel : public wxPanel
{
wxImage m_image;
public:
wxImagePanel(wxFrame* parent);
void paintEvent(wxPaintEvent & evt);
void paintNow();
void render(wxDC& dc);
void mouseMoved(wxMouseEvent& event);
DECLARE_EVENT_TABLE()
};
#endif
Code: Select all
#include "wxImagePanel.hpp"
BEGIN_EVENT_TABLE(wxImagePanel, wxPanel)
EVT_PAINT(wxImagePanel::paintEvent)
EVT_MOTION(wxImagePanel::mouseMoved)
END_EVENT_TABLE()
void wxImagePanel::mouseMoved(wxMouseEvent& event)
{
if (event.Dragging())
{
m_image.SetRGB(event.m_x, event.m_y, 255, 0, 0);
paintNow();
}
}
wxImagePanel::wxImagePanel(wxFrame* parent) :
wxPanel(parent)
{
m_image = wxImage(640, 480, true);
}
void wxImagePanel::paintEvent(wxPaintEvent & evt)
{
wxPaintDC dc(this);
render(dc);
}
void wxImagePanel::paintNow()
{
wxClientDC dc(this);
render(dc);
}
void wxImagePanel::render(wxDC& dc)
{
dc.DrawBitmap(m_image, 0, 0, false );
}
Code: Select all
#ifndef APP_HPP
#define APP_HPP
#include <wx/wx.h>
#include "noname.h"
class MyApp : public wxApp
{
virtual bool OnInit();
};
class MyFrame1Impl : public MyFrame1
{
public:
MyFrame1Impl();
virtual ~MyFrame1Impl();
protected:
void onMotion(wxMouseEvent &event);
};
#endif
Code: Select all
#include "app.hpp"
IMPLEMENT_APP(MyApp)
bool
MyApp::OnInit()
{
MyFrame1 *frame = new MyFrame1Impl();
frame->Show(true);
SetTopWindow(frame);
return true;
}
MyFrame1Impl::MyFrame1Impl() : MyFrame1(NULL) { }
MyFrame1Impl::~MyFrame1Impl() { }
void
MyFrame1Impl::onMotion(wxMouseEvent &event)
{
wxString label =
wxString::Format
(
wxT("MyFrame1Impl::onMotion(): x: %d y: %d"),
event.m_x,
event.m_y
);
m_staticText1->SetLabel(label);
event.Skip();
}
noname.h:
Code: Select all
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Jun 30 2011)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#ifndef __NONAME_H__
#define __NONAME_H__
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include "wxImagePanel.hpp"
#include <wx/string.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/stattext.h>
#include <wx/sizer.h>
#include <wx/frame.h>
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// Class MyFrame1
///////////////////////////////////////////////////////////////////////////////
class MyFrame1 : public wxFrame
{
private:
protected:
wxImagePanel *m_image;
wxStaticText* m_staticText1;
// Virtual event handlers, overide them in your derived class
virtual void onMotion( wxMouseEvent& event ) { event.Skip(); }
public:
MyFrame1( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 500,300 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL );
~MyFrame1();
};
#endif //__NONAME_H__
Code: Select all
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Jun 30 2011)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#include "noname.h"
///////////////////////////////////////////////////////////////////////////
MyFrame1::MyFrame1( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style )
{
this->SetSizeHints( wxDefaultSize, wxDefaultSize );
wxBoxSizer* bSizer1;
bSizer1 = new wxBoxSizer( wxVERTICAL );
m_image = new wxImagePanel(this);
bSizer1->Add( m_image, 1, wxALL|wxEXPAND, 5 );
m_staticText1 = new wxStaticText( this, wxID_ANY, wxT("MyLabel"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText1->Wrap( -1 );
bSizer1->Add( m_staticText1, 0, wxALL, 5 );
this->SetSizer( bSizer1 );
this->Layout();
this->Centre( wxBOTH );
// Connect Events
this->Connect( wxEVT_MOTION, wxMouseEventHandler( MyFrame1::onMotion ) );
}
MyFrame1::~MyFrame1()
{
// Disconnect Events
this->Disconnect( wxEVT_MOTION, wxMouseEventHandler( MyFrame1::onMotion ) );
}
The result looks like this:
This looks a bit better, but now the mouse events are no longer being captured by the wxImagePanel. They go straight to the top wxPanel, which is not what I want. How do I make sure the events get to the child wxImagePanel?
The updated source for the GUI is as follows:
noname.h:
Code: Select all
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Jun 30 2011)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#ifndef __NONAME_H__
#define __NONAME_H__
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include "wxImagePanel.hpp"
#include <wx/string.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/stattext.h>
#include <wx/sizer.h>
#include <wx/panel.h>
#include <wx/frame.h>
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// Class MyFrame1
///////////////////////////////////////////////////////////////////////////////
class MyFrame1 : public wxFrame
{
private:
protected:
wxPanel* m_panel1;
wxImagePanel *m_image;
wxStaticText* m_staticText1;
// Virtual event handlers, overide them in your derived class
virtual void onMotion( wxMouseEvent& event ) { event.Skip(); }
public:
MyFrame1( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 500,300 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL );
~MyFrame1();
};
#endif //__NONAME_H__
Code: Select all
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Jun 30 2011)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#include "noname.h"
///////////////////////////////////////////////////////////////////////////
MyFrame1::MyFrame1( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style )
{
this->SetSizeHints( wxDefaultSize, wxDefaultSize );
wxBoxSizer* bSizer1;
bSizer1 = new wxBoxSizer( wxVERTICAL );
m_panel1 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* bSizer2;
bSizer2 = new wxBoxSizer( wxVERTICAL );
m_image = new wxImagePanel(this);
bSizer2->Add( m_image, 1, wxALL|wxEXPAND, 5 );
m_staticText1 = new wxStaticText( m_panel1, wxID_ANY, wxT("MyLabel"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText1->Wrap( -1 );
bSizer2->Add( m_staticText1, 0, wxALL, 5 );
m_panel1->SetSizer( bSizer2 );
m_panel1->Layout();
bSizer2->Fit( m_panel1 );
bSizer1->Add( m_panel1, 1, wxEXPAND | wxALL, 5 );
this->SetSizer( bSizer1 );
this->Layout();
this->Centre( wxBOTH );
// Connect Events
m_panel1->Connect( wxEVT_MOTION, wxMouseEventHandler( MyFrame1::onMotion ), NULL, this );
}
MyFrame1::~MyFrame1()
{
// Disconnect Events
m_panel1->Disconnect( wxEVT_MOTION, wxMouseEventHandler( MyFrame1::onMotion ), NULL, this );
}