Jak zacząć

Prosty program (tiny.cpp):
//////////////////////////////////////////////////////////////////
#include "basic.h" 

// Klasa reprezentująca główne okno aplikacji, musi dziedziczyc Frame
class MyFrame : public Frame {
public:
  MyFrame() ;
} ;


// Konstruktor: tytuł, położenie (x,y) i rozmiar (szer.,wys.)
MyFrame::MyFrame() : Frame("Tiny", 0,0,200,200){}


// Klasa aplikacji, dziedziczy App; musi istniec jeden obiekt tej klasy
class MyApp:public App {
  MyFrame *frame ;
  void onInit() ;
} ;

// Wywoływane przy starcie aplikacji
void MyApp::onInit()
{ 
  frame = new MyFrame ;
  setMainWindow(frame) ;
}

int main()
{
  MyApp().run();
}
//////////////////////////////////////////////////////////////////

Dodajemy obsługę klawiatury (small.cpp):

class MyApp:public App {
  MyFrame *frame ;

  virtual void onInit() ;
  virtual bool onKeyPressed(int key) {
    if(key == 'q') {App::quit() ;return true;} 
    return false ;
  }
} ;


Wypełnianie okna treścią

Klasa Frame (a w zasadzie jej nadklasa, MWindow) posiada wirtualną
metodę

void paint()

metoda ta jest wywoływana kiedy potrzebne jest odświeżenie zawartości
okna (przy utworzeniu, zmianie rozmiaru, odsłonięciu okna).
Musimy przedefiniować ją w naszej klasie (MyFrame), np.

class MyFrame : public Frame {
public:
  MyFrame() ;
  void paint() ;
  void onClick(int,int); // o tej metodzie za chwilę
} ;

void MyFrame::paint() 
{
  drawLine(10,10,100,100) ; // rysuje linię od (10,10) do (100,100)
}

Do rysowania, mamy następujące metody:

drawPoint(int x,int y) ;                      // punkt
drawLine(int x1,int x2,int y1, int y2) ;      // linia od (x1,y1) do (x2,y2)
drawRectangle(int x,int y,int w, int h) ; // prostokąt: x,y,szerokość,wysokość
fillRectangle(int x,int y,int w, int h) ; // toż, wypełniony
drawCircle(int x, int y, int r); // okrag
fillCircle(int x, int y, int r); // kolo
drawArc(int x,int y,int w, int h,int angle1, int angle2); // wycinek luku
fillArc(int x,int y,int w, int h,int angle1, int angle2); // wycinek kola

  dwie ostatnie metody ---  man XDrawArc

drawString (int x, int y, string text )  ;    // napis
clear() ;                                     // wyczyść okno

Kolory i klasa Rgb

Klasa Rgb

Reprezentuje kolory w kodowaniu RGB (Red, Green Blue)
Kolor jest reprezentowany przez intensywność składników: czerwonego,
zielonego i niebieskiego (0-255). Przykłady:

const Rgb red(255,0,0) ;       // czerwony
const Rgb lime(0,255,0) ;      // jasny zielony
const Rgb blue(0,0,255);       // niebieski
const Rgb white(255,255,255) ; // biały
const Rgb black(0,0,0) ;       // czarny
const Rgb magenta(255,0,255);  // fioletowy
const Rgb yellow(255,255,0);   // żółty
const Rgb cyan(0,255,255);     // jasny niebieski
const Rgb green(0,128,0);      // (ciemny) zielony

Do ustawiania koloru tła i rysowania służą metody

void setBackground(Rgb c) {setBackground(Color(c));};
void setForeground(Rgb c) {setForeground(Color(c));};  

Przykład użycia - kolorowy kwadrat z czarną obwódką (btest.cpp)

class Square {
public:
  Square(int x, int y, int a, Rgb col)
    : m_x(x),m_y(y),m_a(a),m_col(col) {};
  void draw(MWindow& win) ; 

private:
  int m_x, m_y, m_a;
  Rgb m_col ;
};

void
Square::draw(MWindow& win)
{
  win.setForeground(m_col) ;
  win.fillRectangle(m_x,m_y,m_a,m_a) ;
  win.setForeground(black) ;
  win.drawRectangle(m_x,m_y,m_a,m_a) ;
}

Obsługa myszy

Podstawowa - metoda onClick(int x,int y) wywoływana w momencie
kliknięcia (argumentami są współrzędne wskaźnika myszy w oknie)

Przykład:

void MyFrame::onClick(int x, int y)
{
  std::cout << "Click: x="<<x<<",y="<<y<<std::endl;
}

Zaawansowana - metody

  virtual void onLeftButtonDown(int,int) {};
  virtual void onRightButtonDown(int,int) {} ;
  virtual void onLeftButtonUp(int x,int y) {onClick(x,y);};
  virtual void onRightButtonUp(int,int){} ;

wywoływane odpowiednio w momencie naciśnięcia i puszczenia lewego bądź
prawego przycisku myszy.

Uwaga: jeśli przedefiniujemy metodę onLeftButtonUp, to nie będzie
wywoływana metoda onClick.

Wszystkie wspomniane powyżej metody są zdefiniowane w klasie
Clickable, która jest nadklasą MWindow (a więc i Frame)

Gadżety - klasa Gadget

Gadget reprezentuje element aplikacji, który ma
- wygląd (sposób narysowania)  - paint(MWindow& w)
- reakcje na zdarzenia myszy - on...(x,y)
- metodę przesunięcia o podany wektor - move

- (ewentualnie) elementy (też klasy Gadget)
- metodę dodawania nowych elementów - add

Powyższe metody (z wyjątkiem add) są automatycznie propagowane do
wszystkich elementów.

Z punktu widzenia użytkownika, Gadget wygląda tak:

class Gadget : public Clickable {
 public:
  void add(Gadget* c);
  virtual void onClick(int x, int y);
  virtual void paint(MWindow& win) ;
  virtual void move(int dx,int dy) ;
};

Przykładem gadżetu może być napis:

class GLabel:public Gadget {
  string m_text;
  int m_x,m_y;
 public:
  GLabel(int x, int y,string s):m_x(x),m_y(y),m_text(s){}
  void onClick(int,int){}
  void paint(MWindow& win){win.drawString(m_x,m_y,m_text);}
};

Inny przykład użycia gadżetów (BoardSquare i PaletteSquare są
podklasami klasy Gadget)

Aplikacja składa się z dwóch obszarów: palety i planszy. Każdy z nich
zawiera pewną ilość gadżetów.

MyFrame::MyFrame() : Frame(0,"Clicker", 0,0,640,480)
{
  const int squareSize = 32 ;

  palette.add(new PaletteSquare(0*squareSize,0*squareSize,squareSize,white));
  palette.add(new PaletteSquare(1*squareSize,0*squareSize,squareSize,black));
  //...
		
    for(int row=0;row<16;row++)
    for(int col=0;col<16;col++)
      board.add(new BoardSquare(col*squareSize,
				row*squareSize,
				squareSize,
				brush)
		) ;

    palette.move(10,0);  
    board.move(120,0);
    
    allGadgets.add(&palette);
    allGadgets.add(&board);
}

void MyFrame::paint() 
{
  allGadgets.paint(*this);
}

void MyFrame::onClick(int x, int y)
{
  allGadgets.onClick(x,y);
  paint();
}