Monday, October 8, 2018

Developing a simple tray application in JavaFx



      some desktop applications need to be active for a long time or running in the background waiting for some event to occur, like a mailing for example. tray application is the best choice for this type  of situations.

in javafx we need some help from the AWT library because the javafx doesn't have the equivalent of java.awt.SystemTray yet.

what you see below is the the class responsible for the creation of the tray menu. I think it's
self-explanatory.

import java.awt.AWTException;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.event.ActionListener;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Platform;
import javafx.stage.Stage;

public class TrayManager {
  public TrayManager() {
     }
     
     
     private TrayIcon trayIcon;
     private Stage stage;
     
     public void createTrayIcon(final Stage stage) {
                 this.stage = stage;
                 
   if (SystemTray.isSupported()) {
    // get the SystemTray instance
    SystemTray tray = SystemTray.getSystemTray();
    // load an image
    java.awt.Image image = Toolkit.getDefaultToolkit().getImage(TrayManager.class.getResource("chart.png"));   
    // create a action listener to listen for default action executed on the tray icon
    final ActionListener closeListener = (java.awt.event.ActionEvent e) -> {
                             System.exit(0);
                         };

    ActionListener showListener = (java.awt.event.ActionEvent e) -> {
                             Platform.runLater(() -> {
                                 this.stage.show();                                
                             });
                         };

    // create a popup menu
    PopupMenu popup = new PopupMenu();

    MenuItem showItem = new MenuItem("Show");
    showItem.addActionListener(showListener);
    popup.add(showItem);

    MenuItem closeItem = new MenuItem("Exit");
    closeItem.addActionListener(closeListener);
    popup.add(closeItem);

    trayIcon = new TrayIcon(image, "tray app demo", popup);   
    
                     try {
                         tray.add(trayIcon);                        
                         trayIcon.displayMessage("note", "Application is active", TrayIcon.MessageType.INFO);
                     } catch (AWTException ex) {
                         Logger.getLogger(TrayManager.class.getName()).log(Level.SEVERE, null, ex);
                     }

   }
  }
     
     public void showProgramIsMinimizedMsg() {
   trayIcon.displayMessage("note", "application is mimimized", TrayIcon.MessageType.INFO);
  }
}
we can now create a basic Fxml application that uses the code above :

public class Main extends Application {
 TrayManager trayManager = new TrayManager();
  
 @Override
 public void start(Stage primaryStage) {
  try {
   BorderPane root = (BorderPane)FXMLLoader.load(getClass().getResource("Main.fxml"));
   Scene scene = new Scene(root,400,400);
   scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
   primaryStage.setScene(scene);
   
   
   Platform.setImplicitExit(false);
   
   primaryStage.setOnCloseRequest((WindowEvent event) -> {
    primaryStage.hide();
             event.consume();
         });
   
   primaryStage.setOnHidden((WindowEvent event) -> {
             trayManager.showProgramIsMinimizedMsg();
         });
   
   
   
   
   trayManager.createTrayIcon(primaryStage);
   
   
         
  } catch(Exception e) {
   e.printStackTrace();
  }
 }
 
 public static void main(String[] args) {
  launch(args);
 }
}





here is the result :

note :

the demo application written in eclipse photon can be downloaded from this link :


Tuesday, April 24, 2018

Using multiples FXML files in a javafx application

In this post we assume that you have the knowledge necessary for building your user interface with the JavaFX SceneBuilder.

Usually, one FXMl file represent one screen in the user interface and practically any decent application has more than one.







So how to switch between mutiples fxml files ?


Remember that FXML files are loaded into JavaFX applications by the JavaFX runtime using the FXML Loader class and the result is always a Java object, usually a node such as a Group or a Pane.

So for this purpose we will use a screen controller that holds all of the instances of the fxml files loaded. And every fxml controller will point the instance of that controller.
The screen controller will give the appropriate root to the scene when needed.


public class Controller {
    Pane                     container;
    Map<String, Pane>        screens;  
    public Controller(Pane container) {
        this.container = container;
        screens = new HashMap<>();
    }      

    public void switchContent(String fxml) {            
       container.getChildren().clear();                
       container.getChildren().add(getContent(fxml)); 
    }

    private Pane getContent(String fxml) {        
        if (!screens.containsKey(fxml)) {
            Parent node = loadContent(fxml);
            screens.put(fxml,(Pane) node);
        }        
        return screens.get(fxml);
    }

    private Parent loadContent(String fxml) {
        String path = String.format("%s.fxml", fxml);
        FXMLLoader loader = new FXMLLoader();
        loader.setBuilderFactory(new JavaFXBuilderFactory());
        loader.setLocation(this.getClass().getResource(path));
        Parent page = null;
        try (InputStream in = this.getClass().getResourceAsStream(path)) {
            page = loader.load(in);
            ((Managed) loader.getController()).setScreensController(this);
        } catch (IOException ex) {
            ex.printStackTrace();
        }                     
        return page;
    }         
}

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

Sunday, November 8, 2015

create a custom control in javafx 8

in this tutorial we are going to modify a well known javafx sample : the lcd clock and turn it in a reusable control. so we need to create a custom control that behave that way. the final result will look like this :

custom javafx 8 control


  1. architecture of controls
  2. creating a custom control.
  3. adding events handling to a control.
  4. stylling a control.
  5. source code.
  6. further reading.

architecture of controls

javafx 8 controls hierarchy


all the controls extend the abstarct class Control which in turn extends the class Region. The Region class is a resizable Parent node which can be styled from CSS and also layout the children. the important properties and methods of the Region Class that you must take into account are the following :



Properties of the Region Class
name access type description
width read-only Double the width of the node set by the parent container
height read-only Double the height of the node set by the parent container
minWidth read-write Double the overriden min max, preferred min, preffered and max for width and height of the Region
minHeight read-write Double
prefWidth read-write Double
prefHeight read-write Double
maxWidth read-write Double
maxHeight read-write Double
padding read-write Insets padding of the region



Functions of the Region Class
Name Description
computeMaxHeight(double width)
Computes the maximum height of this region.
computeMaxWidth(double width) Computes the maximum width of this region.
computeMinHeight(double width) Computes the minimum height of this region.
computeMinWidth(double width) Computes the minimum width of this region.

prefWidth and preHeight are by default set to zero. it's up to you to give then an appropiate value. you must take into account the css box model when calculating them :


  • padding is the space between the content and the content’s border.
  • border is the line that’s drawn around each edge of the box.
  • margin is what separates one node from another.
  • the Inset is the sum of the padding and the border.

mvc pattern in javafx 8

Controls follow the classic MVC design pattern. as you can see every Control (the model) has a reference to a single Skin. so there is a one to one relationship between them, The Control Class holds all the properties needed to represent his state and its the responsability of the Skin class to set the visual wich include calculating the min and max dimensions and handle all the interaction with the user.

creating a custom control.

so to implement a custom control we need two classes at leat one which extends the Control Class and one extends the skin Class. each of them have a methode that allow to retrieve the other.
The skin of a control is defined by the Skin<C extends Skinnable> interface. this interface ha three methods :
Name Description
void dispose() Called by a Skinnable when the Skin is replaced on the Skinnable.
 Node getNode() Gets the Node which represents this Skin.
C getSkinnable Gets the Skinnable to which this Skin is assigned.

custom control implementation will extend the Control class, and its skin implementation will extend the SkinBase class :
 in our example the two classes are :

//the control :

public class LcdClock extends Control {

//....

@Override

protected Skin&lt;?&gt; createDefaultSkin() {

return new LcdClockSkin(this);

}

}




//the skin

public  class LcdClockSkin extends SkinBase&lt;LcdClock&gt; {

//....

public LcdClockSkin(LcdClock control) {

super(control);

//....

}

the LcdClockSkin manage the properties of LcdClock and define its size by redefining these methods :
@Override

protected double computePrefHeight(double width, double topInset, double rightInset, double bottomInset, double leftInset) {

return 100;

}

@Override

protected double computePrefWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) {

return 300;

}

@Override

protected double computeMinHeight(double width, double topInset, double rightInset, double bottomInset, double leftInset) {

return 30;

}

@Override

protected double computeMinWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) {

return 100;

}

@Override

protected double computeMaxHeight(double width, double topInset, double rightInset, double bottomInset, double leftInset) {

return computePrefHeight(width, topInset, rightInset, bottomInset, leftInset);

}

@Override

protected double computeMaxWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) {

return computePrefWidth(height, topInset, rightInset, bottomInset, leftInset);

}
the drawing of the clock is done by overrinding this method :
@Override

protected void layoutChildren(double contentX, double contentY, double contentWidth, double contentHeight) {

if (invalidate){

updateClock(contentWidth, contentHeight) ;

invalidate=false;

}

layoutInArea(this.getNode(), contentX, contentY, contentWidth, contentHeight, -1, HPos.CENTER, VPos.CENTER);

}

adding event handling :

for demo purpose we add an onclick event to our control which print a simple message on the console :
first of all we define an ordinary property : onActionPropriety. of the type EventHandler<ActionEvent>.

private final ObjectProperty<EventHandler<ActionEvent>> onAction = new ObjectPropertyBase<EventHandler<ActionEvent>>() {

@Override

public Object getBean() {

return LcdClock.this;

}

@Override

public String getName() {

return "onAction";

}

@Override

protected void invalidated() {

setEventHandler(ActionEvent.ACTION, get());

}

};

public EventHandler<ActionEvent> getOnAction() {

return onActionProperty().get();

}

public void setOnAction(EventHandler<ActionEvent> value) {

onAction.set(value);

}

public ObjectProperty<EventHandler<ActionEvent>> onActionProperty() {

return onAction;

}
after that we add the following code to the constructor of the skin Class :
getSkinnable().setOnMousePressed((e) -> {

getSkinnable().fireEvent(new ActionEvent());

});

skining the control :

Making a property styleable, then, consist of:
  1. defining the javafx.beans.property as a StyleableProperty
  2. creating a corresponding CssMetaData
  3. ensuring the CssMetaData is returned in the List<CssMetaData>
Pseudo-class state support consists of notifying CSS of a pseudo-class state change via the invalidated() method of a property.
in our case we are make only one property styleable. let's say it's the backgroundColor property. to achieve this result the property must extend one of the StyleableProperty classe. here the StyleableObjectProperty :

private ObjectProperty<Color>   backgroundColor = new StyleableObjectProperty<Color>(Color.BLACK) {

@Override

public Object getBean() {

return LcdClock.this;

}

@Override

public String getName() {

return "backgroundColor";

}

@Override

public CssMetaData getCssMetaData() {

return StyleableProperties.LCD_CLOCK_METADATA;

}

@Override

public void invalidated() {

updateBackgroundColor();

}

};
In java doc we find the following definition of CssMetaData :

"A CssMetaData instance provides information about the CSS style and provides the hooks that allow CSS to set a property value. It encapsulates the CSS property name, the type into which the CSS value is converted, and the default value of the property.
CssMetaData is the bridge between a value that can be represented syntactically in a .css file, and a StyleableProperty. There is a one-to-one correspondence between a CssMetaData and a StyleableProperty. Typically, the CssMetaData of a will include the CssMetaData of its ancestors. During CSS processing, the CSS engine iterates over the Node's CssMetaData, looks up the parsed value of each, converts the parsed value, and sets the value on the StyleableProperty.
The method Node.getCssMetaData() is called to obtain the List<CssMetaData>. This method is called frequently and it is prudent to return a static list rather than creating the list on each call. By convention, node classes that have CssMetaData will implement a static method getClassCssMetaData() and it is customary to have getCssMetaData() simply return getClassCssMetaData(). The purpose of getClassCssMetaData() is to allow sub-classes to easily include the CssMetaData of some ancestor. "

private static final CssMetaData<LcdClock, Color> LCD_CLOCK_METADATA = new CssMetaData<LcdClock, Color>("-fx-lcd-bk", StyleConverter.getColorConverter(), Color.BLACK) {

@Override

public boolean isSettable(LcdClock styleable) {

return styleable.backgroundColor == null || !styleable.backgroundColor.isBound();

}

@Override

public StyleableProperty<Color> getStyleableProperty(LcdClock styleable) {

return (StyleableProperty<Color>) (WritableValue<Color>) styleable.backgroundColor;

}

};

finnally getClassCssMetaData() and getCssMetaData() have to be created :

static {

List<CssMetaData<? extends Styleable, ?>> temp

= new ArrayList<>(Control.getClassCssMetaData());

Collections.addAll(temp, LCD_CLOCK_METADATA);

cssMetaDataList = Collections.unmodifiableList(temp);

}

private static final List<CssMetaData<? extends Styleable, ?>> cssMetaDataList;

@Override

protected List<CssMetaData<? extends Styleable, ?>> getControlCssMetaData() {

return getClassCssMetaData();

}

public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() {

return StyleableProperties.cssMetaDataList;

} 

source code

you can find the source code for netbeans at https://github.com/mooninvader/lcdClock

further reading


Friday, September 18, 2015

tetris game with javafx

TETRIS GAME WITH JAVAFX



a simple tetris game written in javafx under netbeans.

you can find the source code of the project at the following link :






Saturday, August 15, 2015

parsing an arithmetic expression using the shunting-yard algorithm and drawing with javafx


this time I am demonstrating the use of the shunting-yard algorithm for parsing an arithmetic expression. the parser is written in groovy. you can use the following functions :


  • cos
  • sin 
  • tan
  • log
  • log10
  • sqrt
  • abs
  • pow
  • max
  • min 


and the following  operators :

  • +
  • -
  • *
  • /
  • ^ (power not xor).

the parser is from me but for the graphical part, i found an intersting post on stackoverflow :

http://stackoverflow.com/questions/24005247/draw-cartesian-plane-graphi-with-canvas-in-javafx

so i use the awsome piece of code given by jewelsea : http://stackoverflow.com/users/1155209/jewelsea

the code is very concise and easy to ready you extend or fix it with no pain. perhaps it is a foundation for a new open source project what do you think?

any way here is some snapshots :







i also user the library exp4j http://www.objecthunter.net/exp4j/ to test my code.

as usual you can find the code source at github : https://github.com/mooninvader/FunctionPlotter



Monday, July 13, 2015

using ireport in javafx applications



one of reporting solutions in java is to use ireports from JasperSoft. here we choose to generate a xhtml report and send it to a web view component. 
you must now that ireport wont start under java8 you must have jdk 7 or under installed .
go to directory of ireport installation and edit the file ireport.conf which is in the  etc folder. uncomment the line jdkhome and make it point to the older jdk.


first we need of course to create a report. this one is simple it's a result of the simple query "select * from emp"  with the schema scott in oracle database.  make a connection and use the wizard for this simple report : 






next we take the resulting scott.jrxml into our new netbeans project :

 to setup a ireport project we must include the following jars :
  • commons-logging.
  • commons-digesters
  • commons-collections.
  • commons-beanutils.
  • groovy-all
  • jasperreports-5.6.0
  •  jasperreports-fonts-5.6.0
  •  jasperreports-htmlcomponent-5.0.

Our goal is to generate a xhtml report and injecting into the Webview component.

to generate the report we use ReportPrinter class :
 



package ireportfx;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExporter;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.export.JRXhtmlExporter;
        
/**
 *
 * @author hakim
 */
public class ReportPrinter {

    Connection conn = null;

    public ReportPrinter(Connection conn) {
        this.conn = conn;
    }


    private String jasperReport(String name, 
            ResultSet data, Map params) {

        JasperPrint jasperPrint = null;
        try {
            JasperReport jr=JasperCompileManager.compileReport(ReportPrinter.class.getResourceAsStream(name));
            InputStream stream = ReportPrinter.class.getResourceAsStream(name);
            jasperPrint = JasperFillManager.fillReport(
                    jr, params, conn);
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception ex) {
            java.util.logging.Logger.getLogger(ReportPrinter.class.getName()).log(Level.SEVERE, null, ex);
        }

        JRExporter exporter = null;
        StringWriter out = new StringWriter();
        PrintWriter printWriter = new PrintWriter(out);

        try {
            exporter = new JRXhtmlExporter();
            exporter.setParameter(JRExporterParameter.JASPER_PRINT,
                    jasperPrint);
            exporter.setParameter(JRExporterParameter.OUTPUT_WRITER,
                    printWriter);

        } catch (RuntimeException e) {
            throw e;
        }
        try {
            exporter.exportReport();
        } catch (JRException ex) {
            Logger.getLogger(ReportPrinter.class.getName()).log(Level.SEVERE, null, ex);
        }

        try {
            if (conn != null) {
                conn.close();
            }
        } catch (SQLException ex) {
            java.util.logging.Logger.getLogger(ReportPrinter.class.getName()).log(Level.SEVERE, null, ex);
        }

        return out.toString();
    }

    public String generateReport(String ReportName, Map params) {
        return jasperReport(ReportName, null, params);
    }
    
}


and this is the simple controller that fill the report :
 
package ireportfx;

import java.net.URL;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.web.WebView;

/**
 *
 * @author hakim
 */
public class FXMLDocumentController implements Initializable {

    @FXML
    WebView webView;

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        webView.getEngine().loadContent(generateReport());
    }


    Connection getConnection()  {
        String url = "jdbc:oracle:thin:@localhost:1521:orcl";
        Connection con=null;
        try {
            con = DriverManager.getConnection(url,"scott","tiger");
        } catch (Exception except) {
            except.printStackTrace();

        }
        return con;
    }

    private String generateReport() {
          ReportPrinter rp=new ReportPrinter(getConnection())  ;
          String sp=rp.generateReport("scott.jrxml",  null);
          System.out.println(sp);
          return sp;
    }

}

the result is in the screenshot below :


as usual you can find the full source code at git hub :

https://github.com/mooninvader/ireportfx/tree/master/src/ireportfx