Sl-Alex домашняя лаборатория

Руководство по WxWidgets: 9. Перетаскивание

Просмотров: 1799Комментарии: 0
Статьи
Руководство по WxWidgets: 9. Перетаскивание

Википедия: в GUI драг-н-дроп - это действие (или поддержка действия) при котором кликаешь на виртуальном объекте и тащишь его в другое место, или в другой виртуальный объект. В основном, это используется для вызова различных типов действий, или для создания различных типов связей между абстрактными объектами.

Функциональность драг-н-дроп - это одна из наиболее очевидных сторон GUI. Драг-н-дроп позволяет выполнять множество сложных действий практически интуитивно.

Выполняя перетаскивание мы, по существу, передаём данные из источника в приёмник. Итак, нам нужно следующее:

  • Data object (объект данных)
  • Data source (источник данных)
  • Data target (приёмник данных)

Для перетаскивания текста в wxWidgets есть встроенный класс wxTextDropTarget.

В следующем примере, мы реализуем возможность перетаскивать имена файлов из верхнего списка в нижний.

textdrop.h
#include <wx/wx.h>
#include <wx/dnd.h>
class TextDrop : public wxFrame
{
public:
	TextDrop(const wxString& title);
    
	void OnSelect(wxCommandEvent& event);
	void OnDragInit(wxListEvent& event);
	wxGenericDirCtrl *m_gdir;
	wxListCtrl *m_lc1;
	wxListCtrl *m_lc2;
};
class MyTextDropTarget : public wxTextDropTarget
{
public:
	MyTextDropTarget(wxListCtrl *owner);
	virtual bool OnDropText(wxCoord x, wxCoord y, 
		const wxString& data);
	wxListCtrl *m_owner;
};
textdrop.cpp
#include "textdrop.h"
#include <wx/treectrl.h>
#include <wx/dirctrl.h>
#include <wx/dir.h>
#include <wx/splitter.h>
TextDrop::TextDrop(const wxString& title)
	: wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(300, 200))
{
	wxSplitterWindow *spl1 = new wxSplitterWindow(this, -1);
	wxSplitterWindow *spl2 = new wxSplitterWindow(spl1, -1);
	m_gdir = new wxGenericDirCtrl(spl1, -1, wxT("/home/"), 
		wxPoint(-1, -1), wxSize(-1, -1), wxDIRCTRL_DIR_ONLY);
	m_lc1 = new wxListCtrl(spl2, -1, wxPoint(-1, -1), 
		wxSize(-1, -1), wxLC_LIST);
	m_lc2 = new wxListCtrl(spl2, -1, wxPoint(-1, -1), 
		wxSize(-1, -1), wxLC_LIST);
	MyTextDropTarget *mdt = new MyTextDropTarget(m_lc2);
	m_lc2->SetDropTarget(mdt);
	Connect(m_lc1->GetId(), wxEVT_COMMAND_LIST_BEGIN_DRAG, 
		wxListEventHandler(TextDrop::OnDragInit));
	wxTreeCtrl *tree = m_gdir->GetTreeCtrl();
	spl2->SplitHorizontally(m_lc1, m_lc2);
	spl1->SplitVertically(m_gdir, spl2);
	Connect(tree->GetId(), wxEVT_COMMAND_TREE_SEL_CHANGED, 
		wxCommandEventHandler(TextDrop::OnSelect));
	Center();
}
MyTextDropTarget::MyTextDropTarget(wxListCtrl *owner)
{
	m_owner = owner;
}
bool MyTextDropTarget::OnDropText(wxCoord x, wxCoord y, 
	const wxString& data)
{
	m_owner->InsertItem(0, data);
	return true;
}
void TextDrop::OnSelect(wxCommandEvent& event)
{
	wxString filename;
	wxString path = m_gdir->GetPath();
	wxDir dir(path);
	bool cont = dir.GetFirst(&filename, wxEmptyString, wxDIR_FILES);
	int i = 0;
	m_lc1->ClearAll();
	m_lc2->ClearAll();
	while ( cont )
	{
		m_lc1->InsertItem(i, filename);
		cont = dir.GetNext(&filename);
		i++;
	}
}
void TextDrop::OnDragInit(wxListEvent& event)
{
	wxString text = m_lc1->GetItemText(event.GetIndex());
  
	wxTextDataObject tdo(text);
	wxDropSource tds(tdo, m_lc1);
	tds.DoDragDrop(wxDrag_CopyOnly);
}
main.h
#include <wx/wx.h>
class MyApp : public wxApp
{
	public:
		virtual bool OnInit();
};
main.cpp
#include "main.h"
#include "textdrop.h"
IMPLEMENT_APP(MyApp)
bool MyApp::OnInit()
{
	TextDrop *td = new TextDrop(wxT("TextDrop"));
	td->Show(true);
	return true;
}

В нашем примере мы имеем окно разделённое на три части. Это сделано с помощью виджета wxSplitterWindow. В левой части окна находится общий список директорий. Мы отображаем все директории доступные в файловой системе. В правой части мы имеем два окна. Первое отображает все файлы в выбранной директории. Второе используется для перетаскивания файлов.

MyTextDropTarget *mdt = new MyTextDropTarget(m_lc2);
m_lc2->SetDropTarget(mdt);

Здесь мы определяем приёмник для перетаскиваемого текста.

wxString text = m_lc1->GetItemText(event.GetIndex());
wxTextDataObject tdo(text);
wxDropSource tds(tdo, m_lc1);
tds.DoDragDrop(wxDrag_CopyOnly);

В методе OnDragInit() мы определили объект текстовых данных и объект источника для перетаскивания. Мы вызываем метод DoDragDrop(). Константа wxDrag_CopyOnly позволяет только копировать данные.

bool MyTextDropTarget::OnDropText(wxCoord x, wxCoord y, 
	const wxString& data)
{
	m_owner->InsertItem(0, data);
	return true;
}

Выполняя операцию перетаскивания, мы добавляем текстовые данные в список.

Рисунок 9.1: Drag & Drop

Рисунок 9.1: Drag & Drop

Остальные материалы курса:

Вступление

1. Вспомогательные классы

2. Первые программы

3. Меню и панели инструментов

4. Управление компоновкой

5. События

6. Диалоги

7. Виджеты часть 1

8. Виджеты часть 2

9. Перетаскивание

10. Контексты устройств

11. Самодельные виджеты

12. Тетрис в wxWidgets

Примечание

Оригинал руководства расположен здесь. Автор оригинала - Jan Bodnar.

Перевод (без разметки и картинок) был выполнен пользователем ber113 с сайта translated.by. К сожалению, сайт сейчас не работает.

Данный документ представляет собой компиляцию указанных документов с сохранением оригинальной разметки и иллюстраций.