Friday, October 7, 2016

the solution to use javafx with ruby : jrubyfx

Ruby is a cross-platform interpreted language. an easily readable type of syntax. The Ruby language was created by Yukihiro Matsumoto (commonly known as Matz), and it was first released in 1995. it's now one of the top ten languages in use, essentially due to success of the rails framework for web development. here is some of the features that makes Ruby a cool language and worth learning :

  • Purely object-oriented : unlike java there is not primitives types. when you write 10 you are dealing with an object:   10.downto(0){|i| puts i } prints 10 to 0 on each line.
  • Dynamically typed (“duck typed”) : duck typing means that if it walks like a duck and quack like a duck then it's a duck. object doesn't need to implement a specific inteface to do the job as long as it implements the nedded method.
  • Compact syntax :example : compute 1*2*...*100. on line :  puts (1..10).reduce(:*)
  • Closures  or code Blocks. 
  • Open classes : adding a functionality to an existing class has never been so simple, in fact you even redefine classes of the core library.
  • meta-programming support : Metaprogramming is writing code that writes code.
  • Rails framework : write a blog application in less then 30 minutes...

    An interpreted language :

    the original standard version of Ruby is often known as Matz’s Ruby Interpreter (MRI). but over the years many alternative implementations of Ruby have been written. Some, like RubyMotion, MacRuby, and IronRuby, were designed to run on specific platforms. Others, like Topaz  were built using programming languages other than C.  Rubinius, was built
    using Ruby itself. And Matz wrote a smaller version of Ruby called mruby, designed to run inside another application.

    and we come to the JRuby which an implementation of ruby atop the JVM, written in java and ruby. which brings the best of the two worlds : the  beauty of ruby and the power of the JVM. giving in the same time access to all java libraries to the ruby code.


    Getting started :

    first you have to install the JDK     and jruby
    if things went ok : test your installation in the command prompt :

    C:\Users\Hakim>jruby -v
    jruby 9.1.5.0 (2.3.1) 2016-09-07 036ce39 Java HotSpot(TM) 64-Bit Server VM 25.91-b14 on 1.8.0_91-b14 +jit [mswin32-x86_64]
    C:\Users\Hakim> jruby -e "puts 'Hello, Ruby'"
    Hello, Ruby

JRubyFx :

 JavaFX, a new GUI toolkit  destined to be the replacement for Swing. so when jruby can use all the java labraries available, it is logic to think that we can use this technology in ruby. and here come jrubyfx.

first install the appropriate gem :
move to the jruby directory and type  gem install jrubyfx (type chcp 1252 for windows users before). and it's done. you have javafx availble to your ruby code.

here a simple program that create a simple form :
require 'jrubyfx'
 class HelloWorldApp < JRubyFX::Application
   def start(stage)
     stage.title = "Hello World!"
     stage.width = 800
     stage.height = 600
     stage.show()
   end
end
 HelloWorldApp.launch
to demonstrate all that we said here is a simple calclator written in ruby with the help of jrubfx.

and this is the code for building the UI :


require_relative 'calculator.rb'
require 'jrubyfx'

class CalcFx < JRubyFX::Application
  BUTTON_SIZE, GAP=40, 5

  def initialize
    @calculator= Calculator.new
  end

  def start(stage)
    innerGrid=buildGrid
    with(stage, title: 'calculator', width: (BUTTON_SIZE+GAP+1)*5,height: (BUTTON_SIZE+GAP)*7, maximized: false, resizable: false) do
      layout_scene() do
        innerGrid
      end
      stage.scene.stylesheets << 'res/Login.css'
      show
    end

    setShortcuts(stage.scene)
  end

  def buildGrid
    buttons =[
        %w(ce c <- root 1/x),
        %w(1 2 3 / %),
        %w(4 5 6 * sin),
        %w(7 8 9 - cos),
        %w(+/- 0 . + =)
    ]

    vbox      =build(VBox, padding: build(Insets, 5))
    textField =build(TextField, text: 'rrrr', editable: false,alignment: Pos::CENTER_RIGHT, prefHeight: BUTTON_SIZE,disable: true)
    gridPane  =build(GridPane, hgap: GAP, vgap: GAP,alignment: Pos::CENTER, gridLinesVisible: false)

    textField.text_property.bind(@calculator.result_property)
    gridPane.add(textField, columnIndex: 0, eowIndex: 0, columnSpan: 5, rowSpan: 1)


    buttons.each_with_index { |line, line_index|
      line.each { |caption|
        button=build(Button, text: caption, prefWidth: BUTTON_SIZE,minHeight: BUTTON_SIZE)
        if (('0'..'9')=== button.text)
          button.id = 'numpad'
        end
        setButtonsActions(button)
        gridPane.addRow(line_index+1, button)
      }
    }

    vbox.children << textField << gridPane
    vbox
  end


  def setButtonsActions(button)
    button.set_on_action do |e|
      @calculator.handleInput(e.source.text)
    end
  end

  def setShortcuts scene
    scene.set_on_key_pressed do |keyEvent|
      case keyEvent.code
        when KeyCode::NUMPAD0, KeyCode::NUMPAD1, KeyCode::NUMPAD2, KeyCode::NUMPAD3,KeyCode::NUMPAD4, KeyCode::NUMPAD5,
            KeyCode::NUMPAD6, KeyCode::NUMPAD7, KeyCode::NUMPAD8, KeyCode::NUMPAD9 then
          @calculator.handleInput((keyEvent.code.to_s)[-1])
        when KeyCode::ENTER then
          @calculator.handleInput('=')
        when KeyCode::SUBTRACT then
          @calculator.handleInput('-')
        when KeyCode::ADD then
          @calculator.handleInput('+')
        when KeyCode::MULTIPLY then
          @calculator.handleInput('*')
        when KeyCode::DIVIDE then
          @calculator.handleInput('/')
        when KeyCode::DECIMAL then
          @calculator.handleInput('.')
        when KeyCode::BACK_SPACE then
          @calculator.handleInput('<-')
        when KeyCode::ESCAPE then
          @calculator.handleInput('c')
      end
    end
  end

end


CalcFx.launch

 


the full code source is available at github (rubyMine project): https://github.com/mooninvader/Rubycalcfx

links :

jruby home
jrubyfx home

No comments:

Post a Comment