Programowanie GUI
Transkrypt
Programowanie GUI
Programowanie graficznego interfejsu użytkownika Wykład 6 Maciej Wołoszyn mailto:[email protected]∗ 5 kwietnia 2006 Spis treści 1 wxWidgets c.d. 1.1 1.2 1.3 1.4 1.5 1 Prekompilowane pliki nagłówkowe (PCH) Model okna . . . . . . . . . . . . . . . . Tworzenie i usuwanie okien . . . . . . . Wybrane widgety . . . . . . . . . . . . . Rozmieszczanie widgetów . . . . . . . . 1.5.1 Dost˛epne układy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 2 3 4 7 8 1 wxWidgets c.d. 1.1 Prekompilowane pliki nagłówkowe (PCH) • w celu przyspieszenia procesu kompilacji można skorzystać z prekompilowanych plików nagłówkowych (jeśli używamy kompilatora dajacego ˛ taka˛ możliwość) • należy wydzielić w tym celu plik nagłówkowy (najwyżej jeden na jednostk˛e kompilacji) i skompilować go z opcjami identycznymi jak używane do kompilowania plików źródłowych ∗ Prosz˛ e o przesyłanie na ten adres informacji o znalezionych bł˛edach, literówkach oraz propozycji zmian i uzupełnień. Dokument przygotowano za pomoca˛ systemu LATEX. Prawa autorskie zastrzeżone. 1 Programowanie GUI – Wykład 6 2 Przykład dla kompilatora gcc1 : 5 P01.h #include <wx/wx.h> $ g++ ‘wx-config --cxxflags‘ -D_REENTRANT -c P01.h → plik P01.h.gch (∼35 MB) 5 P01.cpp #include "P01.h" class MyFrame : public wxFrame { // ... $ g++ ‘wx-config --cxxflags --libs‘ P01.cpp sposób kompilacji zwykły PCH czas [s] 11.2 2.2 1.2 Model okna • okno to obszar, który może: – zawierać inne okna (w tym paski menu, narz˛edzi, statusu) – być ukryty lub uwidoczniony – dopuszczać zmian˛e rozmiaru – „narysować si˛e” • zwykle jest skojarzony z obiektem klasy wxWindow lub potomnej • rozmiar okna określa wymiary zewn˛etrzne (zawiera w sobie dekoracj˛e okna itp.) obszar wewn˛etrzny (client area) to cz˛eść okna, w˛ewnatrz ˛ której można rysować albo umieszczać inne okna • tylko okna na najwyższym poziomie hierarchii (top-level windows, np. wxFrame, wxDialog) moga˛ być tworzone z wartościa˛ NULL jako wskaźnik do okna macierzystego 1 Powody użycia makra _REENTRANT sa˛ omówione np. pod adresem http://gcc.gnu.org/bugzilla/ show_bug.cgi?id=11953 (dotyczy tylko gcc<4.1); w razie problemów przydatna opcja -Winvalid-pch Programowanie GUI – Wykład 6 3 1.3 Tworzenie i usuwanie okien • najcz˛eściej widgety tworzone sa˛ operatorem new: – w jednym kroku wxButton* b = new wxButton(parent,wxID_OK); – za pomoca˛ dwóch instrukcji: konstruktora domyślnego oraz funkcji Create przyjmujacej ˛ takie same argumenty jak pełny konstruktor wxButton* b=new wxButton; b->Create(parent,wxID_OK); w drugim przypadku dopiero uruchomienie Create powoduje utworzenie widgetu gotowego do wyświetlenia (i wygenerowanie zdarzenia wxEVT_CREATE) – można wcześniej określić dodatkowe właściwości obiektu • przekazanie wskaźnika do okna macierzystego zapewnia dołaczenie ˛ do niego bieżacego ˛ obiektu – zostanie on automatycznie usuni˛ety gdy niszczony jest „rodzic” • wszystkie widgety za wyjatkiem ˛ tych na najwyższym poziomie hierarchii (wxFrame, wxDialog) tworzone sa˛ jako widoczne – b˛eda˛ wi˛ec widoczne, jeśli rodzic jest widoczny – można je ukryć wywołujac ˛ Show(false) • wxFrame oraz wxDialog nie sa˛ po utworzeniu wyświetlane aby umożliwić rozmieszczenie w nich innych widgetów bez niepożadanych ˛ efektów wizualnych (np. migotania) – sa˛ wyświetlane dopiero po użyciu Show lub dla okien modalnych ShowModal • okna typu top-level likwiduje si˛e w bezpieczny sposób uruchamiajac ˛ metod˛e Destroy, co zapewnia obsłużenie wszystkich oczekujacych ˛ zdarzeń przed ostatecznym usuni˛eciem obiektu • dołaczone ˛ do okna macierzystego widgety (typu child) rzadko sa˛ likwidowane bezpośrednio – zostana˛ usuni˛ete wraz z usuni˛eciem „rodzica” • do typowych argumentów konstruktorów okien należa˛ (poza wskaźnikiem do okna macierzystego): – identyfikator (wartość typu wxWindowID, np. wxID_ANY) – pozycja (wxPoint, domyślna wartość wxDefaultPosition) – rozmiar (wxSize, domyślnie wxDefaultSize) – nazwa (wxString, rzadko używana poza środowiskami Motif i Xt) Programowanie GUI – Wykład 6 4 ˛ okna za pomoca˛ – styl (long, domyślnie 0) – pozwala określić szczegóły wygladu stałych połaczonych ˛ bitowym OR, np. wxCAPTION | wxMINIMIZE_BOX oprócz styli odziedziczonych po klasie wxWindow widgety w wi˛ekszości dodaja˛ kolejne style 1.4 Wybrane widgety • klasy podstawowe: – wxWindows – bazowa dla wszystkich okien (widgetów); bardzo duży zbiór funkcji składowych – wxControl – bazowa dla elementów sterujacych, ˛ takich jak np. wxButton – wxControlWithItems – j.w., ale dla elementów składajacych ˛ si˛e z wielu pozycji • okna: – wxFrame – skalowalne okno mogace ˛ zawierać inne widgety; cz˛esto używane do tworzenia głównego okna programu – wxDialog – skalowalne okno wyboru – wxPopupWindow – minimalna ilość dekoracji okna – wxMDIParentFrame, wxMDIChildFrame (MDI = Multiple Document Interface, przestarzały?) Przykład: class MyFrame: public wxMDIParentFrame { public: MyFrame(const wxString& title); }; MyFrame::MyFrame(const wxString& title) : wxMDIParentFrame(NULL,wxID_ANY,title){ wxMDIChildFrame* child = new wxMDIChildFrame(this,wxID_ANY,"Child"); child->Show(true); } class MyApp: public wxApp { virtual bool OnInit(); }; Programowanie GUI – Wykład 6 5 bool MyApp::OnInit() { MyFrame *frame = new MyFrame( "P02"); frame->Show(true); return true; } IMPLEMENT_APP(MyApp) • pojemniki: – wxPanel – okno, na którym można rozmieścić elementy sterujace ˛ (zamiast bezpośrednio na wxFrame, ale wtedy bez możliwości sterowania klawiatura˛ i bezpośredniego rysowania na każdej platformie) – wxScrolledWindow – wxNotebook – zakładki (karty) MyFrame::MyFrame(const wxString& title) : wxFrame(NULL, wxID_ANY, title) { wxNotebook* nb = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_RIGHT); wxPanel* w1 = new wxPanel(nb,wxID_ANY); wxPanel* w2 = new wxPanel(nb,wxID_ANY); nb->AddPage(w1, "Aaa...", true); nb->AddPage(w2, "Bbb...", false); } Programowanie GUI – Wykład 6 • elementy sterujace ˛ (kontrolki): – dynamiczne (reagujace ˛ na działania użytkownika): ∗ wxButton – przycisk ∗ wxBitmapButton – przycisk z graficzna˛ etykieta˛ ∗ wxChoice – rozwijana lista wyboru ∗ wxComboBox – pole edycji z rozwijana˛ lista˛ wyboru ∗ wxListBox – lista wyboru ∗ wxSlider – suwak ∗ wxTextCtrl – jedno- lub wieloliniowe pole tekstowe – statyczne (nie podlegajace ˛ edycji przez użytkownika programu): ∗ wxGauge – pasek post˛epu ∗ wxStaticText – etykieta tekstowa ∗ wxStaticBitmap – grafika ∗ wxStaticLine – linia ∗ wxStaticBox – obramowanie dookoła innych widgetów MyFrame::MyFrame(const wxString& title) // ...tutaj bez zmian... wxStaticBox* b = new wxStaticBox(w1, wxID_ANY, "Box", wxPoint(30,60), wxSize(150,50) ); wxGauge* g=new wxGauge(w1,wxID_ANY,10); g->SetValue(3); wxStaticLine* l = new wxStaticLine(w1, wxID_ANY,wxPoint(50,50), wxSize(200,5) ); } 6 Programowanie GUI – Wykład 6 7 • menu – wxMenu – menu; może byż używane na pasku menu lub jako menu kontekstowe • paski: – wxMenuBar – menu – wxToolBar – narz˛edzi – wxStatusBar – statusu 1.5 Rozmieszczanie widgetów • wxWidgets zapewnia mechanizmy wspomagajace ˛ skalowalne rozmieszczanie elementów wewnatrz ˛ okien – można uniknać ˛ używania ustalonych współrz˛ednych i podawania rozmiarów (np. okienek dialogowych) – obiekty odpowiadajace ˛ za rozmieszczenie widgetów (sizers, pochodza˛ od klasy abstrakcyjnej wxSizer) zapewniaja˛ automatyczne wyliczanie potrzebnych rozmiarów i współrz˛ednych • przy ustalaniu położenia widgetów pod uwag˛e brane sa: ˛ – minimalny dopuszczalny rozmiar – margines (odst˛ep do brzegu lub sasiedniego ˛ elementu) – ustawiany bezpośrednio (np. 5px) – wyrównanie (w pionie, poziomie – zwykle tylko w jednym z tych kierunków w zależności od sposobu rozmieszczenia) Programowanie GUI – Wykład 6 8 – współczynnik rozmiaru – proporcje, w jakich sa˛ skalowane elementy, jeśli dost˛epne jest wi˛ecej miejsca niż wymagane minimum • obiekt reprezentujacy ˛ rozmieszczenie (tzw. sizer) używany jest w nast˛epujacy ˛ sposób: 1. utworzenie obiektu (b˛edacego ˛ na najwyższym poziomie hierarchii) 2. powiazanie ˛ z oknem macierzystym za pomoca˛ wxWindow::SetSizer 3. dodawanie do hierarchii kolejnych składników (widgetów lub dalszych rozmieszczeń) jedna˛ z wersji metody wxSizer::Add, np. Add(wxWindow* window, int proportion=0, int flag=0, int border=0, wxObject* userData=NULL) • okno dopasuje si˛e rozmiarem do swojej zawartości, jeśli użyjemy funkcji wxSizer::Fit • wxSizer::SetSizeHints zapewni, że okno nie b˛edzie mogło być zmniejszone poniżej swojej poczatkowej ˛ wielkości • dost˛epna jest również funkcja wxWindow::SetSizerAndFit umożliwiajaca ˛ od razu ustawienie rozkładu oraz wywołanie wxSizer::Fit i wxSizer::SetSizeHints 1.5.1 Dostepne ˛ układy • wxBoxSizer – układ pionowy (poszczególne elementy wyrównywane do lewej, środka lub prawej; współczynnik rozmiaru decyduje o wymiarach w pionie) lub poziomy MyFrame::MyFrame(const wxString& title) : wxFrame(NULL, wxID_ANY, title) { const int BORDER=10; wxPanel* p = new wxPanel(this); wxBoxSizer* s = new wxBoxSizer(wxHORIZONTAL); wxGauge* g = new wxGauge(p,wxID_ANY,10); g->SetValue(7); s->Add(g,2,wxALIGN_CENTER|wxALL,BORDER); wxButton* b = new wxButton(p,wxID_OK,"OK"); s->Add(b,1,wxALIGN_BOTTOM|wxALL,BORDER); p->SetSizer(s); s->Fit(this); s->SetSizeHints(this); } Programowanie GUI – Wykład 6 9 • wxStaticBoxSizer – pochodzi od wxStaticBox, dodatkowo może automatycznie umieszczać wxStaticBox wokół zawartych w sobie elementów wxPanel* p = new wxPanel(this); wxStaticBoxSizer* s = new wxStaticBoxSizer(wxVERTICAL,p,"Box"); const int BORDER=10; wxGauge* g= new wxGauge(p,wxID_ANY,10); g->SetValue(7); s->Add(g,2,wxALL,BORDER); wxButton* b = new wxButton(p,wxID_OK,"OK"); s->Add(b,3,wxALL|wxALIGN_CENTER, BORDER); p->SetSizer(s); s->Fit(this); s->SetSizeHints(this); Programowanie GUI – Wykład 6 10 • wxGridSizer – rozmieszczenie w dwuwymiarowej sieci o równych szerokościach oraz równych wysokościach poszczególnych komórek – do konstruktora przekazuje si˛e liczb˛e kolumn i wierszy oraz ew. dodatkowe odst˛epy mi˛edzy elementami: wxGridSizer(int rows, int cols, int vgap, int hgap) wxGridSizer(int cols, int vgap = 0, int hgap = 0) wxPanel* p = new wxPanel(this); wxGridSizer* s=new wxGridSizer(2,2,0,0); wxGauge* g1= new wxGauge(p,wxID_ANY,100); g1->SetValue(25); s->Add(g1,0,wxALL,5); wxButton* b1= new wxButton(p,wxID_OK,"OK"); s->Add(b1,0,wxALL,5); wxButton* b2= new wxButton(p,wxID_CANCEL, "Cancel, cancel......."); s->Add(b2,0,wxALL,5); wxGauge* g2= new wxGauge(p,wxID_ANY,60); g2->SetValue(50); s->Add(g2,0,wxALL,5); Programowanie GUI – Wykład 6 11 p->SetSizer(s); s->Fit(this); s->SetSizeHints(this); • wxFlexGridSizer – podobne do wxGridSizer z tym, że nie wszystkie kolumny musza˛ być jednakowej szerokości oraz nie wszystkie rz˛edy musza˛ być jednakowo wysokie – dodatkowo funkcjami wxFlexGridSizer::AddGrowableCol wxFlexGridSizer::AddGrowableRow można wymusić poszerzanie tylko wybranych kolumn/wierszy podczas zmiany rozmiaru okna wxPanel* p = new wxPanel(this); wxFlexGridSizer* s = new wxFlexGridSizer(2,2,10,10); wxGauge* g1= new wxGauge(p,wxID_ANY,100); g1->SetValue(25); s->Add(g1,0,wxALL); Programowanie GUI – Wykład 6 wxButton* b1= new wxButton(p,wxID_OK,"OK"); s->Add(b1,0,wxALL); wxButton* b2 = new wxButton(p, wxID_CANCEL, "Cancel, cancel......."); s->Add(b2,0,wxALL); wxGauge* g2= new wxGauge(p,wxID_ANY,60); g2->SetValue(50); s->Add(g2,0,wxALL); p->SetSizer(s); s->Fit(this); s->SetSizeHints(this); 12