sexta-feira, 29 de abril de 2011

Sliders

Introdução
    Sliders são controles que nós podemos manipular movendo para frente e para trás (horizontal) ou para cima e para baixo (vertical) alterando seu valor. Em wxWidgets um slider é representado pela classe wxSlider. Podemos obter o valor de um wxSlider através do método GetValue() que nos retorna um número inteiro e definir seu valor através do método SetValue(int valor). No construtor da classe podemos definir seu valor inicial, valor mínimo, valor máximo, tamanho, orientação, etc. Para uma referência completa dos métodos da classe wxSlider visite: http://docs.wxwidgets.org/stable/wx_wxslider.html

Exemplo
    Como exemplo vamos nos basear no post sobre caixas de texto onde fizemos um programa para cálculo do volume do cilindro, mas ao invés de fornecer o raio e a altura através de caixas de texto vamos fornecer estes valores através de sliders (um para o raio e outro para altura). À medida que movemos os sliders os valores de raio e altura são alterados e o volume é calculado sendo mostrado através de um wxStaticText.



Código:

#include <wx/wx.h>

class Slider : public wxFrame
{
    private:
        wxSlider *sliderRaio;
        wxSlider *sliderAltura;
        wxStaticText *txtVolume;
        wxGridSizer *grid;
        double raio, altura, volume;

    public:
        Slider(const wxString &titulo);
        double Volume(double raio, double altura);
        void OnSlide(wxScrollEvent &evt);

};

const int ID_SL_RAIO = 1000;
const int ID_SL_ALTURA = 1001;


#include "slider.h"

Slider::Slider(const wxString &titulo) :
wxFrame(NULL, -1, titulo, wxDefaultPosition, wxSize(240,240))
{
   wxPanel *painel = new wxPanel(this, -1);
   grid = new wxFlexGridSizer(2,3,5,5);
   //criamos um slider com valor inicial = 0, valor minimo = 0, valor maximo = //100, 200 px de tamanho, orientado verticalmente e mostrando o valor //selecionado
   sliderRaio = new wxSlider(painel, ID_SL_RAIO, 0, 0, 100, wxDefaultPosition, wxSize(-1,200), wxSL_VERTICAL | wxSL_LABELS);
   //conectamos o metodo OnSlide ao evento do slider
   //ao movimentar o slide este metodo e chamado
   Connect(ID_SL_RAIO, wxEVT_COMMAND_SLIDER_UPDATED, wxScrollEventHandler(Slider::OnSlide));
   //criamos um slider com valor inicial = 0, valor minimo = 0, valor maximo = //100, 200 px de tamanho, orientado verticalmente e mostrando o valor //selecionado
   sliderAltura = new wxSlider(painel, ID_SL_ALTURA, 0, 0, 100, wxDefaultPosition, wxSize(-1,200), wxSL_VERTICAL | wxSL_LABELS);
   //conectamos o metodo OnSlide ao evento do slider
   //ao movimentar o slide este metodo e chamado
   Connect(ID_SL_ALTURA, wxEVT_COMMAND_SLIDER_UPDATED, wxScrollEventHandler(Slider::OnSlide));
   txtVolume = new wxStaticText(painel, -1, wxT("0"));
   grid->Add(new wxStaticText(painel, -1, wxT("Raio")), 1, wxLEFT, 20);
   grid->Add(new wxStaticText(painel, -1, wxT("Altura")), 1, wxLEFT, 20);
   grid->Add(new wxStaticText(painel, -1, wxT("Volume")), 1, wxLEFT, 38);
   grid->Add(sliderRaio, 1, wxLEFT, 22);
   grid->Add(sliderAltura, 1, wxLEFT, 24);
   grid->Add(txtVolume, 1, wxTOP | wxLEFT, 48);
   painel->SetSizer(grid);
   Centre();
}

double Slider::Volume(double raio, double altura)
{
    this->raio = raio;
    this->altura = altura;
    volume = 3.14 * (this->raio*this->raio) * altura;
    return volume;
}

void Slider::OnSlide(wxScrollEvent &evt)
{
   //o metodo GetValue retorna o valor do slider
   double v = Volume(sliderRaio->GetValue(), sliderAltura->GetValue());
   txtVolume->SetLabel(wxString() << v);
}


#include "slider.h"

class MinhaApp : public wxApp
{
    public:
       virtual bool OnInit();
};

#include "main.h"

IMPLEMENT_APP(MinhaApp)

bool MinhaApp::OnInit()
{
    Slider *slider = new Slider(wxT("Slider com wxWidgets"));
    slider->Show(true);
    return true;
}

segunda-feira, 25 de abril de 2011

CheckBox com wxWidgets

Introdução
     Um checkbox é um widget que pode ter dois estados: ligado ou desligado (checado ou não). Quanto um checkbox está checado ele apresenta um "tick" na caixa que representa o widget. Esta caixa pode ter um label associado a ela do lado esquerdo ou direito. Um checkbox pode ser usado em diversas situações, como marcar ou desmarcar opções, aceitar ou não termos de uso, mostrar ou esconder outros widgets, entre outras. Em wxWidgets um checkbox é representado pela classe wxCheckBox.

Exemplo
    Em nosso exemplo vamos fazer um programa que mostra ou esconde o título da aplicação dependendo do estado do checkbox. Quanto o checkbox estiver checado o título é mostrado, do contrário o título não aparece.


Código

#include <wx/wx.h>
//checkbox.h

class CheckBox : public wxFrame
{
public:
    CheckBox(const wxString& title);

    void Alternar(wxCommandEvent& event);

    wxCheckBox *m_cb;
};

#include "checkbox.h"
//checkbox.cpp

CheckBox::CheckBox(const wxString& title) : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(270, 150))
{
  wxPanel *panel = new wxPanel(this, wxID_ANY);

  m_cb = new wxCheckBox(panel, 100, wxT("Mostra o título"), wxPoint(20, 20));
  m_cb->SetValue(true);
  Connect(100, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(CheckBox::Alternar));
  Centre();
}

void CheckBox::Alternar(wxCommandEvent& WXUNUSED(event))
{

  if (m_cb->GetValue()) {
      this->SetTitle(wxT("CheckBox com wxWidgets"));
  } else {
      this->SetTitle(wxT(" "));
  }
}

#include <wx/wx.h>
//main.h
class MyApp : public wxApp
{
  public:
    virtual bool OnInit();
};

#include "main.h"
#include "checkbox.h"
//main.cpp

IMPLEMENT_APP(MyApp)

bool MyApp::OnInit()
{

    CheckBox *cb = new CheckBox(wxT("CheckBox com wxWidgets"));
    cb->Show(true);

    return true;
}

terça-feira, 19 de abril de 2011

Menus com wxWidgets

Introdução
    Através dos menus nós podemos agrupar os comandos de nossa aplicação para que possamos executá-los de maneira rápida e intuitiva. Em wxWidgets os menus são compostos basicamente de uma barra de menu (wxMenuBar), os menus propriamente ditos (wxMenu) e os items pertencentes a cada menu (wxMenuItem). Através do método SetMenuBar() nós adicionamos uma barra de menu à aplicação. O método Append() adiciona um menu à barra de menu e um item de menu ao menu.
   No nosso exemplo criaremos uma aplicação com uma barra de menu que tem o menu 'Arquivo' que por sua vez tem os items de menu: 'Novo', 'Abrir', 'Salvar' e 'Sair'. Ao clicarmos no item de menu 'Sair' a aplicação é fechada.


Código:

#include <wx/wx.h>
//menu.h

class Menu : public wxFrame
{
        private:
            wxMenuBar *barramenu;
            wxMenu *arquivo;
            wxMenuItem *novo;
            wxMenuItem *abrir;
            wxMenuItem *salvar;
            wxMenuItem *sair;

        public:
            Menu(const wxString &titulo);
            void Sair(wxCommandEvent &evt);
};

#include "menu.h"
//menu.cpp

Menu::Menu(const wxString &titulo) :
      wxFrame(NULL, -1, titulo, wxDefaultPosition, wxSize(500, 400))
      {
            //criamos a barra de menu
            barramenu = new wxMenuBar;
            //criamos o menu Arquivo
            arquivo = new wxMenu;
            novo = new wxMenuItem(arquivo, 1000, wxT("&Novo"));
            abrir = new wxMenuItem(arquivo, 1001, wxT("A&brir"));
            salvar = new wxMenuItem(arquivo, 1002, wxT("&Salvar"));
            sair = new wxMenuItem(arquivo, 1003, wxT("Sai&r"));
            //conectamos o método Sair() ao item de menu de id = 1003
            Connect(1003, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(Menu::Sair));
            //adicionamos os items de menu ao menu arquivo
            arquivo->Append(novo);
            arquivo->Append(abrir);
            arquivo->Append(salvar);
            arquivo->Append(sair);
            //adicionamos o menu Arquivo à barra de menu
            barramenu->Append(arquivo, wxT("&Arquivo"));
            //adicionamos a barra de menu 'barramenu' à aplicacao
            SetMenuBar(barramenu);
            Centre();
      }

void Menu::Sair(wxCommandEvent &evt)
{
    //fechamos a aplicacao
    Close();
}

#include "menu.h"
//main.h

class MinhaApp : public wxApp
{
    public:
        virtual bool OnInit();
};

#include "main.h"
//main.cpp

IMPLEMENT_APP(MinhaApp)

bool MinhaApp::OnInit()
{
        Menu *menu = new Menu(wxT("Menus com wxWidgets"));
        menu->Show(true);
        return true;
}

sábado, 16 de abril de 2011

Caixas de Texto

Introdução
      Caixas de texto são utilizadas em sistemas com interface gráfica para capturar entrada de dados do usuário. Através de caixas de texto podemos entrar com nomes de usuário e senhas para validação, gravar informações em um banco de dados e setar variáveis de nossos programas para fazer cálculos, por exemplo. Em wxWidgets a classe que representa uma caixa de texto é a wxTextCtrl.
    Para capturar o valor de um wxTextCtrl utilizamos o método GetValue() que retorna um wxString.     
    Para setar o valor de um wxTextCtrl utilizamos o método SetValue(wxString valor).

Cálculo do volume do cilindro

     Neste post vou mostrar um programa para calcular o volume de um cilindro. O usuário entrará com o raio da base e a altura do cilindro. A fórmula para calculo do volume do cilindro é dada por: A = PI * r^2 * h, onde r é o raio e h é a altura. O programa avisará através de uma caixa de mensagem (wxMessageBox) se o usuário deixar algum campo vazio ou se os valores digitados não forem números.


     


     

Segue abaixo o código da aplicação:

#include <wx/wx.h>
//cilindro.h

class Cilindro : public wxFrame {

    public:

        Cilindro(const wxString &titulo);

        double Volume(double raio, double altura);

        void Calcula(wxCommandEvent &evt);
        void Limpa(wxCommandEvent &evt);

    private:

       double raio, altura, volume;

       wxTextCtrl *txtraio;
       wxTextCtrl *txtaltura;
       wxTextCtrl *txtvolume;
       wxStaticText *stcraio;
       wxStaticText *stcaltura;
       wxStaticText *stcvolume;
       wxButton *calcular;
       wxButton *limpar;

};

#include "cilindro.h"
//cilindro.cpp

Cilindro::Cilindro(const wxString &titulo) : wxFrame(NULL, -1, titulo, wxDefaultPosition, wxSize(290, 180))
{
    wxPanel *painel = new wxPanel(this, -1);
    wxBoxSizer *boxprincipal = new wxBoxSizer(wxVERTICAL);
    wxGridSizer *boxtexto = new wxGridSizer(3, 2, 5, 5);
    wxBoxSizer *boxbotoes = new wxBoxSizer(wxHORIZONTAL);
    txtraio = new wxTextCtrl(painel, -1, wxT(""));
    txtaltura = new wxTextCtrl(painel, -1, wxT(""));
    txtvolume = new wxTextCtrl(painel, -1, wxT(""));
    stcraio = new wxStaticText(painel, -1, wxT("Raio:"));
    stcaltura = new wxStaticText(painel, -1, wxT("Altura:"));
    stcvolume = new wxStaticText(painel, -1, wxT("Volume:"));
    calcular = new wxButton(painel, 1000, wxT("Calcular"));
    Connect(1000, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(Cilindro::Calcula));
    limpar = new wxButton(painel, 1001, wxT("Limpar"));
    Connect(1001, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(Cilindro::Limpa));
    boxtexto->Add(stcraio, 1, wxALL, 10);
    boxtexto->Add(txtraio, 1, wxALL, 5);
    boxtexto->Add(stcaltura, 1, wxALL, 10);
    boxtexto->Add(txtaltura, 1, wxALL, 5);
    boxtexto->Add(stcvolume, 1, wxALL, 10);
    boxtexto->Add(txtvolume, 1, wxALL, 5);
    boxbotoes->Add(calcular, 1, wxALL, 10);
    boxbotoes->Add(limpar, 1, wxALL, 10);
    boxprincipal->Add(boxtexto, 1, wxEXPAND);
    boxprincipal->Add(boxbotoes, 1, wxEXPAND);
    painel->SetSizer(boxprincipal);
    txtraio->SetFocus();
    Centre();
}

double Cilindro::Volume(double raio, double altura)
{
    this->raio = raio;
    this->altura = altura;
    volume = 3.14 * (this->raio*this->raio) * altura;
    return volume;
}

void Cilindro::Calcula(wxCommandEvent &evt)
{
    double r, h, a;
    //verificamos se algum dos campos está vazio
    //se estiver mostramos uma mensagem de alerta
    if((txtraio->IsEmpty()) || (txtaltura->IsEmpty())) {
        wxMessageBox(wxT("Nao podem haver campos vazios!"), wxT("Aviso"));
        return;
    }
    //verificamos se os valores digitados sao numeros
    //se nao forem exibimos uma mensagem de alerta
    if((!txtraio->GetValue().ToDouble(&r)) || (!txtaltura->GetValue().ToDouble(&h))) {
        wxMessageBox(wxT("Os valores dos campos devem ser numericos!"), wxT("Aviso"));
        return;
    }
    //chamamos o metodo Area() para calcular o volume do cilindro
    a = Volume(r, h);
    //setamos o textbox volume com o valor calculado
    txtvolume->SetValue(wxString() << a);
}

void Cilindro::Limpa(wxCommandEvent &evt)
{
    //limpamos os campos com o método Clear()
    txtraio->Clear();
    txtaltura->Clear();
    txtvolume->Clear();
}

#include "cilindro.h"
//main.h


class MinhaApp : public wxApp
{
    public:
        virtual bool OnInit(); 
   
};

#include "main.h"
//main.cpp

IMPLEMENT_APP(MinhaApp)

bool MinhaApp::OnInit()
{
    Cilindro *cilindro = new Cilindro(wxT("Calculo da area do cilindro"));
    cilindro->Show(true);
    return true;
}





sexta-feira, 15 de abril de 2011

A classe wxString

Introdução
     wxWidgets nos fornece uma classe que representa uma cadeia de caracteres, a classe wxString. Esta classe é usada em várias outras classes da wxWidgets, como para setar ou retornar um valor em um wxTextCtrl, o label de um wxButton, etc. A classe wxString implementa cerca de 90% dos métodos da classe string presente na STL (Standard Template Library) de C++. Um bom conhecimento sobre esta classe é imprescindível para desenvolver programas utilizando wxWidgets.

Alguns Métodos
    Len() ou Length() - Ambos retornam o tamanho da string
    IsEmpty() - Retorna true se a string está vazia
    c_str() - Retorna um ponteiro para uma string ANSI, muito útil para passar uma wxString como argumento para uma função que espera por uma string no estilo C (const char*).
    Exemplo: func_c(minhaString.c_str())
    MakeUpper() - Converte todos os caracteres para maiúsculo e retorna o resultado.
    MakeLower() - Converte todos os caracteres para minúsculo e retorna o resultado.
    FromAscii(str_ascii) - Converte uma string normal para wxString.
    Exemplo: wxString minhaString = wxString::FromAscii(str_ascii)
    Convertendo um número para wxString
    wxString minhaString = wxString::Format(wxT("%d"), 10); //inteiro
    wxString minhaString = wxString::Format(wxT("%f"), 10.5); //float
    wxString s; s.Printf(wxT("%d", 10); //inteiro
    wxString s; s.Printf(wxT("%f", 10.5); //float
    wxString minhaString = wxString() << 10;
    wxString minhaString = wxString() << 10.5;
    Convertendo wxString para números
    long numero;
    wxString num(wxT("1000000"));
    num.ToLong(&numero);   //retorna falso em caso de erro
    double numero_d;
    wxString num_d(wxT("1234.89"));
    num_d.ToDouble(&numero_d); // retorna falso em caso de erro
    Estes são apenas alguns dos métodos da classe wxString, para uma referência completa visitem: http://docs.wxwidgets.org/2.6/wx_wxstring.html
  

quinta-feira, 14 de abril de 2011

Um pouco mais sobre eventos

Uma "quase" calculadora
      O exemplo do post anterior retirado do site zetcode onde é montado o "esqueleto" de uma calculadora não faz nada além de nos dar uma idéia de como trabalhar com wxGridSizer. Que tal implementarmos um método para detectar qual botão foi clicado e o que fazer dependendo de qual botão foi clicado? Isso mesmo!! UM método só para todos os botões!
    Para isso vamos atribuir um ID diferente para cada botão e utilizar o método Connect para conectar todos eles ao nosso método OnClick(). O nosso método OnClick() receberá como parâmetro uma referência para um objeto do tipo wxCommandEvent que descende de wxEvent. Este objeto tem um método chamado GetId() que retorna o ID do objeto que originou o evento e é através deste ID que identificamos qual botão foi clicado.
    Abaixo seguem as modificações no código do esqueleto da calculadora que vimos no post anterior.
    No arquivo gridsizer.h vamos declarar um objeto do tipo wxString (veremos mais sobre esta classe em outro post) na declaração da classe, abaixo de wxTextCtrl *display;:
    wxString textodisplay;
    Agora no construtor da classe GridSizer:

    //inicializamos o texto do display como vazio
    textodisplay = "";
   //atribuímos um ID diferente para cada botão (de 1 a 20), tomando cuidado para que nenhum outro widget 
  //tenha o mesmo ID
  gs->Add(new wxButton(this, 1, wxT("Cls")), 0, wxEXPAND);
  gs->Add(new wxButton(this, 2, wxT("Bck")), 0, wxEXPAND);
  gs->Add(new wxStaticText(this, 3, wxT("")), 0, wxEXPAND);
  gs->Add(new wxButton(this, 4, wxT("Close")), 0, wxEXPAND);
  gs->Add(new wxButton(this, 5, wxT("7")), 0, wxEXPAND);
  gs->Add(new wxButton(this, 6, wxT("8")), 0, wxEXPAND);
  gs->Add(new wxButton(this, 7, wxT("9")), 0, wxEXPAND);
  gs->Add(new wxButton(this, 8, wxT("/")), 0, wxEXPAND);
  gs->Add(new wxButton(this, 9, wxT("4")), 0, wxEXPAND);
  gs->Add(new wxButton(this, 10, wxT("5")), 0, wxEXPAND);
  gs->Add(new wxButton(this, 11, wxT("6")), 0, wxEXPAND);
  gs->Add(new wxButton(this, 12, wxT("*")), 0, wxEXPAND);
  gs->Add(new wxButton(this, 13, wxT("1")), 0, wxEXPAND);
  gs->Add(new wxButton(this, 14, wxT("2")), 0, wxEXPAND);
  gs->Add(new wxButton(this, 15, wxT("3")), 0, wxEXPAND);
  gs->Add(new wxButton(this, 16, wxT("-")), 0, wxEXPAND);
  gs->Add(new wxButton(this, 17, wxT("0")), 0, wxEXPAND);
  gs->Add(new wxButton(this, 18, wxT(".")), 0, wxEXPAND);
  gs->Add(new wxButton(this, 19, wxT("=")), 0, wxEXPAND);
  gs->Add(new wxButton(this, 20, wxT("+")), 0, wxEXPAND);

  //No loop for nós conectamos o click nos botões ao método OnClick() (poderia ter qualquer outro nome)
  for(int i = 1; i < 20; i++) {
    Connect(i, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(GridSizer::OnClick));     
  }

 Agora, eis o  método que vai tratar o click nos botões da "calculadora":

void GridSizer::OnClick(wxCommandEvent &evt) {
   //criamos um ponteiro para um objeto da classe wxButton e fazemos um cast para que
   //ele receba o objeto que gerou o evento
   wxButton *btn = (wxButton*) evt.GetEventObject();
   //o método GetId() da classe wxCommandEvent retorna o id do objeto que gerou o evento
   if(evt.GetId() != 2)
   //se o botão clicado for diferente de Bck atribuímos o label do mesmo ao objeto wxString textodisplay
      textodisplay += btn->GetLabelText();
   else
      //senão removemos o último caracter da string
      textodisplay.RemoveLast();
     
   if(evt.GetId() == 1)
      //se clicarmos no botão Cls atribuimos uma string vazia ao texto do display
      textodisplay = "";
  
   if(evt.GetId() == 4)
      //fechamos a aplicação
      this->Close(); 
   //setamos o valor do display      
   display->SetValue(textodisplay);  
}

quarta-feira, 13 de abril de 2011

Gerenciamento de Layout com wxWidgets

Introdução
      Uma aplicação em wxWidgets pode consistir de vários widgets (controles), como botões, caixas de texto, etc dentro de um container (um painel, por exemplo). Estes controles podem ser posicionados dentro do container de duas formas possíveis: com posicionamento absoluto ou através dos sizers.

Posicionamento Absoluto
     O programador especifica o tamanho e posicionamento de cada controle em pixels, desta forma o tamanho dos controles não se altera, ou seja, se eu redimensionar a janela os controles permanecerão na mesma posição e com o mesmo tamanho, além disso a aparência da aplicação pode ficar diferente dependendo da plataforma em que for compilada e executada.

Utilizando Sizers

    Com sizers nós podemos resolver os problemas de posicionamento absoluto. Em wxWidgets nós temos os seguintes sizers: wxBoxSizer, wxStaticBoxSizer, wxGridSizer, wxFlexGridSizer, wxGridBagSizer.

  • wxBoxSizers 
      Com um wxBoxSizer nós podemos colocar vários widgets em linha ou em coluna e podemos colocar um sizer dentro de outro criando assim layouts bem complexos.
      wxBoxSizer(int orientacao)
      wxSizerItem* Add(wxWindow* janela, int proporcao = 0, int flag = 0, int borda = 0)
      A orientação pode ser wxVERTICAL ou wxHORIZONTAL. Para adicionarmos os widgets dentro do wxBoxSizer nós utilizamos o método Add().
     O parâmetro proporcao define a taxa com que os widgets mudam na orientação definida, o parâmetro flag define o comportamento dos widgets dentro de um wxBoxSizer e o parâmetro borda adiciona bordas ao redor dos widgets. Para definirmos as bordas precisamos declarar os lados em que as bordas serão aplicadas no parâmetro flag. Os flags usados podem ser: wxLEFT, wxRIGHT, wxBOTTOM, wxTOP e wxALL. Nós podemos combiná-los através do operador '|' (ou).

  
Abaixo segue em exemplo retirado de:  http://zetcode.com/tutorials/wxwidgetstutorial/layoutmanagement/
    
#include <wx/wx.h>
//border.h

class Border : public wxFrame
{
public:
  Border(const wxString& title);

};
#include "border.h"
//border.cpp
Border::Border(const wxString& title)
       : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(250, 200))
{

  wxColour col1, col2;
  col1.Set(wxT("#4f5049"));
  col2.Set(wxT("#ededed"));

  wxPanel *panel = new wxPanel(this, -1);
  panel->SetBackgroundColour(col1);
  wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL);

  wxPanel *midPan = new wxPanel(panel, wxID_ANY);
  midPan->SetBackgroundColour(col2);
  //colocamos uma borda de 20 pixels ao redor do painel midPan
//wxALL aplica a borda ao redor de todo o painel
  //wxEXPAND faz com que a borda ocupe todo o espaço disponível
  vbox->Add(midPan, 1, wxEXPAND | wxALL, 20);
  panel->SetSizer(vbox);

  Centre();
}
#include <wx/wx.h>
//main.h
class MyApp : public wxApp
{
  public:
    virtual bool OnInit();
};
#include "main.h"
#include "border.h"
//main.cpp
IMPLEMENT_APP(MyApp)

bool MyApp::OnInit()
{

    Border *border = new Border(wxT("Border"));
    border->Show(true);

    return true;
}

  • wxGridSizer
wxGridSizer estabelece os widgets em uma tabela de duas dimensões onde cada célula da tabela tem o mesmo tamanho. 
wxGridSizer(int linhas, int colunas, int vgap, int hgap)
No construtor nós especificamos o número de linhas e colunas de nossa tabela e o espaço horizontal e vertical entre cada célula.
No próximo exemplo nós criaremos o esqueleto de uma cálculadora. 
Este exemplo também foi retirado de: http://zetcode.com/tutorials/wxwidgetstutorial/layoutmanagement/
 
#include <wx/wx.h>
//gridsizer.h

class GridSizer : public wxFrame
{
public:
  GridSizer(const wxString& title);

  wxMenuBar *menubar;
  wxMenu *file;

  wxBoxSizer *sizer;
  wxGridSizer *gs;
  wxTextCtrl *display;

};
#include "gridsizer.h" //gridsizer.cpp
GridSizer::GridSizer(const wxString& title)
       : wxFrame(NULL, -1, title, wxPoint(-1, -1), wxSize(270, 220))
{
  menubar = new wxMenuBar;
  file = new wxMenu;

  SetMenuBar(menubar);

  sizer = new wxBoxSizer(wxVERTICAL);
 
  display = new wxTextCtrl(this, -1, wxT(""), wxPoint(-1, -1),
     wxSize(-1, -1), wxTE_RIGHT);

  sizer->Add(display, 0, wxEXPAND | wxTOP | wxBOTTOM, 4);
  gs = new wxGridSizer(4, 4, 3, 3);

  gs->Add(new wxButton(this, -1, wxT("Cls")), 0, wxEXPAND);
  gs->Add(new wxButton(this, -1, wxT("Bck")), 0, wxEXPAND);
  gs->Add(new wxStaticText(this, -1, wxT("")), 0, wxEXPAND);
  gs->Add(new wxButton(this, -1, wxT("Close")), 0, wxEXPAND);
  gs->Add(new wxButton(this, -1, wxT("7")), 0, wxEXPAND); 
  gs->Add(new wxButton(this, -1, wxT("8")), 0, wxEXPAND);
  gs->Add(new wxButton(this, -1, wxT("9")), 0, wxEXPAND);
  gs->Add(new wxButton(this, -1, wxT("/")), 0, wxEXPAND);
  gs->Add(new wxButton(this, -1, wxT("4")), 0, wxEXPAND);
  gs->Add(new wxButton(this, -1, wxT("5")), 0, wxEXPAND);
  gs->Add(new wxButton(this, -1, wxT("6")), 0, wxEXPAND);
  gs->Add(new wxButton(this, -1, wxT("*")), 0, wxEXPAND);
  gs->Add(new wxButton(this, -1, wxT("1")), 0, wxEXPAND);
  gs->Add(new wxButton(this, -1, wxT("2")), 0, wxEXPAND);
  gs->Add(new wxButton(this, -1, wxT("3")), 0, wxEXPAND);
  gs->Add(new wxButton(this, -1, wxT("-")), 0, wxEXPAND);
  gs->Add(new wxButton(this, -1, wxT("0")), 0, wxEXPAND);
  gs->Add(new wxButton(this, -1, wxT(".")), 0, wxEXPAND);
  gs->Add(new wxButton(this, -1, wxT("=")), 0, wxEXPAND);
  gs->Add(new wxButton(this, -1, wxT("+")), 0, wxEXPAND);

  sizer->Add(gs, 1, wxEXPAND);
  SetSizer(sizer);
  SetMinSize(wxSize(270, 220));

  Centre();
}
#include <wx/wx.h>
//main.h
class MyApp : public wxApp
{
  public:
    virtual bool OnInit();
};
#include "main.h"
#include "gridsizer.h"
//main.cpp
IMPLEMENT_APP(MyApp)

bool MyApp::OnInit()
{

    GridSizer *gs = new GridSizer(wxT("GridSizer"));
    gs->Show(true);

    return true;
}
gs->Add(new wxButton(this, -1, wxT("Cls")), 0, wxEXPAND);
Nós chamamos o método Add() várias vezes. Os widgets são colocados dentro da tabela na ordem em que eles são adicionados.
Após o preenchimento de todas as colunas da primeira linha passasse para a segunda linha e assim por diante.
  • wxFlexGridSizer
   Este sizer é muito parecido com o wxGridSizer, todas as células tem a mesma largura em uma coluna e a mesma altura em uma linha, 
mas suas linhas e colunas não precisam ser da mesma largura ou altura.
 wxFlexGridSizer(int linhas, int colunas, int vgap, int hgap)
    No construtor nós especificamos o número de linhas e colunas de nossa tabela e o espaço horizontal e vertical entre cada célula. 
 
 

segunda-feira, 11 de abril de 2011

Eventos

Introdução
       Manipulação de eventos é uma parte indispensável em qualquer sistema que utilize  interface gráfica. Eventos normalmente vêm de ações executadas pelo usuário sobre o sistema, como o clique em um botão, o pressionamento de uma tecla, etc, mas também podem ser gerados de outras formas, como pelo manipulador de janelas, o timer, etc.
      Tradicionalmente wxWidgets trabalha com eventos através da manipulação de uma tabela de eventos estática, diferentemente do modo como foi apresentado no post anterior com o método Connect, que é uma forma mais moderna e prática de tratar eventos com wxWidgets.

Exemplo
     Utilizando tabela de eventos o exemplo do post anterior ficaria assim:

#include <wx/wx.h>
//frame.h
class MeuFrame : public wxFrame {
        private:
            wxPanel *painel;
            wxButton *btnsair;
            wxStaticText *label;
            DECLARE_EVENT_TABLE() // Declaramos a tabela de eventos com a macro  
                                                                //DECLARE_EVENT_TABLE()
        public:
            MeuFrame(const wxString &titulo);
            void Sair(wxCommandEvent &evt);
};

#include "frame.h"
//frame.cpp
MeuFrame::MeuFrame(const wxString& titulo):
          wxFrame(NULL, wxID_ANY, titulo, wxDefaultPosition, wxSize(500, 400))
{
     painel = new wxPanel(this, wxID_ANY);
     label = new wxStaticText(painel, -1, wxT("Meu Primeiro Programa com wxWidgets"), wxPoint(100, 200));
     btnsair = new wxButton(painel, wxID_EXIT, wxT("Sair"), wxPoint(200, 250), wxSize(50, 30));
     //  Connect(wxID_EXIT, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MeuFrame::Sair));
     btnsair->SetFocus();
     Centre();
}

void MeuFrame::Sair(wxCommandEvent &evt) {
    //fecha a aplicação
    Close(true);
}

//Esta macro inicia a tabela de eventos
BEGIN_EVENT_TABLE(MeuFrame, wxFrame)
    /*Aqui através da macro EVT_BUTTON nós atribuímos o método sair ao botão com id =
       wxID_EXIT, isto é, o método sair será chamado quando o botão for clicado, onde 
      EVT_BUTTON indica o tipo de evento. */
    EVT_BUTTON(wxID_EXIT, MeuFrame::Sair)

//Esta macro finaliza a tabela de eventos
END_EVENT_TABLE()

Primeiro programa com wxWidgets

Introdução
    wxWidgets é uma biblioteca de classes para criar aplicações com interface gráfica em C++, mas, além de criação de interface gráfica, esta biblioteca provê também classes para manipulação de streams, banco de dados, threads, etc.  É uma biblioteca de código aberto e multiplataforma, funciona na maioria dos sistemas operacionais como: Windows, Linux, Mac, etc.  Seu projeto foi iniciado em 1992 por Julian Smart.

Instalação
  •    Linux:
             Faça download do wxGTK em: http://www.wxwidgets.org/downloads/
             Vá ao terminal e digite:
             cd /caminho/wxGTK-2.8.x (o caminho onde você extraiu o pacote)
             mkdir gtk-build
             cd gtk-build
             ../configure --enable-unicode --with-opengl --disable-shared
             make
             sudo make install
             Para testar a instalação digite: wx-config --version
             Para desenvolver seus programas eu recomendo a utilização da IDE Code::Blocks que pode ser baixada em:  http://www.codeblocks.org/downloads
             Se você prefere compilar seus programas pela linha de comando faça da seguinte maneira:
             g++ `wx-config --cppflags` `wx-config --libs` programa.cpp            

  • Windows
         Para Windows eu recomendo a utilização da IDE wxDev-cpp. Tudo o que você tem a fazer é baixar a IDE em: http://wxdsgn.sourceforge.net/?q=node/4 e instalá-la. O instalador da IDE faz todo trabalho de instalação da wxwidgets pra você.
 

Primeiro Programa
    No nosso primeiro programa vamos simplesmente criar uma janela com um texto no centro e um botão que ao ser clicado finaliza a aplicação.




Segue abaixo o código.


#include <wx/wx.h>
//frame.h

class MeuFrame : public wxFrame {
        private:
            wxPanel *painel;
            wxButton *btnsair;
            wxStaticText *label;
        public:
            MeuFrame(const wxString &titulo);
            void Sair(wxCommandEvent &evt);
};

#include "frame.h"
//frame.cpp

MeuFrame::MeuFrame(const wxString& titulo):
          wxFrame(NULL, wxID_ANY, titulo, wxDefaultPosition, wxSize(500, 400))
{
     //cria-se o widget wxPanel que fica dentro de um wxFrame
     painel = new wxPanel(this, wxID_ANY);
     //cria-se o widget wxStaticText que fica dentro do panel
     label = new wxStaticText(painel, -1, wxT("Meu Primeiro Programa com wxWidgets"), wxPoint(100, 200));
     //cria-se o widget wxButton que fica dentro do panel
     //wxPoint inica as coodenadas do botão dentro do painel e wxSize seu tamanho
     btnsair = new wxButton(painel, wxID_EXIT, wxT("Sair"), wxPoint(200, 250), wxSize(50, 30));
     //conecta-se o evento wxEVT_COMMAND_BUTTON_CLICKED ao método sair da classe   //MeuFrame
     //passando como parametro o ID do botão clicado
     Connect(wxID_EXIT, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MeuFrame::Sair));
     //atribui-se o foco ao botão sair
     btnsair->SetFocus();
     //centraliza o Frame na tela
     Centre();
}

void MeuFrame::Sair(wxCommandEvent &evt) {
    //fecha a aplicação
    Close(true);
}

#include <wx/wx.h>
//main.h
class MinhaApp : public wxApp {
    public:
        virtual bool OnInit();
};

#include "main.h"
#include "frame.h"
//main.cpp
//A macro que implementa a aplicação
IMPLEMENT_APP(MinhaApp)

bool MinhaApp::OnInit()
{
    //criamos o Frame passando o titulo da aplicação para o construtor
    MeuFrame *frame = new MeuFrame(wxT("Primeiro Programa com wxWidgets"));
    //mostramos o frame na tela
    frame->Show(true);
    return true;
}