terça-feira, 30 de agosto de 2011

Tutorial wxWidgets e sqlite3 parte 6 - Criando o Projeto e a Interface do programa


Vamos iniciar com a criação do projeto, aqui vou iniciar um projeto no Linux, para quem estiver usando o Visual C++ 2008 no Windows, veja como fazê-lo nos tutoriais anteriores aqui e aqui.

Crie uma pasta onde o projeto será salvo, aqui estou criando em /home/alex/Documentos/tuto_sqlite e vou chamar meu projeto de “agenda”, no caso vai ser bem simples, o objetivo é exatamente incentivar vocês a criarem um projeto com mais campos, depois de terminarmos com os tutoriais, para fixarem bem o conhecimento.

Abrindo o Code::Blocks vamos iniciar um novo projeto wxWidgets, a única coisa que vocês precisam ficar atentos é nesta parte:


Vamos criar um projeto vazio, sem arquivos, pois criaremos tudo na unha como dizem por aí...

Com o projeto aberto criem 6 novos arquivos:

Arquivos de cabeçalho:

main.h
framep.h
//Neste arquivo vamos criar as funções do wxSqlite3
sqlf.h

Aquivos de implementação:

main.cpp
framep.cpp
//Neste arquivo vamos criar as funções do wxSqlite3
sqlf.cpp

Vamos criar então o Aplicativo e a Interface de controle:

Obs.: A explicação está nos comentários do fonte, tentem escrever o programa linha por linha e passe adiante só depois de ter entendido bem o que cada coisa significa, se não conseguirem, os comentários aí do blog servem pra isso mesmo, tirar dúvidas...

O arquivo main.h ficará assim:
//ARQUIVO DO BLOG - http://wxnewbie.blogspot.com
//TUTORIAL wxWidgets + sqlite3 usando wxSqlite3

#ifndef MAIN_H_INCLUDED
#define MAIN_H_INCLUDED

#include <wx/wx.h>

class wxAppTutorial: public wxApp
{
    public:
        bool OnInit(void);
};

#endif

O arquivo main.cpp
//ARQUIVO DO BLOG - http://wxnewbie.blogspot.com
//TUTORIAL wxWidgets + sqlite3 usando wxSqlite3

#include "main.h"
#include "framep.h"

bool wxAppTutorial::OnInit(void)
{
    //Crio o Frame que vai controlar a aplicação
    wxFramePrincipal *frameprincipal = new wxFramePrincipal();

    //Mostro o Frame
    frameprincipal->Show();

    //Passo para wxApp que este frame irá controlar a aplicação...
    //quando ele for fechado, a aplicação também será fechada...
    SetTopWindow(frameprincipal);

    return true;
}

IMPLEMENT_APP(wxAppTutorial)

O arquivo framep.h (Formulário que vai controlar a aplicação)
//ARQUIVO DO BLOG - http://wxnewbie.blogspot.com
//TUTORIAL wxWidgets + sqlite3 usando wxSqlite3

#ifndef FRAMEP_H_INCLUDED
#define FRAMEP_H_INCLUDED

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

class wxFramePrincipal: public wxFrame
{
    public:
        wxFramePrincipal();
    private:

        //Campos para pegar o ID na edição
        //Também irei usá-lo para saber se
        //está em modo de edição ou inserção...
        //Se for igual a -1 é inserção...
        //Se for diferente de -1 é edição
        int ID;

        //O grid que vai exibir os dados existentes na tabela...
        wxGrid *lista_contatos;

        //Labels dos campos...
        wxStaticText *label_nome;
        wxStaticText *label_idade;

        //Os campos de texto onde preencheremos os campos...
        wxTextCtrl *nome;
        wxTextCtrl *idade;

        //Os botões onde iremos executar os eventos de edição do banco...
        wxButton *salvar;
        wxButton *limpar;
        wxButton *deletar;

        //Declaro a tabela de eventos...
        DECLARE_EVENT_TABLE()

        //Eventos...
        //Evento para salvar no banco de dados...
        void OnClickSalvar(wxCommandEvent& event);
        //Evento para limpar os campos e cancelar edição...
        void OnClickLimpar(wxCommandEvent& event);
        //Evento para deletar um campo...
        void OnClickDeletar(wxCommandEvent& event);

        //Evento de seleção do registro que será editado...
        void OnDoubleClickCell(wxGridEvent& event);

        //Aqui eu vejo se os campos estão em branco, e também se idade é um número...
        bool ConfereCampos();
        //Aqui escrevo uma função para limpar os campos
        //Está função será usada para cancelar uma edição
        //e após executar alterações...
        void LimparCampos();

        enum{
            //Identificador do botão salvar
            ID_SALVAR = 1000,
            //Identificador do botão limpar
            ID_LIMPAR,
            //Identificador do botão deletar...
            ID_DELETAR,
            //Identificador do grid...
            ID_GRID,
        };
};

#endif // FRAMEP_H_INCLUDED

O arquivo framep.cpp
//ARQUIVO DO BLOG - http://wxnewbie.blogspot.com
//TUTORIAL wxWidgets + sqlite3 usando wxSqlite3

#include "framep.h"

wxFramePrincipal::wxFramePrincipal():wxFrame(NULL, wxID_ANY, wxT("Teste Tutorial Sqlite3"))
{
    //Altero a cor do background do Frame
    this->SetBackgroundColour(*wxWHITE);

    //Meu BoxSizer Principal...
    wxBoxSizer *boxp = new wxBoxSizer(wxVERTICAL);

    //Inicio a construção do grid...
    lista_contatos = new wxGrid(this, ID_GRID);

    //Começo com 0 linhas e 3 colunas, lembre-se que o número de colunas deve ser igual ao numero de campos
    //Da view que iremos carregar ou do comando select que iremos carregar...
    lista_contatos->CreateGrid(0, 3);

    //Aqui altero o valor dos rótulos de cada coluna...
    //Nunca se esqueça, o vetor começa em 0, tanto para colunas como para linhas...
    lista_contatos->SetColLabelValue(0, wxT("ID"));
    lista_contatos->SetColLabelValue(1, wxT("Nome"));
    lista_contatos->SetColLabelValue(2, wxT("Idade"));

    //Altero a largura padrão do rótulo da linha para 25px...
    //Altero a altura padrão do rótulo da coluna para 25px...
    lista_contatos->SetRowLabelSize(25);
    lista_contatos->SetColLabelSize(25);

    //Desabilito a edição dos valores no grid, a alteração de valores será feita
    //pelos wxTextCtrl's
    lista_contatos->EnableEditing(false);

    //Adiciono o grid no BoxSizer principal...
    boxp->Add(lista_contatos, 1, wxEXPAND, 0);

    //Aqui eu adiciono um separador...
    boxp->Add(0, 0, 0, wxALL, 10);

    //Aqui crio um BoxSizer para arranjar os campos de preenchimento de valores...
    wxBoxSizer *box_texts = new wxBoxSizer(wxVERTICAL);

    //o rótulo para o campo nome...
    label_nome = new wxStaticText(this, wxID_ANY, wxT("Nome"));
    //adiciono o rótulo no box dos valores de preenchimento...
    box_texts->Add(label_nome, 0, wxALL, 2);

    //Faço o mesmo que fiz anteriormente para todos os outros campos...
    nome = new wxTextCtrl(this, wxID_ANY, wxEmptyString ,wxDefaultPosition, wxSize(200, -1));
    box_texts->Add(nome, 0, wxALL, 5);

    label_idade = new wxStaticText(this, wxID_ANY, wxT("Idade"));
    box_texts->Add(label_idade, 0, wxALL, 2);

    idade = new wxTextCtrl(this, wxID_ANY, wxEmptyString ,wxDefaultPosition, wxSize(120, -1));
    box_texts->Add(idade, 0, wxALL, 5);

    //Aqui adiciono o box dos campos de preenchimento no box principal...
    boxp->Add(box_texts, 0, wxLEFT, 40);

    //Agora um box para arranjar os botões...
    wxBoxSizer *box_btns = new wxBoxSizer(wxHORIZONTAL);

    //Um separador...
    box_btns->Add(0, 0, 0, wxLEFT, 40);

    //Botão salvar...
    salvar = new wxButton(this, ID_SALVAR, wxT("Salvar"));
    //Adiciono ao box dos botões...
    box_btns->Add(salvar, 0, wxALL, 5);

    limpar = new wxButton(this, ID_LIMPAR, wxT("Limpar Campos"));
    box_btns->Add(limpar, 0, wxALL, 5);

    deletar = new wxButton(this, ID_DELETAR, wxT("Deletar"));
    box_btns->Add(deletar, 0, wxALL, 5);

    //Adiciono o box dos botões ao box principal...
    boxp->Add(box_btns, 1, wxEXPAND, 0);

    //"Digo" ao meu frame que o boxp é o box principal...
    this->SetSizer(boxp);

    //Aqui apenas faço com que tudo seja arranjado de maneira correta...
    this->Layout();

    //Seto o ID como -1 para saber que inicio em modo de inserção...
    ID = -1;
}

//Aqui minha tabela de eventos declarada...
BEGIN_EVENT_TABLE(wxFramePrincipal, wxFrame)
//Veja que digo para cada evento, que o controle que estiver com
//determinado id, é o que será responsável por executá-lo
//No exemplo de salvar:
//Eu digo que é um evento do tipo EVT_BUTTON, ou seja, um evento executado por um botão...
//O botão responsável pelo evento é o que tiver o identificador: ID_SALVAR
//e o evento que ele vai executar é o OnClickSalvar...

//É muito importante o entendimento desta parte para não acontecer nada de errado...
EVT_BUTTON(ID_SALVAR, wxFramePrincipal::OnClickSalvar)
EVT_BUTTON(ID_LIMPAR, wxFramePrincipal::OnClickLimpar)
EVT_BUTTON(ID_DELETAR, wxFramePrincipal::OnClickDeletar)

//Quando você for criar um evento para grid's repare que alguns levam um CMD no nome e outros não...
//Se você estiver criando uma classe derivada de wxGrid, vc não usa o comando que contém o CMD
//Veja que este comando sem CMD como é o caso de EVT_GRID_CELL_LEFT_DCLICK (comando que é executado
//quando dou 2 cliques em uma célula) não recebe ID nenhum como parâmetro...
//agora se eu for executar o mesmo comando usando um wxGrid como controle no meu frame ou dialogo
//eu uso o comando com CMD como é o caso do evento abaixo...
EVT_GRID_CMD_CELL_LEFT_DCLICK(ID_GRID, wxFramePrincipal::OnDoubleClickCell)
END_EVENT_TABLE()

//Aqui eu inicio a implementação do evento para salvar um registro...
void wxFramePrincipal::OnClickSalvar(wxCommandEvent& event)
{
    //...Os comandos que usaremos aqui, será escrito depois...
}

//Aqui o evento que vai limpar os campos...
void wxFramePrincipal::OnClickLimpar(wxCommandEvent& event)
{
    //...Os comandos que usaremos aqui, será escrito depois...
}

//Aqui o evento quando eu clicar no botão deletar...
void wxFramePrincipal::OnClickDeletar(wxCommandEvent& event)
{
    //...Os comandos que usaremos aqui, será escrito depois...
}

//Aqui o evento que será exxecutado
//quando eu der 2 cliques em uma célula...
void wxFramePrincipal::OnDoubleClickCell(wxGridEvent& event)
{
    //...Os comandos que usaremos aqui, será escrito depois...
}

//Esta função eu vou usar para limpar os campos
//como eu precisarei fazer isto sempre que eu completar uma alteração
//vou escrever este código em uma função em separado...
void wxFramePrincipal::LimparCampos()
{
    //...Os comandos que usaremos aqui, será escrito depois...
}

//Aqui vou conferir os campos para ver se o usuário digitou algo errado...
bool wxFramePrincipal::ConfereCampos()
{
    //...Os comandos que usaremos aqui, será escrito depois...
    return true;
}

Estudem o código, já coloquei nele os eventos que serão usados para o controle das ações. O resultado final da Interface é esse:



No próximo tutorial explicarei como executar alguns comandos usando wxSqlite3 e escreveremos os códigos para fazer a agenda funcionar.

Até a próxima.

2 comentários:

Anônimo disse...

Parabéns, muito bom!

Alex disse...

Valeu!

Postar um comentário