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

Podobne dokumenty