O que eu quero dizer: ter um estado emocional estável e sereno não é a nossa configuração biológica padrão. É algo que se aprende, que se pratica. E é um esforço constante pois, no menor descuido, você se vê de volta à selva.

A vida é embasada em atitudes e respostas constantes. O estilo de ser é individual, mas as situações são as mesmas ao irmão que prefere o clamor do Globo seja sob os holofotes ou a ânsia pelo poder que satisfaz momentaneamente o ego e o compromete ao menor gesto praticado na linha do inviável.
Vida resume-se a estilo próprio e característica condizente com as práticas e leis do amor de Deus. Seja leve para que no momento de deixar o Globo, a sua partida lhe abra portas desconhecidas pelo viajor comum. Os ensinamentos de Jesus estão disponíveis e você, está apto a praticá-los? Analise, conclua.

A gem qtbindings na verdade faz um bind com a gem QT. Na prática, ela faz praticamente a mesma coisa que o JRuby faz com bibliotecas Java: traduz os métodos que seriam C++ para Ruby. Por exemplo, um método QMainWindow#setWindowTitle(QString title) será traduzido para ruby como Qt::MainWindow#window_title = “Some Ruby String”.
Basicamente, a tela é montada no Qt Designer, um aplicativo da própria QT e que provavelmente virá instalado na maior parte dos Linux. Ao salvar cada tela, teremos um arquivo .ui. Esse arquivo será convertido num código Ruby de interface usando o programa rbuic4, que já vem com a gem qtbindings. Depois, só precisamos fazer um “require” nesse arquivo gerado, e mapear nossos eventos. Na verdade, o processo todo é bem simples, então vou usar o espaço aqui do blog para falar da organização dos arquivos.
Eu costumo deixar todos os arquivos que eu gero com o rbuic4 numa pasta chamada ui. Dessa forma, eu posso só fazer require_relative ‘ui/main.rb’ e já possuo uma classe chamada Ui::Main, que eu posso usar. É importante mencionar que cada tela que criamos no designer deve ter seus nomes alterados para que reflitam um nome de uma classe, caso contrário o rbuic4 pode gerar arquivos inválidos. Para mapear uma classe, eu costumo fazer o seguinte (assumindo que criamos uma QMainWindow no designer chamada Main, por exemplo):
Isso já cria uma tela principal. Se quisermos mostrar essa tela, podemos usar o seguinte comando (digamos, num outro arquivo “start.rb”):
Repare bem nas linhas 5 e 6: Perceba que eu atribuí uma variável “main”, e só depois eu rodei show. Ao contrário de Java, aonde poderíamos fazer algo como new Main().show(), isso não é válido em QT – e o motivo será explicado mais tarde. Por hora, entenda a seguinte regra: todo objeto de interface precisa manter-se referenciado enquanto está sendo exibido na tela. Ele nunca pode sair de escopo.
Mas nenhum aplicativo desktop está bom se não puder reagir a eventos. Então, digamos que na nossa UI temos um objeto chamado “button”, e que queremos reagir a eventos de click pra ele. Pela documentação, vemos que ele responde a alguns sinais, e um deles é clicked(bool checked=false). Conectamos usando um método especial – SIGNAL – no qtbindings:
A partir daí, fazer interfaces gráficas em Ruby é um sossego – apenas conectamos eventos e usamos Ruby normalmente.
Conectar eventos dessa forma é mais “Java” e “C” do que “Ruby”. Podemos tentar minimizar o impacto de tais operações usando um Hash como representação da tela. Imagine, por exemplo, que temos um banco de dados com uma tabela chamada people, e com os campos: name, age, e birth_date. Se fizermos uma interface no QT Designer, podemos nomear um campo de texto como name, um campo do tipo QSpinBox do chamado age, e um do tipo QDateEdit chamado birth_date.
A primeira coisa que teríamos que fazer, nesse caso, seria mapear que todos esses objetos retornem uma API igual. Para facilitar, vamos dizer que todos precisam suportar os métodos text e text=. Podemos resolver isso com monkey-patch:
Depois disso, podemos usar nosso próprio modelo Ruby para definir os campos que vamos usar da interface, e dessa forma promover a exibição automática dos dados na tela (no caso de uma consulta) ou salvar o registro (no caso de criação/modificação) sem precisar de muito código:
Essa abordagem tem MUITAS vantagens: a principal está acima, porém outras podem ser: em caso de erro, temos um mapeamento simples em que podemos deixar todos os campos que deram erro em vermelho, ou o fato de já termos um mapeamento dos campos permite “zerar” todos os campos para seus valores padrão, etc.
O qt_bindings possui um problema muito sério: todos os bindings dele de C++ para Ruby são feitos de forma automática usando uma biblioteca C++ chamada SMOKE. O problema do smoke é que seus bindings são extremamente fracos: primeiro, ele tenta fazer mais ou menos o que o JRuby faz com Java: tenta converter camelCaseMethods para camel_case_methods, e setValue(String) para value = String. Isso é muito bom, o problema é que quando tentamos fazer alguns códigos – por exemplo, se tentarmos fazer um some_input.text = 10, ele vai dar um erro de UndefinedMethod. Claro que o método está definido – o problema é que a assinatura não bateu. Às vezes, isso é difícil de achar.
Outra coisa perigosa é que o SMOKE não sabe quando seus objetos estão em foco ou não. Em Java, com Swing por exemplo, você pode usar algo como new MainWindow().show() que tudo funciona tranquilamente. Em Ruby com qt_bindings, isso não acontece. Os códigos abaixo, ambos, dariam problemas:
Provavelmente você teria uma mensagem de erro BEM bizarra do tipo: UndefinedMethodError: no method “strip!” for 10:Fixnum, numa linha que obviamente chamaria o método strip! numa variável de instância que só poderia ser uma String. Isso acontece, bizarramente, porque o SMOKE não detectou que tinha que manter aquela variávem de instância em foco, então o Ruby chamou o Garbage Collector, coletou a variável, e o interpretador pôs um número no lugar (ou qualquer outro objeto – nesse caso, obviamente, a parte 10:Fixnum iria mudar). Ou, às vezes, ele dará um SegFault falando que o interpretador Ruby quebrou…
O ponto é: usando qt_bindings, SEMPRE mantenha as telas que estão sendo exibidas em foco. SEMPRE. Nem que você tenha que criar variáveis de instância em classes que não precisariam mantê-las. O qt_bindings NÃO FARÁ ISSO PRA VOCÊ, então fique atento. Estou pegando muito nessa tecla porque é um dos problemas mais difíceis de resolver, e um dos que eu mais cometi nas últimas vezes que mexi com Qt4.
Tirando esses problemas, interfaces gráficas com Qt e Ruby são fascinantemente simples de se fazer, e muito fáceis de se programar. A única coisa que ainda fica em falta é uma boa forma de testá-las unitariamente, que infelizmente no ramo de interfaces gráficas, ainda é uma grande deficiência.