Criando uma classe de janela em FLTK2 usando o FLUID

Reblog de um antigo post meu sobre programação. Espero que seja útil.

Simples e multiplataforma, a FLTK (lê-se ?fullticks?) é uma interface gráfica despretenciosa e que oferece recursos básicos para o seu desenvolvedor. Ela gera programas extremamente enxutos e leves em sua interface gráfica e está disponível em várias das principais plataformas e SOs da atualidade.

Nesse artigo, veremos como desenvolver uma classe de Janela utilizando-se do FLUID, um gerador de interface simplificado que vêm com o FLTK.

Nota: Os exemplos serão apresentados para o Dev-C++ for Windows. Para outros compiladores e ambientes operacionais, leia a documentação do compilador e obtenha maiores informações em http://www.fltk.org e http://www.fltk.net. Apesar disso, os exemplos de programação são todos genéricos, podendo ser usados em qualquer platadforma e compilador.

1-) Obtendo os DevPaks:

O Dev-C++ tem como principais características ser free software (GPL) e ser muito extensível, através dos DevPaks, pacotes especiais instalados no ambiente de desenvolvimento. Se você não tiver o Dev-C++, você poderá o obter em http://www.bloodshed.net/dev.

A primeira coisa é obter o DevPak do FLTK. Ele pode ser obtido em http://www.fltk.net/files/devpak/FLTK2.DevPak. Você também precisará do DevPak de libpthreads, copiado em http://www.fltk.net/files/devpak/libpthread.DevPak. Esses dois pacotes são necessários.

Com o Dev-C++ instalado, basta clicar duas vezes nos arquivos dos DevPak. Instale primeiro o libpthread.DevPak, em seguida o FLTK2.DevPak.

2-) Preparando o Dev-C++:

Você precisará preparar o ambiente, inserindo nele o FLUID. Para isso, clique no menu Ferramentas. Você terá um menu semelhante o abaixo.

No caso, o FLUID já está inserido, mas vejamos como inserí-lo no menu. Escolha a opção ?Configurar Ferramentas?. Aparecerá uma janela como a abaixo.

Clique em ?Adicionar? e você receberá uma nova janela, como a seguinte:

Digite ?FLUID? em Título e escolha os caminhos do programa e do diretório de trabalho. Em geral o caminho do programa será C:\Dev-Cpp\bin\fluid.exe, e o diretório de trabalho,C:\Dev-Cpp\bin\. Corrija esses dados conforme sua instalação. Clique OK. Aparecerá a entrada do FLUID na Janela ?Configuração das Ferramentas?. Clique OK. O FLUID já deverá estar no menu Ferramentas do Dev-C++.

Agora que o Dev-C++ já está configurado, vamos passar a ver como o FLUID funciona.

3-) Desenhando uma tela no FLUID:

Para começar, chame o FLUID no Menu Ferramentas. Você deverá receber uma janela como a seguinte.

O FLUID exige uma função para poder começar a criar os Widgets (os objetos de Janela). Para colocar uma função no fluid, vá em New | Code | Function/Method.

Você receberá uma janela como a seguinte (você pode ignorar por enquanto as opções e ir direto ao assunto clicando OK):

Com o tempo você poderá ver essas opções. De imediato, ignore-as e vamos para o assunto que é criar a janela: Vá em New | Group | fltk::Window. Isso irá lhe abrir uma janela. Clique duas vezes sobre ela e você irá receber uma janela de configurações do Widget. Sempre que precisar dessa janela para um certo Widget, clique duas vezes sobre ele:

Por enquanto vamos nos ater à aba GUI. Na aba Style você encontrará configurações relacionadas a cores e fontes do Widget. Na aba C++, você encontrará configurações expecíficas de C++, como visibilidade do Widget e por aí afora.

Na aba GUI, para a Window, alteraremos apenas a propriedade Label. Diferentemente de outras APIs de Interface Gráfica, a FLTK coloca labels em todos os seus componentes. Na verdade, o componente raiz de todos os demais componentes, fltk::Widget, pode ser usado como um Label caso necessário. No caso, vamos definir o Label como ?Hello World!?. As demais propriedades podem ficar como estão. Clique em OK ou aperte ENTER.

Agora temos uma janela vazia com um título na Janela (?Hello World!?). Agora vamos adicionar dois componentes na janela, mais exatamente um fltk::Input e um fltk::ReturnButton. Para isso, clique com o botão direito sobre a Janela. Você irá receber um menu semelhante àquele aonde você adicionou a função e a Janela. Escolha primeiro text | fltk::Input. Dimensione-a e posicione-a aonde preferir, como em qualquer outro ambiente RAD (como o VisualStudio ou o Delphi). Depois de posicioná-lo aonde desejar, clique duas vezes sobre o Input para chamar a janela de propriedades. O fltk::Input é como um componente Edit do Delphi ou um TextBox do VisualStudio. Ele aceita dados e pode alterá-los e tudo o mais.

Na janela de propriedades do fltk::Input, primeiro digite em Label ?Digite o seu nome:?. Depois, vá até Alignment. Perceba que há quatro setas indicando para as quatro direções básicas (para cima, para baixo, direita e esquerda). Clique na seta para cima para marcá-la e na seta para a direita para desmarcá-la. Clique novamente em OK ou pressione Enter. Repare que o label foi parar em cima do Input e centralizado em relação a ele.

Vamos agora para o fltk::ReturnButton. O fltk::ReturnButton é como um botão normal de outros RAD, mas com uma diferença fundamental: no Window aonde ele estiver, ele sempre será acionado quando a tecla Enter for pressionada. Você deve estar pensando agora no botão OK dentro da janela de propriedades do FLUID: ele é um fltk::ReturnButton. Para botões normais, a FLTK oferece o componente fltk::Button, sendo que o fltk::ReturnButton e o fltk::ReturnButton são intercambiáveis.

Clique duas vezes no fltk::ReturnButton. Na janela de propriedades, vamos mudar apenas o Label para ?Hello World!?.

Se você seguiu corretamente todos os passos, você deverá ter conseguido um Form similar a esse:

Se você conseguiu, parabéns! Você criou sua primeira janela no FLUID. Vá em File | Save e salve a janela criada pelo FLUID.

Nota: Em Windows o FLUID tem um bug no qual não pode salvar-se nenhuma janela em diretórios que tenham espaço no nome. Tenha sempre isso em mente ao salvar a janela.

Depois de salvar a janela, vá em File | Write Code. O FLUID irá gerar dois arquivos com o mesmo nome que você deu para a sua janela, mas com extensões .cxx e .h. Serão esses os arquivos que iremos usar no projeto. Pode fechar o FLUID após isso.

4-) Criando um Projeto FLTK2:

OK… Agora que fechamos o FLUID, a primeira coisa que precisamos fazer é voltar ao Dev-C++ e criar um projeto FLTK2 para podermos compilar o código gerado no FLTK.

Voltando ao projeto… Imaginando que tudo tenha sido feito corretamente, você agora terá dois arquivos, .cxx e .h. E agora voltamos ao Dev-C++.

A primeira coisa é ir em Arquivo | Novo | Projeto. Vai abrir-se uma janela como a abaixo:

Escolha, na guia GUI, FLTK2 (Static). Dê um nome qualquer ao projeto nas Opções de Projeto (Por exemplo, Teste). Vai se abrir uma janela normal, solicitando um local para gravar o arquivo .dev do projeto. Escolha um diretório qualquer conveniente para salvar este arquivo. Você receberá uma janela como a seguinte:

Perceba que o sistema já lhe gera um main.cpp. Não iremos o utilizar, mas se quiser compilá-lo para fazer um teste se o FLTK está bem instalado, pressione F9 ou vá em Executar | Compilar & Executar. Salve o arquivo se necessário (no diretório escolhido para o projeto!), e se tudo foi instalado corretamente (e deve ter sido para ter chegado até aqui), você receberá a seguinte janela:

PS: Os ícones na Barra de Tarefas não são partes da FLTK, e sim de um Plugin do WinAMP chamado WinAmpBar…

Se estiver tudo OK, voltemos ao projeto. Vamos inserir os dois arquivos gerados pelo FLUID no projeto. Para isso, copie os arquivos gerados pelo FLUID para o diretório aonde você salvou o seu projeto. Aproveite e renomeie o arquivo, mudando sua extensão de .cxx para .cpp. Depois, vá até o lado direito, aonde está o teu projeto e clique com o botão direito. Um menu como o abaixo irá aparecer. Clique em Adicionar ao Projeto e escolha os arquivos gerados pelo FLUID (relembrando que o .cxx teve sua extensão alterada para .cpp) .

Após adicionar os arquivos, você terá três arquivos no seu projeto: main.cpp e os arquivos .cpp e .h gerados pelo FLUID. Vejamos o .h (no caso, teste.h):

// generated by Fast Light User Interface Designer (fluid) version 2.0002

#ifndef teste_h

#define teste_h

#include <fltk/Window.h>

#include <fltk/Input.h>

#include <fltk/ReturnButton.h>

extern “C” { fltk::Window* make_window(); }

#endif

Na verdade, não vamos aproveitar muito desse código. Vejamos agora o .cpp (no caso, teste.cpp):

// generated by Fast Light User Interface Designer (fluid) version 2.0002

 

#include “teste.h”

 

fltk::Window* make_window() {

fltk::Window* w;

{fltk::Window* o = new fltk::Window(267, 99, “Hello World!”);

w = o;

o->begin();

{fltk::Input* o = new fltk::Input(30, 25, 205, 25, “Digite seu nome:”);

o->align(fltk::ALIGN_TOP);

}

{fltk::ReturnButton* o = new fltk::ReturnButton(70, 60, 130, 25, “Hello World!”);

o->shortcut(0xff0d);

}

o->end();

}

return w;

}

Agora podemos dizer qual será a idéia: perceba que o FLUID gerou os objetos que fltk::Window, fltk::Input, e fltk::ReturnButton usando comandos new, pois eles são objetos declarados nos headers (cabeçalhos) <fltk/Window.h>, <fltk/Input.h> e <fltk/ReturnButton.h>, que são importados no header teste.h. No caso, a idéia será declarar em teste.h uma classe herdando de fltk::Window, e dentreo criar um fltk::Input*, e fltk::ReturnButton*, dessa forma usando os comandos já gerados pelo FLUID para gerar os objetos durante à construção de nossa classe herdada. Na destruição da mesma, deveremos também lembrar de destruir os objetos fltk::Input*, e fltk::ReturnButton*, devolvendo a memória usada por ele.

Vamos começar:

5-) Modificando o .h:

Primeiro de tudo, vamos alterar o header teste.h. Para isso, vamos retirar a linha:

extern “C” { fltk::Window* make_window(); }

E colocar o seguinte código para definirmos a classe:

using namespace fltk;

 

class wHelloWorld:public Window

{

private:

Input *txtHelloWorld;

ReturnButton *btnHelloWorld;

public:

wHelloWorld();

~wHelloWorld();

};

Se você conhece bem C++, deve ter notado que originalmente declaramos que o header usa o namespace fltk. Quando falavamos lá em cima em fltk::ReturnButton, queríamos dizer um objeto ReturnButton no namespace fltk. Com o uso do comando using namespace fltk, evitamos a necessidade de indicar o namespace toda vez. Caso você acredite que você possa ter conflito de nomes usando esse método, utilize a declaração explícita com o fltk::.

Logo em seguida declaramos a classe wHelloWorld, que herda todos os métodos públicos de fltk::Window. Perceba que aqui poderíamos fazer sobrecarga dos vários métodos que a FLTK oferece para sua classe fltk::Window. No caso, porém, não iremos fazer isso. Continuemos, então.

Em seguida, declaramo dois ponteiros para objetos FLTK como privativos: Input *txtHelloWorld e ReturnButton *btnHelloWorld. Esses ponteiros indicarão os objetos que iremos manipular.

Logo abaixo, declaramos o construtor e o destrutor da classe wHelloWorld. Será neles que iremos manipular os objetos, criando-os antes do uso pelo software e os destruindo quando a janela for destruída.

Se você compilar o programa, você receberá o mesmo ?Hello World? visto anteriormente, já que não implementamos a classe wHelloWorld. Então vamos fazer isso.

6-) Implementando a classe wHelloWorld:

Agora vamos passar para a implementação da classe wHelloWorld. Antes, porém, vejamos o código gerado pelo FLUID para a janela em teste.cpp:

// generated by Fast Light User Interface Designer (fluid) version 2.0002

 

#include “teste.h”

 

fltk::Window* make_window() {

fltk::Window* w;

{fltk::Window* o = new fltk::Window(267, 99, “Hello World!”);

w = o;

o->begin();

{fltk::Input* o = new fltk::Input(30, 25, 205, 25, “Digite seu nome:”);

o->align(fltk::ALIGN_TOP);

}

{fltk::ReturnButton* o = new fltk::ReturnButton(70, 60, 130, 25, “Hello World!”);

o->shortcut(0xff0d);

}

o->end();

}

return w;

}

Perceba que ele começa com uma função chamada make_window(), que retorna um ponteiro para uma fltk::Window. Vamos tirar isso e colocar o nosso construtor:

wHelloWorld::wHelloWorld()

:Window(267, 99, “Hello World!”)

{

Window* w;

Perceba que aproveitamos a declaração da Janela gerada pelo FLUID, e aproveitamos o ponteiro fltk::Window* w declarado, pois precisaremos de um fltk::Window* dentro do construtor, e o fltk::Window* w declarado presta-se bem para isso.

Agora, vamos substituir as seguintes linhas:

{fltk::Window* o = new fltk::Window(267, 99, “Hello World!”);

w = o;

o->begin();

Pelo seguinte código:

w=this;

w->begin();

Utilizamos aqui o ponteiro this para auto-referenciar nosso objeto wHelloWorld específico. Em seguida, chamamos o método (ou função-membro, se você preferir) begin() de w, lembrando que w foi inicializado como this, ou seja, como o próprio objeto sendo criado. Esse método begin() é herdado por fltk::Window de fltk::Group e indica aonde o FLTK deverá começar a contar os objetos seguintes como parte da Window. Podemos dizer, utilizando o jargão do VB.Net, que a classe Window é um componente coleção (ou um objeto container, no jargão do Delphi), ou seja, pode ?armazenar? dentro dele outros objetos. Tudo que acontece com ele, acontece aos demais objetos: se ele é desativado, todos os demais objetos o são. Se ele é destruído, todos os demais o são também (em teoria, mas não custa nada dar uma reforçada).

Agora vamos inicializar o ponteiro para nossa.caixa de texto (ou Input), substituindo o seguinte código:

{fltk::Input* o = new fltk::Input(30, 25, 205, 25, “Digite seu nome:”);

o->align(fltk::ALIGN_TOP);

}

por:

txtHelloWorld = new Input(30, 25, 205, 25, “Digite seu nome:”);

txtHelloWorld->align(ALIGN_TOP);

Perceba que a sintaxe de quase todos os objetos FLTK é a mesma

<obj>(<x>,<y>,<l>,<h>,<caption>)

Aonde <obj> é o nome da classe, <x> e <y> indicam a posição aonde o objeto será inserido dentro do conteiner (no caso, wHelloWorld) em pixels, <l> e <h> indicam respectivamente a largura e a altura do objeto (também em pixels), e <caption> guarda um texto a ser exibido próximo (ou dentro) do objeto. No caso, o nosso txtHelloWorld é um Input (equivalente ao TextBox do VB.Net e ao TEdit do Delphi), será construído a 30 pixels do canto direito e a 25 pixels do topo do conteiner dele (no caso, wHelloWorld), terá 205 pixels de largura, 25 pixels de altura e exibirá próximo a ele o texto ?Digite seu nome:?.

Você deve estar se perguntando ?como o FLTK sabe aonde posicionar o texto dos objetos??. Todos os objetos da FLTK possuem um método align() que retorna/define o alinhamento do objeto FLTK específico. Seu default varia de objeto para objeto, mas em geral para os objetos container (como Window ou Group) fica no topo, centralizado (ou de outra forma no padrão do gerenciador de janelas), em objetos de edição (como Input, Output ou RadioButton) à esquerda, centralizado na altura e nos demais casos (como Button ou Label), dentro do Widget. No caso, utilizamos o comando

txtHelloWorld->align(ALIGN_TOP);

para indicarmos que queremos alinhar o texto do nosso txtHelloWorld acima do mesmo, centralizado em relação ao Widget.

Nota: para pessoas que vêem do background do Delphi e do VB, deve ser difícil imaginar o texto como sendo o label do widget. Em ambos os casos, normalmente o texto equivale ao que vai dentro do widget. Na verdade, existe uma diferença aqui entre label e valor. O texto (label) é o texto que indica para o usuário o widget. Já o que o VB e o Delphi entendem como texto é chamado na FLTK de valor (método value()). Veremos mais sobre isso quando estivermos desenvolvendo o código que interagem com a janela.

Falta pouco para convertermos a nossa janela do FLUID em classe. Mude o seguinte código:

{fltk::ReturnButton* o = new fltk::ReturnButton(70, 60, 130, 25, “Hello World!”);

o->shortcut(0xff0d);

}

Para:

btnHelloWorld = new ReturnButton(70, 60, 130, 25, “Hello World!”);

Perceba que não estaremos aproveitando o código:

o->shortcut(0xff0d);

}

Isso porque, como o botão escolhido já é um ReturnButton, ou seja, um Botão acionado quando a tecla Return é pressionada, não há necessidade de definir-se um atalho de teclado para ele, que é a função do método shortcut().

Agora vamos terminar tudo, substituindo esse código:

o->end();

}

return w;

Por este:

w->end();

Perceba que não aproveitamos o return, pois quando utilizamos construtores é esperado que o mesmo receba o objeto construído ao término de sua construção.

Com isso terminamos o construtor. O destrutor é ainda mais simples:

wHelloWorld::~wHelloWorld()

{

delete txtHelloWorld;

delete btnHelloWorld;

}

Ou seja, apenas destrói os objetos criados pela nossa classe wHelloWorld.

No fim das contas, esse é o código que deveremos ter ao fim de tudo:

// generated by Fast Light User Interface Designer (fluid) version 2.0002

 

#include “teste.h”

 

wHelloWorld::wHelloWorld()

:Window(267, 99, “Hello World!”)

{

Window* w;

w=this;

w->begin();

txtHelloWorld = new Input(30, 25, 205, 25, “Digite seu nome:”);

txtHelloWorld->align(ALIGN_TOP);

btnHelloWorld = new ReturnButton(70, 60, 130, 25, “Hello World!”);

w->end();

}

 

wHelloWorld::~wHelloWorld()

{

delete txtHelloWorld;

delete btnHelloWorld;

}

Mas se você compilar e rodar o programa ainda estaremos recebendo o bendito HelloWorld! Como fazer para receber a nossa janela? Veremos isso agora:

 

 

7-) Chamando a Janela desenhada:

Voltemos agora para o nosso main.cpp. Se você estiver usando o DevPak correto no Dev-C++, você deverá ter o seguinte main.cpp:

// This is just small FLTK2 application

// Now you can imediately compile&run it in Dev-C++

// Enjoy FLTK2 – Dejan Lekic, dejan@fltk.net, http://dejan.lekic.org

 

#include <fltk/Window.h>

#include <fltk/Widget.h>

#include <fltk/run.h>

using namespace fltk;

 

int main(int argc, char **argv) {

Window *window = new Window(300, 180);

window->begin();

Widget *box = new Widget(20, 40, 260, 100, “Hello, World!”);

box->box(UP_BOX);

box->labelfont(HELVETICA_BOLD_ITALIC);

box->labelsize(36);

box->labeltype(SHADOW_LABEL);

window->end();

window->show(argc, argv);

return run();

}
Perceba que ele já tem uma janela dentro dele. Vamos modificar o código para que ele receba nossa Janela e a abra.

Primeiro de tudo, remova todo o código de dentro da função main. Mantenha a definição da função e os parâmetros, e mantenha também o return run(). Você provavelmente terá algo como:

// This is just small FLTK2 application

// Now you can imediately compile&run it in Dev-C++

// Enjoy FLTK2 – Dejan Lekic, dejan@fltk.net, http://dejan.lekic.org

 

#include <fltk/Window.h>

#include <fltk/Widget.h>

#include <fltk/run.h>

using namespace fltk;

 

int main(int argc, char **argv)

{

return run();

}

OK… Agora vamos eliminar todos os #includes desnecessários: apague as seguintes linhas:

#include <fltk/Window.h>

#include <fltk/Widget.h>

E as substitua por:

#include ?teste.h?

Com isso você estará indicando ao sistema que você tem um header teste.h, que você precisará usar. Lembre-se que é em teste.h que é aonde está a definição da nossa classe wHelloWorld.

Perceba que não removemos o header <fltk/run.h>, pois precisaremos da função run() definida nele, que retorna um int com um código de erro caso tenha havido uma falha de execução, ou 0 se o programa executou normalmente.

Agora falta muito, muito pouco. Dentro da função main , escreva este código antes de return run():

wHelloWorld *frmHelloWorld=new wHelloWorld();

frmHelloWorld->show();

O que fazemos aqui é:

  1. Criar um objeto wHelloWorld chamado frmHelloWorld;

  2. Chamar o método show() do objeto frmHelloWorld, que ele herdou da classe fltk::Window;

Se tudo estiver OK, você tem o seguinte código:

// This is just small FLTK2 application

// Now you can imediately compile&run it in Dev-C++

// Enjoy FLTK2 – Dejan Lekic, dejan@fltk.net, http://dejan.lekic.org


#include “teste.h”

#include <fltk/run.h>

using namespace fltk;


int main(int argc, char **argv) {

wHelloWorld *frmHelloWorld=new wHelloWorld();

frmHelloWorld->show();

return run();

}
Se estiver, rode e compile o programa, você deverá ter uma janela como a seguinte:

😎 Implementando funcionalidades na Janela:

Agora, porém, tente clicar no Botão ?Hello World!? ou pressionar Return dentro da caixa de texto. Você perceberá que nada acontece! Isso se deve pelo fato de que não avisamos para o FLTK o que ele deve fazer quando o ReturnButton for clicado. No FLTK, isso é feito através de callbacks.

Para aqueles que vêm do panorama VB.Net, podemos comparar toscamente o callback como uma espécie de delegate ao contrário. No delegate, é o objeto que avisa ao sistema que que algo aconteceu com ele, e é o sistema quem deve ter uma função para tratar o evento delegado (daí o nome delegate). No callback, é o sistema quem fornece ao objeto uma função que ele deverá chamar quando algo acontecer com ele (o que que dizer, mal e mal, callback em inglês).

Em FLTK, exige-se que o callback tenha a seguinte estrutura:

void <nome_func>(Widget*, void*);

Onde <nome_func> é uma função que recebe dois parâmetros: um ponteiro para o Widget que disparou o evento (normalmente não-usado) e um ponteiro void (em geral, é por onde vem a janela aonde está o Widget).

Além disso, o FLTK, quando usado em classe, exige que os callbacks não sejam funções membros não-static. Nesse caso restam três opções:

  1. usar funções membro static;

  2. deixar os Widget públicos ou;

  3. usar funções friend;

No caso, adotaremos a terceira opção: até agora não consegui utilizar a primeira no Dev-C++ (por algum motivo de configuração, creio eu) e a segunda não é das melhores opções.

Para quem não sabe o que são funções friend, elas são funções não-membro (ou seja, não fazem parte do objeto) que podem acessar os dados privativos e protegidos (private e protected). Embora elas violem os conceitos de OOP, o uso de friend permite alguns recursos interessantes, como no nosso caso.

Comecemos modificando o teste.h. Nas declarações de #include, adicione as seguintes linhas:

#include <fltk/ask.h>

#include <iostream>

Precisaremos da função fltk::message() (declarada no header <fltk/ask.h>) e do objeto std::string, que pertence ao namespace std (e que está incluído no header <iostream>).

Para nos facilitar a vida com o string, logo abaixo de:

using namespace fltk;

Inclua essa linha:

using namespace std;

Descendo na definição da classe, na parte public, inclua essa linha:

friend void HelloClick(Widget* w, void* v);

Perceba que essa função HelloClick possui exatamente o tipo de parâmetros exigidos por padrão de um callback, como vimos anteriormente.

Aqui acabamos com a questão da definição de classe. Voltemos para o código. No construtor da classe wHelloWorld, logo abaixo a criação do objeto btnHelloWorld, acrescente essa linha:

btnHelloWorld->callback(HelloClick,w);

Nesse caso, utilizamos o método callback do objeto btnHelloWorld para definir o callback do mesmo. No caso, esse método possui o seguinte protótipo, definido em <fltk/Widget.h>:

void callback(Callback* c, void* p);

No caso, definimos como Callback* (um ponteiro de função interno do objeto) nossa função HelloClick (ela é passada como um ponteiro para a função) e passamos como void* o nosso ponteiro w (lembre-se que w é um ponteiro para o objeto criado). É importante notar que o ReturnButton herda o método callback da classe-mãe geral fltk::Widget. Como ela é a classe-mãe de todas as demais, isso quer dizer que todos os objetos FLTK, sem exceção, possuem métodos callback e, portanto, podem receber funções de callback conforme a necessidade.

OK. Agora, vá até o fim do código fonte e insira o seguinte código:

void HelloClick(Widget* w, void* v)

{

wHelloWorld *to=((wHelloWorld*)v);

string strHelloWorld(“Olá,”);

strHelloWorld+=to->txtHelloWorld->value();

strHelloWorld+=”! Sou um programa em FLTK!”;

message(strHelloWorld.c_str());

}

Vamos explicar agora o que isso faz:

Perceba que essa função void HelloClick(Widget* w, void* v) é declarado de forma semelhante à nossa friend definida na classe. Na prática, essa é a nossa friend! Ela é ligada pela assinatura da função (ou seja, ela é uma função void, chamada HelloClick, que recebe um Widget* (um ponteiro para um Widget)e um void* v (um ponteiro ?vazio? – um ponteiro para alguma coisa qualquer).

A primeira coisa que precisamos fazer é transformar o ponteiro void* v recebido em um ponteiro para a nossa janela.

?Mas ele já não é??, você deve se perguntar.

Sim… e não.

Esse ponteiro aponta para o endereço aonde nossa janela foi alocada, mas ele não sabe que no caso temos um objeto da classe wHelloWorld. Por isso, precisamos trasformar o nosso void* v em um wHelloWorld* (ou seja, um ponteiro para um objeto wHelloWorld). Para isso, utilizamos um cast, como o mostrado na linha abaixo:

wHelloWorld *to=((wHelloWorld*)v);

Perceba a declaração do cast: ele associa ao ponteiro wHelloWorld *to o valor de v, mas alertando para o sistema que v deve ser entendido como um ponteiro para um objeto wHelloWorld (wHelloWorld*). Perceba que essa indicação fica em parênteses, como no caso (wHelloWorld*).

As três próximas linhas criam um objeto std::string e colocam nele informações:

string strHelloWorld(“Olá,”);

strHelloWorld+=to->txtHelloWorld->value();

strHelloWorld+=”! Sou um programa em FLTK!”;

Perceba que não precisamos usar std::, pois já declaramos o uso do namespace std no teste.h na linha using namespace std. O objeto strHelloWorld é inicializado com o texto ?Olá, ?, e ao pouco vai recebendo outros textos que vão sendo contatenados ao fim do texto. Na segunda linha está o interessante:

strHelloWorld+=to->txtHelloWorld->value();

Utilizando o método value() do nosso objeto txtHelloWorld, ele pega o texto digitado na caixa de texto no momento em que o callback for acionado e o concatena ao objeto strHelloWorld criado. Em seguida ele adiciona o fim da saudação.

Depois utilizamos a função não-membro do FLTK message() (ou, no caso de não declarar-se o uso de namespace, fltk::message()) para exibir o texto em uma caixa de informações (mais ou menos como uma versão rudimentar do MsgBox() do VB.Net ou do MessageDlg do Delphi):

message(strHelloWorld.c_str());

Essa função, como dissemos anteriormente, é declarado em <fltk/ask.h>. Ele pode receber dois tipos de parâmetros: um char* que será exibido, ou um texto formatado como na função printf() do C, com os devidos dados a serem exibidos. No caso, precisamos oferecer uma saída do nosso objeto string strHelloWorld como um char* (ponteiro de caracteres, o tipo de string do C). Para isso, usamos o método c_str() do objeto strHelloWorld.

Agora, compile e rode o programa. Se tudo deu certo, quando você digitar um texto na caixa de texto, como:

E pressionar a tecla Return ou clicar no botão ?Hello World!?, você irá receber uma mensagem como a seguinte:

Bem, isso conclui nosso rápido interlúdio na FLTK. Para maiores informações, a API da FLTK2 é divulgada em http://www.fltk.net. Nesse mesmo site podem ser obtidos cópias para consulta offline da documentação FLTK (embora levemente desatualizadas, são muito úteis). Outro site importante também é http://www.fltk.org. Nele você poderá encontrar informações adicionais sobre a FLTK.

Sobre Fábio Emilio Costa
Linux, Free Software, EMACS, Rugby, Indycar, Doctor Who, Harry Potter... Yep, this is me!

2 Responses to Criando uma classe de janela em FLTK2 usando o FLUID

  1. kayo disse:

    HogwartsLinux, gostei haha. Bom artigo.

  2. Kamikaze disse:

    Voce poderia ativar a conta da hospedagem de imagem? não está exibindo nada

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s