Skip to content

Tag: tutorial

JavaFX SDK 1.0 on Linux

JavaFX 1.0 is out and is absolutely amazing. You guys did really a great work on it.

As I really need a working SDK on Linux to continue to study and I don’t have any Windows/Mac near me, I’m using the Weiqi Gao’s workaround. I tried to simplify a little bit more the process for those who need JavaFX SDK working on Linux right now.

Download javafxsdk_linux_unofficial.tar.bz2 (~18Mb).

And then

tar -xjvf javafxsdk_linux_unofficial.tar.bz2
sudo cp javafx /opt/javafx
echo “PATH=\$PATH:/opt/javafx/bin” >> ~/.profile
echo “JAVAFX_HOME=/opt/javafx” >> ~/.profile
source ~/.profile

Now you can call javafx, javafxc, javafxdoc and javafxpackager from your terminal. Don’t forget that you need Java 1.6 or greater installed.

Here’s a video showing the SDK working, I’m compiling and running two sample applications. Remeber that as a temporary unofficial port for Linux, there’s not native video support nor hardware acceleration.

JavaFX, rectangular collision detection

In a game I wrote some years ago we handled simple rectangular collisions. Given the points:

We did:

// returning 0 means collision
int collision(int ax, int ay, int bx, int by, int cx, int cy, int dx, int dy){
	return ((ax > dx)||(bx < cx)||(ay > dy)||(by < cy));
}

I’ll show here a little demo about how implement simple rectangular collisions on JavaFX.
First I created a movable rectangle using the same idea of draggable nodes I already had posted before.

import javafx.input.MouseEvent;
import javafx.scene.geometry.Rectangle;
 
public class MovableRectangle extends Rectangle {
    private attribute startX = 0.0;
    private attribute startY = 0.0;
 
    public attribute onMove = function(e:MouseEvent):Void {}
 
    override attribute onMousePressed = function(e:MouseEvent):Void {
        startX = e.getDragX()-translateX;
        startY = e.getDragY()-translateY;
        onMove(e);
    }
 
    override attribute onMouseDragged = function(e:MouseEvent):Void {
        translateX = e.getDragX()-startX;
        translateY = e.getDragY()-startY;
        onMove(e);
    }
}

In the main code I some important things:

  • colide, a color that represents the collision effect. White means no collision and gray means collision.
  • rec1 and rec2, the two rectangles that can collide.
  • checkcollision() the function that checks and handles a possible collision.

Here is the main code:

import javafx.application.Frame;
import javafx.application.Stage;
import javafx.scene.geometry.Rectangle;
import javafx.scene.paint.Color;
import javafx.input.MouseEvent;
 
var colide = Color.WHITE;
 
function checkcollision():Void {
    if (
        (rec1.getBoundsX() > rec2.getBoundsX() + rec2.getWidth()) or
        (rec1.getBoundsX() + rec1.getWidth() < rec2.getBoundsX()) or 
        (rec1.getBoundsY() > rec2.getBoundsY() + rec2.getHeight()) or 
        (rec1.getBoundsY() + rec1.getHeight() < rec2.getBoundsY())
    ) {
        colide = Color.WHITE
    } else {
        colide = Color.LIGHTGRAY
    }
}
 
var rec1: MovableRectangle = MovableRectangle {
    x: 10, y: 10, width: 50, height: 60, fill: Color.RED
    onMove: function(e:MouseEvent):Void {
        checkcollision()
    }
}
 
var rec2: MovableRectangle = MovableRectangle {
    x: 100, y: 100, width: 70, height: 30, fill: Color.BLUE
    onMove: function(MouseEvent):Void {
        checkcollision()
    }
}
Frame {
    title: "Rectangular Collisions", width: 300, height: 300
    closeAction: function() { 
        java.lang.System.exit( 0 ); 
    }
    visible: true
 
    stage: Stage {
        fill: bind colide
        content: [rec1, rec2]
    }
}

Try it via Java Web Start:

Java Web Start

Some considerations:

  • You can use rectangular collisions to create bounding boxes to handle collisions in more complex shapes or sprites. Is a common approach in 2d games to avoid more expensive calculations.
  • There are space for optimizations.
  • In this case I’m using only two objects. Some problems raises when I have N objects to handle.

More generally, we can code:

function collission(ax, ay, bx, by, cx, cy, dx, dy): Boolean {
    return not ((ax > dx)or(bx < cx)or(ay > dy)or(by < cy));
}
 
function hitnode(a: Node, b:Node): Boolean{
    return (collission(
        a.getBoundsX(), a.getBoundsY(),
        a.getBoundsX() + a.getWidth(), a.getBoundsY() + a.getHeight(),
        b.getX(), b.getY(),
        b.getX() + b.getWidth(), b.getY() + b.getHeight()
    ));
}

This way we can pass just two bounding boxes to hitnode and easily check collision of a node against a list of bounding boxes nodes.
Using the same approach I also wrote this function to test if a Node is inside another Node:

function inside (ax, ay, bx, by, cx, cy, dx, dy):Boolean{
    return ((ax > cx) and (bx < dx) and (ay > cy) and (by < dy));
}
 
function insidenode(a:Node,b:Node):Boolean{
    return (inside(
        a.getBoundsX(), a.getBoundsY(),
        a.getBoundsX() + a.getWidth(), a.getBoundsY() + a.getHeight(),
        b.getBoundsX(), b.getBoundsY(),
        b.getBoundsX() + b.getWidth(), b.getBoundsY() + b.getHeight()
    ));
}

Soon I’ll post game examples showing how to use this method and others collission detection methods.

Downloads:

Short urls with Glassfish+MySQL


Pipes, Creative Commons photo by flattop341.

1. The Problem

Internet is full of long urls and meaningless.

Long urls are difficult to remember or print, usually full of redundancy and low semantic. With short and meaningful urls you can avoid thes problems and even achieve profitable goals with SEO
SEO (search engine optimization) technics.

There are services like Tiny URL, Fancy URL, Moo URL and others. Although they solve part of the problems, they bring several others. Another problem is if you have a web site like example.com and use a third-party service for short urls you are losing part of your mind-share with your users and clients.

As an example, if a example.com company wants to promote a open work position would be preferable spread a example.com/jobs instead of a tinyurl.com/examplejobs, or even worst, a tinyurl.com/3i4i592 (meaningless hash).

2. Solution Approach

I created a little program called xort that can be placed on your own server and provide you own short maintening your base url.

I use a pipe abstraction. Each pipe redirects from a key url to an output url.

The idea is that you have xort installed and associated into your domain (preferably on /x). A pipe inside example.com would be like example.com/x/jobs.

3. Tools

All those tools are multi platform, open source and free.

3.1 Glassfish Application Server

Glassfish is an open source application server project led by Sun Microsystems for the Java Enterprise Edition (Java EE) platform. It’s very easy to install and run and have a very nice administration web interface where you can do from simple tasks like deploy a application to more complexes like clustering.


Glassfish Admin Console

To develop the application I’m using NetBeans 6.5 Beta that comes with Glassfish V3 prelude b15b. Netbeans also provides a integration of project, database and web server.

Nevertheless, Glassfish has no dependencies with any IDE and perfectly works by alone. If you need I wrote this post explaining how to install and deploy a application on Glassfish from scratch.

3.2 MySQL Relational Database

MySQL is a relational database management system and probably the most used database on internet (has more than 11 million installations). It’s also very easy to install and administer, through command line or many gui interfaces.

To install MySQL and JDBC driver on Ubuntu just run as root:

# apt-get install mysql-server libmysql-java

After installing and configuring it you can test the jdbc driver throught this servlet code. You can optionally register the MySQL on NetBeans to have a easier access to it thought the service tab.

At the command line you can invoke mysql command line interface and use MySql commands or SQL queries. I’ll login and create a database called xort:

$ mysql -u username -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 13
Server version: 5.0.51a-3ubuntu5.3 (Ubuntu)

Type ‘help;’ or ‘\h’ for help. Type ‘\c’ to clear the buffer.

mysql> create database xort;
Query OK, 1 row affected (0.06 sec)

You could also create this database by an SQL statement:

CREATE DATABASE xort;

To select the database xort:

mysql> use xort;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql>

Now we create a database called pipes with fields pin (pipe in) and pout (pipe out). They represent the input url and the output url of our pipe abstraction.

CREATE TABLE pipes (
   pin VARCHAR(255) NOT NULL,
   pout VARCHAR(255)
);

As we expect a lot of searches queries on this table, we can optionally create a index for it on pin field. This can reduce ours searches from O(n) to O(logn) (because pin’s will be ordered so don’t need to look all pipes, we can use logn algorithms like binary search).

CREATE INDEX pinindex ON pipes (pin);

Another trick to improve our speed is recycling connections through connection pools.

Creating a pool of MySQL connections on Glassfish is very easy. There’re two good tutorials on this subject:

And now we populate the database with some initial pipes.

INSERT INTO pipes VALUES ('blog','http://silveiraneto.net');
INSERT INTO pipes VALUES ('cejug','http://cejug.org/display/cejug/Home');
INSERT INTO pipes VALUES ('orkut','http://www.orkut.com.br/Main#Profile.aspx?rl=ls&amp;uid=12443310329436634134');
INSERT INTO pipes VALUES ('glassfish','http://glassfish.dev.java.net');
INSERT INTO pipes VALUES ('mysql','http://dev.mysql.org');
INSERT INTO pipes VALUES ('twitter','http://twitter.com/silveira');
INSERT INTO pipes VALUES ('lab', 'http://maps.google.com/maps?f=q&amp;geocode=&amp;q=campus+do+pici&amp;g=Fortaleza,+Brazil&amp;ie=UTF8&amp;t=h&amp;ll=-3.745978,-38.574023&amp;spn=0.002452,0.004823&amp;z=18');
INSERT INTO pipes VALUES ('videos', 'http://br.youtube.com/user/NetoSilveira');
INSERT INTO pipes VALUES ('photos', 'http://flickr.com/photos/silveiraneto/');

4. Program

Basically we have just a program that implement this simple behavior:

  1. separate the key from the url.
  2. if the key is a pin from a pipe then redirect to that pout.
  3. else provide a way to create a new pipe.
  4. list all pipes.
  5. provide a way to remove a pipe.

To get the key we need to separate the proper part of the request uri:

String uri = request.getRequestURI();
String key = uri.substring(request.getContextPath().length()+1);

After that we check if it matches with a pin of some pipe. In this case we redirect user for the correspondent pout:

response.sendRedirect(pout);

Notice that using this approach we can connect a url to a extern or intern url (even to another pipe).

5. Download

Check out the xort project and sources at xort.dev.java.net:

Or grab sources and the current build with:

svn checkout https://xort.dev.java.net/svn/xort/trunk xort

Parameters can be passed by the the web.xml file:

   Set if users can add new pipes using the web interface.
allowNewPipes
true
 
   JDBC driver to use
driver
com.mysql.jdbc.Driver
 
   Username to login on the database.
username
root
 
   Password for the given username.
password
yourpassword
 
   JDBC path to database.
database
jdbc:mysql://localhost:3306/xort

Xort up and running:

Compiling Inkscape

Inkscape running

Inkscape is a Open Source vector graphics editor that works with SVG (Scalable Vector Graphics) format, Inkscape works with transparency, gradients, node editing, pattern fills, PNG export, and more. It also runs on Linux, Windows and OSX, those three are officially supported, but also runs in a broad list of Operational Systems. Is a software that I work daily and frequently is featured here in my blog.

You can download Inkscape or directly install it via some package system like Apt:

sudo apt-get install inskcape

But sometimes we need some special feature that is not available yet in the repositories or we want gain speed by having special binaries for our platforms or we want to help developing a new feature. In those cases we need to compile the software by ourself.

Those tips are valid for Ubuntu 8.04 but some part of them can be applied in others distributions. The Inkscape compiled here is the version 0.46+devel so newest versions can have compiling procedures slightly different.

Getting sources via APT.The easiest way to compile Inkscape on Ubuntu is

sudo su
apt-get build-dep inkscape
apt-get source inkscape
cd inkscape
./autogen.sh
./configure
make
make install

This will get a version of inkscape, compile it and install. If the first step doesn’t work well, you can try install all necessary packages by yourself using:

sudo apt-get install autotools-dev fakeroot dh-make build-essential autoconf automake intltool libglib2.0-dev libpng12-dev libgc-dev libfreetype6-dev liblcms1-dev libgtkmm-2.4-dev libxslt1-dev libboost-dev libpopt-dev libgsl0ldbl libgsl0-dev libgsl0-dbg libgnome-vfsmm-2.6-dev libssl-dev libmagick++9-dev libwpg-dev

Getting sources via SVN. The recipe I showed above will compile a stable version of Inkscape but not the last version of Inkscape. For that we need to grab the source directly from the Subversion repositories and so compile it.

At your home folder:

sudo apt-get install subversion
svn checkout https://inkscape.svn.sourceforge.net/svnroot/inkscape/inkscape/trunk inkscape

A alternative way to subversion is getting sources from here. Those are tarballs built every hour after someone change something in the development repositories. Download a tarball, and decompress it on your home folder.

Install all tools we need to compile Inkscape, this should fits:

sudo apt-get install autotools-dev fakeroot dh-make build-essential autoconf automake intltool libglib2.0-dev libpng12-dev libgc-dev libfreetype6-dev liblcms1-dev libgtkmm-2.4-dev libxslt1-dev libboost-dev libpopt-dev libgsl0ldbl libgsl0-dev libgsl0-dbg libgnome-vfsmm-2.6-dev libssl-dev libmagick++9-dev libwpg-dev

Enter in the directory with the Inkscape source and do:

./autogen.sh
mkdir build
cd build
../configure
make
sudo make install

In both cases, grabbing sources via svn or via apt, or can set the place where the software will be installed so it not cause conflicts with you already installed version of Inkscape. You can do that replacing the ./configure step with something like:

./configure –prefix=/home/yourname/inkscape

If you had some trouble in one of those steps, consider reading some of those other tutorials:

ps: thanks guys from the inkscape-devel@lists.sourceforge.net specially heathenx.

JavaFX, creating a sphere with shadow

This is a short tutorial about some JavaFX elements like ellipses, circles, effects and gradients.

In the first code we are creating a frame with a ellipse with center in (120,140), 60 pixels of horizontal radius, 20 pixels of vertical radius and color black. We have also a circle with center in (100,100), 50 pixels of radius and color red. The idea is make this circle appears like a sphere and make the ellipse look like a shadow.

import javafx.application.*;
import javafx.scene.paint.*;
import javafx.scene.geometry.*;
 
Frame {
    title: "JavaFX Sphere", width: 300, height: 300, visible: true
    stage: Stage {
        content: [
            Ellipse {
                 centerX: 120, centerY: 140, radiusX: 60, radiusY: 20
                 fill: Color.BLACK
            },
            Circle { centerX: 100, centerY: 100, radius: 50, fill: Color.RED }
        ]
    }
}

Now we will just add two thing, a effect and a radial gradient.

First we’ll just add javafx.scene.effect.* to our import list and just call the gaussian blur effect in our ellipse with

effect: GaussianBlur{ radius: 20 }

This creates a gaussian blur of radius 20. The first ellipse was like

and now with the effect becomes

Now we create a radial gradient for the circle appears like a sphere. We do that using the RadialGradient class at

RadialGradient {
   centerX: 75, centerY: 75, radius: 50, proportional: false
   stops: [
      Stop {offset: 0.0 color: Color.WHITE},
      Stop {offset: 0.3 color: Color.RED},
      Stop {offset: 1.0 color: Color.DARKRED},
   ]
}

First lets look at the gradient. It starts with a white color, going to red during the first 30% of the way. The remaining of the way is the color red going to a dark red. It creates a gradient like this one:

But it is a radial gradient, with center in (75,75) and radius 50. So this radial gradient looks like this:

As we place this radial gradient in our circle, it was like this:

And now is like this:

Now the complete code. I guess it’s simple and also concise.

import javafx.application.*;
import javafx.scene.paint.*;
import javafx.scene.effect.*;
import javafx.scene.geometry.*;
 
Frame {
    title: "JavaFX Sphere", width: 300, height: 300, visible: true
    stage: Stage {
        content: [
            Ellipse {
                centerX: 120, centerY: 140, radiusX: 60, radiusY: 20
                fill: Color.BLACK
                effect: GaussianBlur{ radius: 20 }
            },
            Circle {
                centerX: 100, centerY: 100, radius: 50
                fill: RadialGradient {
                    centerX: 75, centerY: 75, radius: 50, proportional: false
                    stops: [
                        Stop {offset: 0.0 color: Color.WHITE},
                        Stop {offset: 0.3 color: Color.RED},
                        Stop {offset: 1.0 color: Color.DARKRED},
                    ]
                }
            }
        ]
    }
}

Here is the final screenshot:

Script to Installing JavaFX Compiler

Right in this moment you can choose between three options to develop JavaFX:

I did this little script to download the last version of JavaFX continuos build and install it for you.

#!/bin/sh
envfile=$HOME/.bash_profile
 
#download and unpatch the last build of JavaFx
mkdir jfx
cd jfx
wget http://openjfx.java.sun.com/hudson/job/openjfx-compiler/lastBuild/artifact/openjfx-compiler/dist//*zip*/dist.zip
unzip dist.zip
rm dist.zip
 
#set files at bin folder as executable
chmod +x dist/bin/*
 
#add those executables to the path
echo "PATH=\$PATH:`pwd`/dist/bin" >> $envfile

Save this script as install_jfx.sh and execute it. Probably you want to execute it at you home directory. If you want to install JavaFX to root change envfile for /root/.bash_profile, if you want to install to all users change for /etc/profile. I tested this script successfully on my Ubuntu 8.04.

After that open a new terminal and try to see if javafx, javafxc and javafxdoc are available. You can test your enviroment with this simple program.

import javafx.ui.*;
import java.lang.*;
 
Frame {
  visible: true
  content: FlowPanel {
  content: Button {
      var n = 0
      text: bind Integer.toString(n)
      action: function() {
        n++;
      }
    }
  }
}

Save it as Counter.fx, compile with javafxc Counter.fx and so execute it with javafx Counter.fx.

To know more, take a look into the preliminary JavaFX API or in the article Using JavaFX GUI Toolkit.