xList
項目 (LC_REPORT
ビュー)間の DnD をサポートする wxListCtrl派生コントロール () を編成しようとしています。だから、私は BEGIN_DRAG イベントをキャッチします
Connect(wxEVT_COMMAND_LIST_BEGIN_DRAG,
(wxObjectEventFunction)&xList::OnBeginDrag
);
関数は、( )OnBeginDrag
のインスタンスごとにマウスの動きとマウスの左ボタン アップ イベントをキャッチするように設計されています。xList
list
list->Connect(wxEVT_MOTION,
wxMouseEventHandler(xList::OnMoveDrag)
);
list->Connect(wxEVT_LEFT_UP,
wxMouseEventHandler(xList::OnEndDrag)
);
(そしてOnEndDrag
それらをすべて切断します)。単一のxList
インスタンス (1 つのパネル) がある場合は完全に動作しますが、2 つある場合はモーションのように見え、ドラッグを開始したパネルに対してのみ左アップイベントがキャッチされます: 単一のパネル内で DnD を実行できますが、マウスをドラッグするとあるパネルから別のパネルまでxList::OnMoveDrag
、最初のパネルでまだ機能しているように機能します。私が欠けているものは何ですか?
wxEVT_MOTION
ウィジェットごとに個別に処理されますか? もしそうなら、なぜプログラムはこのように動作しますか。そうでない場合、最後に接続されたウィジェットではなく、ドラッグを開始するウィジェットに対して常に処理されるのはなぜですか?
何が起こっているかを示すサンプルコード(私が到達できる限り単純なもの)を次に示します。
#include <wx/wx.h>
#include <vector>
class xList;
// class to store group of xList to DnD between
class DnDxList
{public:
void BeginDrag ();
void EndDrag ();
void AddList (xList* l) {list.push_back (l); }; // register new xList object
private:
std::vector<xList*> list;
};
class xList: public wxListCtrl
{public:
xList (DnDxList& dnd,
wxWindow *parent,
wxWindowID winid = wxID_ANY,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxLC_ICON,
const wxValidator &validator = wxDefaultValidator,
const wxString &name = wxListCtrlNameStr
);
virtual ~xList () {};
void OnBeginDrag(wxListEvent& event);
void OnEndDrag(wxMouseEvent& event);
void OnMoveDrag(wxMouseEvent& event);
DnDxList& dndsource; // keep reference to common DnDxList object
};
void DnDxList::BeginDrag () // connect motion and left-up events for all lists in group
{for (std::vector<xList*>::const_iterator i = list.begin(); i != list.end(); i++)
{(*i)->Connect(wxEVT_MOTION,
wxMouseEventHandler(xList::OnMoveDrag)
);
(*i)->Connect(wxEVT_LEFT_UP,
wxMouseEventHandler(xList::OnEndDrag)
);
}
};
void DnDxList::EndDrag () // disconnect all
{for (std::vector<xList*>::const_iterator i = list.begin(); i != list.end(); i++)
{(*i)->Disconnect(wxEVT_MOTION,
wxMouseEventHandler(xList::OnMoveDrag)
);
(*i)->Disconnect(wxEVT_LEFT_UP,
wxMouseEventHandler(xList::OnEndDrag)
);
}
}
xList::xList (DnDxList& dnd,
wxWindow *parent,
wxWindowID winid,
const wxPoint& pos,
const wxSize& size,
long style,
const wxValidator &validator,
const wxString &name
): wxListCtrl (parent, winid, pos, size, style, validator, name),
dndsource (dnd)
{Connect(wxEVT_COMMAND_LIST_BEGIN_DRAG,
(wxObjectEventFunction)&xList::OnBeginDrag
);
dndsource.AddList (this);
};
void xList::OnBeginDrag(wxListEvent& event) // begin drag
{SetCursor(wxCursor(wxCURSOR_HAND));
dndsource.BeginDrag();
}
void xList::OnMoveDrag(wxMouseEvent& event)
{std::cout << "Movie: " << this << std::endl; // to show the object for which the move event is called for
}
void xList::OnEndDrag(wxMouseEvent& event)
{std::cout << "End: " << this << std::endl;
dndsource.EndDrag();
SetCursor(wxCursor(*wxSTANDARD_CURSOR));
}
class xFrame: public wxFrame
{
public:
xFrame (const wxString& title,
const wxPoint& pos,
const wxSize& size
);
~xFrame () { }
private:
void OnExit(wxCommandEvent& event);
DECLARE_EVENT_TABLE();
DnDxList* dndxlist;
xList* lp;
xList* rp;
wxPanel* panel;
};
BEGIN_EVENT_TABLE(xFrame, wxFrame)
EVT_MENU(wxID_EXIT, xFrame::OnExit)
END_EVENT_TABLE()
xFrame::xFrame(const wxString& title,
const wxPoint& pos,
const wxSize& size
): wxFrame(NULL, wxID_ANY, title, pos, size)
{
panel = new wxPanel(this);
wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
// create common DnDxList
dndxlist = new DnDxList();
// create two panels
lp = new xList (*dndxlist,
panel,
wxID_ANY,
wxDefaultPosition,
wxDefaultSize,
wxLC_REPORT | wxLC_SINGLE_SEL
);
rp = new xList (*dndxlist,
panel,
wxID_ANY,
wxDefaultPosition,
wxDefaultSize,
wxLC_REPORT | wxLC_SINGLE_SEL
);
// some contents
lp->InsertColumn(0, _("A"));
lp->InsertColumn(1, _("B"));
lp->InsertColumn(2, _("C"));
lp->InsertColumn(3, _("D"));
lp->SetColumnWidth(0, 100);
lp->SetColumnWidth(1, 100);
lp->SetColumnWidth(2, 100);
lp->SetColumnWidth(3, 100);
for (long i = 0; i < 100; i++)
{lp->InsertItem(i, 1);
for (int j = 0; j < 4; j++)
{wxString s;
s << _("lp [") << i << _(", ") << j << _("]");
lp->SetItem (i, j, s);
}
}
rp->InsertColumn(0, _("A"));
rp->InsertColumn(1, _("B"));
rp->InsertColumn(2, _("C"));
rp->InsertColumn(3, _("D"));
rp->SetColumnWidth(0, 100);
rp->SetColumnWidth(1, 100);
rp->SetColumnWidth(2, 100);
rp->SetColumnWidth(3, 100);
for (long i = 0; i < 100; i++)
{rp->InsertItem(i, 1);
for (int j = 0; j < 4; j++)
{wxString s;
s << _("rp [") << i << _(", ") << j << _("]");
rp->SetItem (i, j, s);
}
}
sizer->Add(lp,1, wxEXPAND | wxALL, 10);
sizer->Add(rp,1, wxEXPAND | wxALL, 10);
panel->SetSizer(sizer);
}
void xFrame::OnExit(wxCommandEvent& event)
{
Close( true );
}
class xApp: public wxApp
{
public:
virtual bool OnInit();
};
IMPLEMENT_APP(xApp);
bool xApp::OnInit()
{
xFrame *frame = new xFrame(_("Frame"), wxPoint(50, 50), wxSize(450, 340) );
frame->Show(true);
return true;
}
コンソール出力を見ると、マウス モーション イベントとマウス左上げイベントは、実際にマウスがオンになっているオブジェクトではなく、ドラッグが開始される同じオブジェクトのメソッドを常に呼び出すことがわかります。