Показаны сообщения с ярлыком wxWidgets. Показать все сообщения
Показаны сообщения с ярлыком wxWidgets. Показать все сообщения

воскресенье, 3 июля 2011 г.

Model-View-Controller (MVC) + wxWidgets



Интерфейс "Наблюдатель" (Observer)



1 #ifndef OBSERVER_H
2 #define OBSERVER_H 1
3 class Observer
4 {
5 public:
6 virtual void update(){}
7 };
8 #endif




Описание модели (Model)



1 #ifndef MODEL_H
2 #define MODEL_H 1
3
4 #include <wx/string.h>
5 #include <set>
6
7 #include "Observer.h"
8
9 class Model
10 {
11 public:
12 Model(int d);
13 void setData(const int d);
14 int getData()const;
15 ~Model(){};
16 private:
17 int d_;
18 std::set<Observer*> registry;
19 public:
20 void attach(Observer*s);
21 void detach(Observer*s);
22 void notify();
23 // void clearRegistry();
24 };
25 #endif




Определение модели



1 #include "Model.h"
2
3 Model::Model(int d):d_(d) {};
4
5 void Model::setData(const int d)
6 {
7 d_=d;
8 notify();
9 }
10
11 int Model::getData()const
12 {
13 return d_;
14 }
15
16 void Model::attach(Observer*s)
17 {
18 registry.insert(s);
19 }
20
21 void Model::detach(Observer*s)
22 {
23 registry.erase(s);
24 }
25
26 void Model::notify()
27 {
28 std::set<Observer*>::iterator it;
29 for (it=registry.begin(); it!=registry.end(); it++)
30 (*it)->update();
31 }
32
33




Обобщенное представление (View)



1 #ifndef VIEW_H
2 #define VIEW_H 1
3 class Controller;
4 #include "Observer.h"
5 #include "Model.h"
6 #include "Controller.h"
7 class View: public Observer
8 {
9 protected:
10 Model *myModel;
11 Controller *myController;
12 public:
13 View(Model *m);
14 virtual ~View();
15 virtual void update();
16 virtual void draw();
17 virtual void initialize();
18 virtual Controller* makeController();
19 Model* getModel();
20 Controller *getController();
21 public:
22 virtual void setConroller(Controller *ctrl);
23 };
24 #endif




Определения методов класса View



1 #include "View.h"
2
3 View::View(Model *m):myModel(m),myController(0)
4 {
5 myModel->attach(this);
6 }
7
8 View::~View()
9 {
10 myModel->detach(this);
11 }
12
13 void View::initialize()
14 {
15 myController=makeController();
16 }
17
18 Controller* View::makeController()
19 {
20 return new Controller(this);
21 }
22
23 Model* View::getModel()
24 {
25 return myModel;
26 }
27
28 Controller * View::getController()
29 {
30 return myController;
31 }
32
33 void View::update()
34 {
35 this->draw();
36 }
37
38 void View::draw() {}
39
40 void View::setConroller(Controller *ctrl)
41 {
42 myController=ctrl;
43 }




Контроллер (Controller)



1 #ifndef CONTROLLER_H
2 #define CONTROLLER_H 1
3 #include <wx/event.h>
4 class View;
5 #include "Observer.h"
6 #include "View.h"
7 #include "Model.h"
8 typedef wxCommandEvent Event;
9 class Controller : public Observer
10 {
11 public:
12 virtual void handleEvent(Event *);// default = no op
13
14 Controller(View* v) ;
15 Controller() ;
16 virtual ~Controller();
17 virtual void update(); // default = no op
18 protected:
19 Model *myModel;
20 View *myView;
21 };
22 #endif




Определения методов контроллера



1 #include "Controller.h"
2 void Controller::handleEvent(Event *) {}
3 Controller::Controller(View* v) : myView(v)
4 {
5 myModel = myView->getModel();
6 myModel->attach(this);
7 }
8
9 Controller::~Controller()
10 {
11 myModel->detach(this);
12 }
13
14 void Controller::update() {}




Описание класса представления TextViewVal, реализующего отображение данных на основе wxStaticText



1 #ifndef TEXTVIEWVAL_H
2 #define TEXTVIEWVAL_H 1
3 #include <wx/stattext.h>
4 #include "View.h"
5 #include "TextControllerVal.h"
6 class TextViewVal:
public View ,public wxStaticText
7 {
8 public:
9 TextViewVal(wxWindow *parent,wxWindowID id,Model *m, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize,
long style=0, const wxString &name=wxStaticTextNameStr);
10 ~TextViewVal() ;
11 virtual void draw();
12 virtual Controller *makeController();//+
13 };
14 #endif




Определения методов класса TextViewVal



1 #include "TextViewVal.h"
2 TextViewVal::TextViewVal(wxWindow *parent,wxWindowID id,Model *m, const wxPoint &pos, const wxSize &size,
long style, const wxString &name):View(m),wxStaticText(parent,id, wxString::Format(wxT("%d"),m->getData()), pos,size,style,
name) {}
3
4 TextViewVal::~TextViewVal() {}
5
6 void TextViewVal::draw()
7 {
8 SetLabel(wxString::Format(wxT("%d"),myModel->getData()));
9 }
10
11 Controller* TextViewVal::makeController()
12 {
13 return new TextControllerVal(this->GetParent(), -1,this);
14 }




Контроллер для связи Модели с Отображением



1 #ifndef TEXTCONTROLLERVAL_H
2 #define TEXTCONTROLLERVAL_H 1
3 #include <wx/textctrl.h>
4 #include "Controller.h"
5 #include "TextViewVal.h"
6 class TextViewVal;
7 class TextControllerVal : public Controller,public wxTextCtrl
8 {
9 public:
10 TextControllerVal(wxWindow* parent, wxWindowID id,TextViewVal *tv, const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize, long style = 0, const wxValidator& validator = wxDefaultValidator,
const wxString& name = wxTextCtrlNameStr) ;
11 virtual void handleEvent(Event *e);
12 };
13 #endif




Определения методов класса TextControllerVal



1 #include "TextControllerVal.h"
2 TextControllerVal::TextControllerVal(wxWindow* parent, wxWindowID id,TextViewVal *tv, const wxPoint& pos,
const wxSize& size , long style, const wxValidator& validator, const wxString& name ):Controller((View*)tv),wxTextCtrl(parent,
id, wxString::Format(wxT("%d"),tv->getModel()->getData()), pos, size, style , validator , name){}
3
4 void TextControllerVal::handleEvent(Event *e)
5 {
6 myModel->setData(wxAtoi(e->GetString().c_str()));
7 }




Описание класса диалога для размещения Представлений и Контроллера



1 #ifndef TEXTDLGVAL_H
2 #define TEXTDLGVAL_H 1
3 #include <wx/dialog.h>
4 #include "TextViewVal.h"
5 class TextDlgVal : public wxDialog
6 {
7 public:
8 TextDlgVal(wxDialog* parent,wxString& title,Model* m);
9 virtual ~TextDlgVal();
10 protected:
11 enum
12 {
13 ID_TXTVAL=1000
14 };
15
16 Model* model_;
17 TextViewVal * view_;
18 TextViewVal * view2_;
19 TextControllerVal *controller_;
20
21 private:
22 void OnClose(wxCloseEvent &event);
23 void OnText(wxCommandEvent &event);
24
25 DECLARE_EVENT_TABLE()
26 };
27 #endif




Определения класса диалога для размещения Контроллера и двух экземпляров класса Представления



1 #include "TextDlgVal.h"
2 BEGIN_EVENT_TABLE(TextDlgVal, wxDialog)
3 EVT_CLOSE(TextDlgVal::OnClose)
4 EVT_TEXT(ID_TXTVAL, TextDlgVal::OnText)
5 END_EVENT_TABLE()
6
7 TextDlgVal::TextDlgVal(wxDialog* parent,wxString& title,Model* m):wxDialog(parent,-1,title),model_(m),view_(0),controller_(0)
8 {
9 this->SetSizeHints(wxDefaultSize, wxDefaultSize);
10 wxBoxSizer* bSizer1;
11
12 bSizer1 = new wxBoxSizer(wxVERTICAL);
13
14 view_=new TextViewVal(this,-1,m);
15 view2_=new TextViewVal(this,-1,m);
16
17 view_->initialize();//Инициализируем дл� нашего пред�тавлени� контроллер
18 controller_=(TextControllerVal*) view_->getController();//
19 controller_->SetId(ID_TXTVAL);//Делаем возможным обработку �обытий от контроллера
20
21 //Св�жем пред�тавление view2_ � контроллером
22 view2_->setConroller(controller_);
23
24 bSizer1->Add(view_, 0, wxALL|wxEXPAND, 5);
25 bSizer1->Add(view2_, 0, wxALL|wxEXPAND, 5);
26
27 bSizer1->Add(controller_, 1, wxEXPAND, 5);
28
29 this->SetSizer(bSizer1);
30 this->Layout();
31 bSizer1->Fit(this);
32 }
33
34 TextDlgVal::~TextDlgVal(){}
35
36 void TextDlgVal::OnClose(wxCloseEvent &event)
37 {
38 Destroy();
39 }
40
41 void TextDlgVal::OnText(wxCommandEvent &event)
42 {
43 controller_->handleEvent(&event);
44 }
45




Класс приложения wxWidgets



1 #ifndef MVC_TAPP_H
2 #define MVC_TAPP_H
3 #include <wx/app.h>
4 class MVC_TApp : public wxApp
5 {
6 public:
7 virtual bool OnInit();
8 };
9 #endif // MVC_TAPP_H




Определение приложения



1 #ifdef WX_PRECOMP
2 #include "wx_pch.h"
3 #endif
4
5 #ifdef __BORLANDC__
6 #pragma hdrstop
7 #endif //__BORLANDC__
8
9 #include "MVC_TApp.h"
10 #include "TextDlgVal.h"
11
12 IMPLEMENT_APP(MVC_TApp);
13
14 bool MVC_TApp::OnInit()
15 {
16 Model* m_=new Model(10);
17 wxString stro=wxT("MVC TEST");
18
19 TextDlgVal* v1_ = new TextDlgVal(0L,stro,m_);
20 v1_->Show();
21
22 return true;
23 }




Модуль для прекомпиляции (можно и без него обойтись)



1 #ifndef WX_PCH_H_INCLUDED
2 #define WX_PCH_H_INCLUDED
3
4 // basic wxWidgets headers
5 #include <wx/wxprec.h>
6
7 #ifdef __BORLANDC__
8 #pragma hdrstop
9 #endif
10
11 #ifndef WX_PRECOMP
12 #include <wx/wx.h>
13 #endif
14
15 #ifdef WX_PRECOMP
16 // put here all your rarely-changing header files
17 #endif // WX_PRECOMP
18
19 #endif // WX_PCH_H_INCLUDED



воскресенье, 1 мая 2011 г.

Настройка CodeBlocks для компиляции wxWidgets / Win32 приложений для Windows компилятором Mingw32 из под Linux/FreeBSD

Установка CodeBlocks из портов:

portinstall codeblocks


Запускаем CodeBlocks, далее меню "Settings" -> "Compiler and Debugger" -> "Selected compiler"
"GNU GCC Compiler" -> "Copy"
задаем имя компилятора "MinGW32 Compiler"

Для этого компилятора задаём:
в "#defines"

WINVER=0x0400
__WIN95__
__GNUWIN32__
STRICT
HAVE_W32API_H
__WXMSW__
__WINDOWS__

в "Toolchain executables" пропишем
"Compiler's installation directory" ~/mingw-cross-env/usr или что там у вас.








"C compiler:"i686-pc-mingw32-gcc
"C++ compiler:"i686-pc-mingw32-g++
"Linker for dynamic libs:"i686-pc-mingw32-g++
"Linker for static libs:" i686-pc-mingw32-ar
"Debugger:"i686-pc-mingw32-gdb
"Resorce compiler:"i686-pc-mingw32-windres
"Make program:"make

По поводу i686-pc-mingw32-gdb, надо создать скрипт ~/mingw-cross-env/usr/bin/i686-pc-mingw32-gdb

cd ~/mingw-cross-env
make gdb
touch ~/mingw-cross-env/usr/bin/i686-pc-mingw32-gdb
echo '#!/bin/csh' >> ~/mingw-cross-env/usr/bin/i686-pc-mingw32-gdb
echo 'wine ~/mingw-cross-env/usr/i686-pc-mingw32/bin/gdb.exe "$@"' >> ~/mingw-cross-env/usr/bin/i686-pc-mingw32-gdb
chmod +x ~/mingw-cross-env/usr/bin/i686-pc-mingw32-gdb



Да и ещё, некоторые общие настройки, хотя и без них wxWidgets приложение соберется, прописать в
"Other Linker Options":
-lstdc++
-lgcc
-lodbc32
-lwsock32
-lwinspool
-lwinmm
-lshell32
-lcomctl32
-lctl3d32
-lodbc32
-ladvapi32
-lodbc32
-lwsock32
-lopengl32
-lglu32
-lole32
-loleaut32
-luuid

Прописать в "Search directories"
Для Compiler путь к include: ~/mingw-cross-env/usr/i686-pc-mingw32/include
Для Linker путь к lib: ~/mingw-cross-env/usr/i686-pc-mingw32/lib
Для Resource compiler: ~/mingw-cross-env/usr/i686-pc-mingw32/include

Жмём "OK"

Из под su, делал так:
ln -s /usr/local/bin/wine /usr/local/bin/wine-auto

При создании нового проекта, надо выбирать "MinGW32 Compiler"
Для новых wxWidgets проектов надо прописывать:
В "Project build options" пропишем
в "Other options":

`i686-pc-mingw32-wx-config --cxxflags`


в "Other linker options:"

`i686-pc-mingw32-wx-config --libs`



Если использовать мастер для создания проекта, то надо wx-config заменить на i686-pc-mingw32-wx-config, для этого можно открыть Ваш файл проекта CodeBlocks (*.cbp) в обычном текстовом редакторе, например, gedit и произвести замену.

Имеются некоторые проблемы при запуске программ после сборки из CodeBlocks, но в общем можно запустить с отладчиком, правда CodeBlocks 10.05 может "рухнуть", было один раз.

В общем, то и все, можно правда некоторые опции компилятора задействовать, например -s, что делает strip, уменьшая размер исполняемого файла.

суббота, 30 апреля 2011 г.

Компилируем wxWidgets приложение для Windows из под FreeBSD

Можно скомпилировать приложение minimal из примеров, поставляемых вместе с wxWidgets.
Использовать будем mingw-cross-env, да к стати из портов можно установить mercurial, чтоб установить последнюю версию mingw-cross-env для этого запускаем:

hg clone http://hg.savannah.nongnu.org/hgweb/mingw-cross-env

Чтоб добыть обновления, запускаем:

hg pull -u


В общем после установки wxwidgets, т.е. после выполнения команд:

cd mingw-cross-env
gmake wxwidgets


В директории с кодом простого wxWidgets приложения выполним:

i686-pc-mingw32-g++ minimal.cpp -o minimal.exe `i686-pc-mingw32-wx-config --cxxflags --libs`

В текущей директории появляется minimal.exe, правда его размер несколько впечатляет почти 7 Мбайт. Можно его уменьшить командой:

i686-pc-mingw32-strip minimal.exe

Почти в два раза.

wine minimal.exe

При записке minimal.exe под Windows 98 , а также wine, при условии, что там в настройках (команда winecfg) стоит Windows 98, может вылести сообщение "wxWidgets Fatal Error\n This program uses Unicode and requires Windows NT/2000/XP ...". Ничего страшного, можно просто перекомпилировать minimal.cpp без поддержки Unicode.

i686-pc-mingw32-g++ minimal.cpp -o minimal.exe `i686-pc-mingw32-wx-config -nounicode --cxxflags --libs`


Об опциях i686-pc-mingw32-wx-config можно узнать командой:

i686-pc-mingw32-wx-config

правда не все опции могут в действительности дать желаемый эффект, например, думал, что опция --release уменьшит размер файла за счет исключения отладочной информации, ну да ладно, strip есть.

воскресенье, 26 сентября 2010 г.

Простои проект C++ с использованием wxWidgets

Понадобится кроссплатформенная утилита bakefile для поддержки генерации make-файлов и файлов-проектов для разных платформ и сред программирования. Для её использования понадобится python. Будем считать, что с установкой wxWidgets справились все. У меня, например, для этого создан командный файл build_cl.cmd в каталоге %WXWIN%\build\msw. %WXWIN% - переменная среды, содержащая путь к wxWidgets (не должен содержать пробелов). Использую, компилятор C++ идущий вместе с Microsoft Visual C++ 2005 Express Edition, установил его без IDE и MSDN, ещё установлен MS PSDK для работы.

call vcvars32
nmake -f makefile.vc MONOLITHIC=0 SHARED=0 UNICODE=1 BUILD=release
pause

В директории проекта создадим поддиректорию build, в ней создадим файл app.bkl, следующего содержания:


1 <?xml version="1.0" ?>
2 <!-- $Id$ -->
3
4 <makefile>
5
6 <!-- Путь к файлу wx.bkl, хотя можно их таскать в
۠отдельной директории с именем presets в
۠директории проекта -->

7 <include file="C:/wxWidgets-2.9.1/build/bakefiles/wxpresets/presets/wx.bkl" />
8
9 <!-- Определяем переменную BUILDDIR в стиле wxWidgets -->
10 <set-wxlike-builddir> </set-wxlike-builddir>
11
12 <exe id="app" template="wxgui">
13
14 <debug-info>off</debug-info>
15 <runtime-libs>dynamic</runtime-libs>
16
17 <!-- Здесь всякие опции для линковщика -->
18 <ldflags cond="FORMAT=='msvc'">/OPT:REF</ldflags>
19 <ldflags cond="FORMAT=='msvc'">/OPT:ICF</ldflags>
20 <ldflags cond="FORMAT=='msvc6prj'">/entry:"wWinMainCRTStartup"</ldflags>
21
22 <!-- Исходники -->
23 <sources>$(fileList('../src/*.cpp'))</sources>
24 <headers>$(fileList('../src/*.h'))</headers>
25 <win32-res>$(fileList('../src/*.rc'))</win32-res>
26 <symbian-res>$(fileList('../src/*.rss'))</symbian-res>
27
28 <!-- Здесь используемые в проекте библиотеки
۠wxWidgets -->

29 <wx-lib>core</wx-lib>
30 <wx-lib>base</wx-lib>
31 </exe>
32
33 </makefile>



Как видим, используется XML-формат. Чтобы bakefile не ругался на строки, где содержатся кириллические символы, файл должен быть в кодировке UTF-8. Имена тегов должны быть в нижнем регистре.

Для генерации makefile.vc использую командный файл, следующего содержания:

bakefile -f msvc app.bkl
call vcvars32
pause

Для сборки проекта использую командный файл, следующего содержания:

nmake /f makefile.vc WX_MONOLITHIC=0 WX_SHARED=0 WX_UNICODE=1 WX_DEBUG=0
pause


Исходники, файлы ресурсов и заголовочные файлы находятся в папке src.
В простейшем случае, там расположены следующие файлы:
app.h
app.cpp
frame.h
frame.cpp
minimal.rc
mondrian.ico
mondrian.xpm

Содержание файла app.h :

1 #include <wx/app.h>
2 #if !defined(__WXMSW__) && !defined(__WXPM__)
3 #include "mondrian.xpm"
4 #endif
5
6 #include "frame.h"
7
8 class App : public wxApp
9 {
10 public:
11 virtual bool OnInit();
12 };


Содержание файла app.cpp :

1 /// app.cpp
2 #include "app.h"
3
4 bool App::OnInit()
5 {
6 if ( !wxApp::OnInit() )
7 return false;
8
9 Frame *frame = new Frame(_T("Только фрейм"));
10 frame->Show(true);
11 return true;
12 }
13
14 IMPLEMENT_APP(App)



Содержание файла frame.h :

1 #include <wx/frame.h>
2 class Frame : public wxFrame
3 {
4 public:
5 Frame(const wxString& title);
6 private:
7 DECLARE_EVENT_TABLE()
8 };
9
10 //Идентификаторы элементов управления, которые должны реагировать на события
11 enum
12 {
13
14 };
15
16



Содержание файла frame.cpp :

1 #include "frame.h"
2
3 //Таблица событий для связи методов и идентификаторов с определенным типом
» сообщения

4 BEGIN_EVENT_TABLE(Frame, wxFrame)
5
6 END_EVENT_TABLE()
7
8 // Конструктор
9 Frame::Frame(const wxString& title)
10 : wxFrame(NULL, wxID_ANY, title)
11 {
12 SetIcon(wxICON(mondrian_xpm));
13 }
14



Содержание файла ресурсов minimal.rc :

mondrian_xpm ICON "mondrian.ico"
#include "wx/msw/wx.rc"

четверг, 3 июня 2010 г.

find_package(wxWidgets)

Решил использовать cmake, сюрпризом было, то что find_package(wxWidgets REQUIRED) не находил библиотеку wxWidgets, все получилось после выполнения следующих команд:

cd %WXWIN%\build\msw
call vcvars32
nmake -f makefile.vc MONOLITHIC=0 SHARED=0 UNICODE=1 BUILD=debug

Таким образом, успешность поиска wxWidgets зависит от наличия debug версии сборки библиотеки ...