O nome é complicado mesmo, o nome da biblioteca é “Profiglacy“. O nome da biblioteca veio de um SPAM recebido pelo Zed Shaw e ele utiliza esta biblioteca para escrever um programa de nome iHate, que é um cliente para um protocolo parecido com IRC, mas com algumas coisas mais divertidas.
O JRuby é uma implementação da linguagem Ruby para rodar na JVM. Uma das vantagens de uma implementação de Ruby rodando em uma JVM é a possibilidade de tirar proveito de todas as outras coisas que também rodam na JVM.
Exemplos disto são o acesso a EJBs a partir de aplicações Ruby, utilização de código Legado Java, acesso a diversas bibliotecas que já existem para Java e ainda não existem para Ruby.
Outra grande vantagem é a possibilidade de escrever UIs utilizando SWING que é um dos frameworks para UI mais completos disponíveis hoje em dia, mas que quando utilizado com java, tem uma possibilidade muito grande de criar um código horrível.
E para solucionar este problema existe o Profiglacy, que é uma biblioteca Ruby para facilitar a utilização de SWING quando se esta trabalhando com o JRuby.
E neste pequeno tutorial vou criar uma aplicação simples utilizando esta biblioteca. A proposta é um Gerenciador de Tarefas bem simples, mas antes vamos ver do que estamos fugindo …
Criar UI em Java é muito flexível mas muito trabalhoso, o SWING é poderoso mas muito verboso, e a própria natureza do Ruby ja melhora um pouco isto, veja o código abaixo:
1 2 3 4 5 6 | require 'java' @frame = javax.swing.JFrame.new "Old Way, using only SWING from Ruby" @frame.add(@lbl1 = javax.swing.JLabel.new("Master Title")) @frame.pack @frame.visible = true |
Isto vai criar um jframe com um label, mas ainda assim iriamos precisar de todos aqueles gerenciadores de layout, além de ser necessário também atrelar a ordem de criação dos objetos a posição deles no layout, mas para tudo há uma solução.
O modo padrão de trabalho do Profiglacy melhora isto apenas um pouco, então vamos começar direto com a utilização da Layout Expression Language criada para utilização na biblioteca. É basicamente uma forma fácil de se utilizar um GridLayout …
O layout vai ser definido como uma String, o formato desta string é bastante simples:
- [ .. ] – delimita o inicio e fim de uma linha
- | – delimita uma celula da linha
- label – qualquer nome utilizado dentro de uma celula se torna o nome da celula para referência posterior
- _ – identifica uma celula em branco
- (width) ou (width,height) – define a largura e/ou altura de um componente dentro da celula
- * – Expande a celula
- ^ ou . – Alinham o componente no topo ou na parte de baixo da celula respectivamente
- < ou > – Alinham o componente a esquerda ou direita respectivamente
E é isto, simples assim …
Segue um exemplo para facilitar o entendimento:
1 2 3 4 5 | [ <lbl_proj | cmb_project ] [ <lbl_activ | cmb_activ ] [ <lbl_date | inpt_date ] [ <lbl_hour | inpt_hour ] [ <lbl_description | (300,200)txt_description ] |
Este código define um Grid Layout de 5 linhas por duas colunas, todos os componentes da esquerda estão também alinhados a esquerda e o último componente da direita tem 300 pixels de largura por 200 de altura.
Agora algum de vocês se anima a escrever o código em java para montar isto? Não precisa nem usar o Grid Layout, garanto que vai ficar bem maior.
Claro que as vezes o LEL (Layout Expression Language) não é suficiente, mas para mim parece que isto torna 80% dos casos bastante simples, e quando for necessário isto sempre pode ser combinado com código padrão …
Deem uma olhada no código abaixo, é criada uma UI simples, combinando paineis.
O primeiro painel definido por “main_layout” organiza os grupos de componentes, o primeiro componente recebe um label e os outros dois recebem paineis, criados com LEL mas poderiam ser criados utilizando JPanel.new sem maiores problemas.
TaskManager.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | require 'java' require 'rubygems' require 'profligacy/swing' require 'profligacy/lel' module TaskManager class UI include_package 'javax.swing' include_package 'java.awt' include_package 'javax.swing.border' include Profligacy def initialize(title) main_layout = "[main_label][inputs][buttons]" layout = %Q{ [ <lbl_proj | cmb_project ] [ <lbl_activ | cmb_activ ] [ <lbl_date | inpt_date ] [ <lbl_hour | inpt_hour ] [ <lbl_description | (300,200)txt_description ] } @ui = Swing::LEL.new JFrame, main_layout do |c,i| c.main_label = JLabel.new "Information About New Entry" c.inputs = Swing::LEL.new JPanel, layout do |d,i| d.lbl_proj = JLabel.new "Project" d.cmb_project = JTextField.new d.lbl_activ = JLabel.new "Activity" d.cmb_activ = JTextField.new d.lbl_date = JLabel.new "Date" d.inpt_date = JTextField.new d.lbl_hour = JLabel.new "Hour" d.inpt_hour = JTextField.new d.lbl_description = JLabel.new "Description" d.txt_description = JTextArea.new end.build :auto_create_container_gaps => false c.buttons = Swing::LEL.new JPanel, "[button_save|button_cancel ]" do |e,i| e.button_save = JButton.new "Save" i.button_save = { :action => method(:save_clicked) } e.button_cancel = JButton.new "Cancel" end.build :auto_create_container_gaps => false end @ui.build(:args => "Simple LEL Example").default_close_operation = JFrame::EXIT_ON_CLOSE end def save_clicked(evt_type,event) puts "Test OK 2" end def self.start SwingUtilities.invoke_later proc { UI.new('My Test Frame with long title') }.to_runnable end end end |
Para executar o código precisamos apenas de um arquivo Ruby para chamar o método “start” definido na classe UI, claro que poderiamos ter utilizado o mesmo arquivo .rb, mas isto iria diminuir a possibilidadede reutilização daquele código, então criei o arquivo abaixo:
starter.rb
1 2 3 | require 'TaskManager' TaskManager::UI.start |
Pronto, com este super mini tutorial, você ja pode escrever muito menos código para definir as suas interfaces Java de hoje em diante, para isto só precisa programar em Ruby
Cada vez mais me convenço que o melhor cenário é utilizar java como Plataforma em vez de como Linguagem
PS.: Eu sei que faltou explicar toda a parte de eventos, mas se não for possível inferir isto do exemplo apresentado, postem perguntas nos comentários que escrevo mais algo detalhado sobre isto (isto vai servir também pra ver se alguem lê o que eu escrevo aqui
)

Interessante e condiz com algo que digo a muito tempo por aí: a linguagenm java é tão somente mais uma forma de gerar bytecodes pra JVM.
Não gosta de java ? Usa JRuby. Não gosta de JRuby ? Usa JavaFX… e por aí vai.
( Pra GUI ainda prefiro o JavaFX. )
Abraços,
Mac
Conhece o DesignGridLayout? https://designgridlayout.dev.java.net/
É o layut manager pra swing muito eficiente e prático, principalmente por ser baseado em canonical grids e fluent interfaces.
abraço,
vinicius
parece legal, vou dar uma olhada nele na próxima vez que eu for fazer alguma coisa com Swing
Miglayout owns!