Showing posts with label Java Gnome. Show all posts
Showing posts with label Java Gnome. Show all posts

Step By Step Java Gnome tutorial

Java Gnome tutorial

This is Java Gnome tutorial. In this tutorial we will learn the basics of GUI programming in Java Gnome. Java Gnome tutorial is suitable for beginner programmers.

Table of contents

Java Gnome

Java Gnome is a wrapper over the GTK+ and Gnome for the Java programming language.
Continue Reading

Nibbles Clone in Java Gnome

Nibbles in Java Gnome

In this part of the Java Gnome programming tutorial, we will create a Nibbles game clone.

Nibbles

Nibbles is an older classic video game. It was first created in late 70s. Later it was brought to PCs. In this game the player controls a snake. The objective is to eat as many apples as possible. Each time the snake eats an apple, its body grows. The snake must avoid the walls and its own body.

Development

The size of each of the joints of a snake is 10px. The snake is controlled with the cursor keys. Initially, the snake has three joints. The game starts immediately. When the game is finished, we display "Game Over" message in the statusbar widget.
board.java
package com.zetcode;

import java.io.FileNotFoundException;

import java.util.Timer;
import java.util.TimerTask;

import org.freedesktop.cairo.Context;

import org.gnome.gdk.Color;
import org.gnome.gdk.EventExpose;
import org.gnome.gdk.EventKey;
import org.gnome.gdk.Keyval;
import org.gnome.gdk.ModifierType;
import org.gnome.gdk.Pixbuf;
import org.gnome.gtk.DrawingArea;
import org.gnome.gtk.Justification;
import org.gnome.gtk.Label;
import org.gnome.gtk.StateType;
import org.gnome.gtk.Widget;


public class Board extends DrawingArea implements Widget.ExposeEvent {

private final int WIDTH = 300;
private final int HEIGHT = 300;
private final int DOT_SIZE = 10;
private final int ALL_DOTS = 900;
private final int RAND_POS = 29;
private final int DELAY = 140;
private final int PERIOD = 80;

private int x[] = new int[ALL_DOTS];
private int y[] = new int[ALL_DOTS];

private int dots;
private int apple_x;
private int apple_y;

private boolean left = false;
private boolean right = true;
private boolean up = false;
private boolean down = false;
private boolean inGame = true;

private Timer timer;

private Pixbuf dot;
private Pixbuf apple;
private Pixbuf head;

private Label statusbar;

public Board(Label statusbar) {

this.statusbar = statusbar;

connect(new SnakeKeyListener());

modifyBackground(StateType.NORMAL, Color.BLACK);

try {
dot = new Pixbuf("dot.png");
apple = new Pixbuf("apple.png");
head = new Pixbuf("head.png");

} catch (FileNotFoundException e) {
e.printStackTrace();
}

connect(this);
setCanFocus(true);

initGame();
}


public Timer getTimer() { return timer; }


public void initGame() {

dots = 3;

for (int z = 0; z < dots; z++) {
x[z] = 50 - z * 10;
y[z] = 50;
}

locateApple();

timer = new Timer();
timer.scheduleAtFixedRate(new ScheduleTask(), DELAY, PERIOD);

}


public void drawObjects(Context cr) {


if (inGame) {

cr.setSource(apple, apple_x, apple_y);
cr.paint();

for (int z = 0; z < dots; z++) {
if (z == 0) {
cr.setSource(head, x[z], y[z]);
cr.paint();
} else {
cr.setSource(dot, x[z], y[z]);
cr.paint();
}
}

} else {
gameOver();
}
}


public void gameOver() {

timer.cancel();

statusbar.setJustify(Justification.LEFT);
statusbar.setAlignment(0f, 0.5f);
statusbar.setLabel("Game Over");
}


public void checkApple() {

if ((x[0] == apple_x) && (y[0] == apple_y)) {
dots++;
locateApple();
}
}

public void move() {

for (int z = dots; z > 0; z--) {
x[z] = x[(z - 1)];
y[z] = y[(z - 1)];
}

if (left) {
x[0] -= DOT_SIZE;
}

if (right) {
x[0] += DOT_SIZE;
}

if (up) {
y[0] -= DOT_SIZE;
}

if (down) {
y[0] += DOT_SIZE;
}
}

public void checkCollision() {

for (int z = dots; z > 0; z--) {

if ((z > 4) && (x[0] == x[z]) && (y[0] == y[z])) {
inGame = false;
}
}

if (y[0] > HEIGHT) {
inGame = false;
}

if (y[0] < 0) {
inGame = false;
}

if (x[0] > WIDTH) {
inGame = false;
}

if (x[0] < 0) {
inGame = false;
}
}

public void locateApple() {
int r = (int) (Math.random() * RAND_POS);
apple_x = ((r * DOT_SIZE));
r = (int) (Math.random() * RAND_POS);
apple_y = ((r * DOT_SIZE));
}

public boolean onExposeEvent(Widget widget, EventExpose eventExpose) {

Context cr = new Context(widget.getWindow());
drawObjects(cr);

return false;
}


class ScheduleTask extends TimerTask {

public void run() {

if (inGame) {
checkApple();
checkCollision();
move();
}
queueDraw();
}
}

class SnakeKeyListener implements Widget.KeyPressEvent {

public boolean onKeyPressEvent(Widget widget, EventKey eventKey) {

final Keyval key;
final ModifierType mod;

key = eventKey.getKeyval();
mod = eventKey.getState();

if ((key == key.Left) && (!right)) {
left = true;
up = false;
down = false;
}

if ((key == key.Right) && (!left)) {
right = true;
up = false;
down = false;
}

if ((key == key.Up) && (!down)) {
up = true;
right = false;
left = false;
}

if ((key == key.Down) && (!up)) {
down = true;
right = false;
left = false;
}

return false;
}
}
}
First we will define some globals used in our game.
The WIDTH and HEIGHT constants determine the size of the Board. The DOT_SIZE is the size of the apple and the dot of the snake. The ALL_DOTS constant defines the maximum number of possible dots on the Board. The RAND_POS constant is used to calculate a random position of an apple. The DELAY constant determines the speed of the game.
 private int x[] = new int[ALL_DOTS];
private int y[] = new int[ALL_DOTS];
These two arrays store x, y coordinates of all possible joints of a snake.
The initGame() method initializes variables, loads images and starts a timeout function.
In the move() method we have the key algorithm of the game. To understand it, look at how the snake is moving. You control the head of the snake. You can change its direction with the cursor keys. The rest of the joints move one position up the chain. The second joint moves where the first was, the third joint where the second was etc.
 for (int z = dots; z > 0; z--) {
x[z] = x[(z - 1)];
y[z] = y[(z - 1)];
}
This code moves the joints up the chain.
 if (left) {
x[0] -= DOT_SIZE;
}
Move the head to the left.
In the checkCollision() method, we determine if the snake has hit itself or one of the walls.
 for (int z = dots; z > 0; z--) {
if ((z > 4) && (x[0] == x[z]) && (y[0] == y[z])) {
inGame = false;
}
}
Finish the game, if the snake hits one of its joints with the head.
 if (y[0] > HEIGHT) {
inGame = false;
}
Finish the game, if the snake hits the bottom of the Board.
The locateApple() method locates an apple randomly on the form.
 int r = (int) (Math.random() * RAND_POS);
We get a random number from 0 to RAND_POS - 1.
 apple_x = ((r * DOT_SIZE));
...
apple_y = ((r * DOT_SIZE));
These line set the x, y coordinates of the apple object.
In the onKeyPressEvent() method of the Board class, we deternime which keys the player hit.
 if ((key == key.Left) && (!right)) {
left = true;
up = false;
down = false;
}
If we hit the left cursor key, we set left variable to true. This variable is used in the move()method to change coordinates of the snake object. Notice also, that when the snake is heading to the right, we cannot turn immediately to the left.
nibbles.java
package com.zetcode;

import java.util.Timer;

import org.gnome.gdk.Event;
import org.gnome.gtk.Gtk;
import org.gnome.gtk.Label;
import org.gnome.gtk.VBox;
import org.gnome.gtk.Widget;
import org.gnome.gtk.Window;
import org.gnome.gtk.WindowPosition;


/**
* ZetCode Java Gnome tutorial
*
* This program creates a Nibbles game clone.
*
* @author jan bodnar
* website zetcode.com
* last modified March 2009
*/

public class GNibbles extends Window {

Board board;
Label statusbar;

public GNibbles() {

setTitle("Nibbles");

initUI();

setDefaultSize(320, 320);
setPosition(WindowPosition.CENTER);

showAll();
}

public void initUI() {

VBox vbox = new VBox(false, 0);

statusbar = new Label("");
board = new Board(statusbar);

vbox.packStart(board);
vbox.packStart(statusbar, false, false, 0);

add(vbox);

connect(new Window.DeleteEvent() {
public boolean onDeleteEvent(Widget source, Event event) {
Timer timer = board.getTimer();
timer.cancel();
Gtk.mainQuit();
return false;
}
});
}

public static void main(String[] args) {
Gtk.init(args);
new GNibbles();
Gtk.main();
}
}
In this class, we set up the Nibbles game. Notice that we get the timer object from the board. This is to perform a clean exit.

Nibbles
Figure: Nibbles

This was the Nibbles computer game programmed using the Java Gnome programming library.
Continue Reading

Continue Drawing with Cairo library

Continue Drawing with Cairo library

In this part of the Java Gnome programming tutorial, we will continue drawing with the Cairo library.

Donut

In the following example we create a complex shape by rotating a bunch of ellipses.
donut.java
package com.zetcode;

import org.freedesktop.cairo.Context;
import org.freedesktop.cairo.Matrix;

import org.gnome.gdk.Event;
import org.gnome.gdk.EventExpose;
import org.gnome.gtk.DrawingArea;
import org.gnome.gtk.Gtk;
import org.gnome.gtk.Widget;
import org.gnome.gtk.Window;
import org.gnome.gtk.WindowPosition;


/**
* ZetCode Java Gnome tutorial
*
* This program draws a Donut
* shape on the drawing area.
*
* @author jan bodnar
* website zetcode.com
* last modified March 2009
*/

public class GDonut extends Window
implements Widget.ExposeEvent {


public GDonut() {

setTitle("Donut");

initUI();

connect(new Window.DeleteEvent() {
public boolean onDeleteEvent(Widget source, Event event) {
Gtk.mainQuit();
return false;
}
});

setDefaultSize(300, 260);
setPosition(WindowPosition.CENTER);
showAll();
}


public void initUI() {
DrawingArea darea = new DrawingArea();
darea.connect(this);
add(darea);
}

public boolean onExposeEvent(Widget widget, EventExpose eventExpose) {
final Context cr;

cr = new Context(widget.getWindow());
drawDonut(cr);

return false;
}

public void drawDonut(Context cr) {
int width = this.getWindow().getWidth();
int height = this.getWindow().getHeight();

cr.setLineWidth(0.5);
cr.translate(width/2, height/2);
cr.arc( 0, 0, 120, 0, 2 * Math.PI);
cr.stroke();
cr.save();

for ( int i = 0; i < 36; i++) {
Matrix mat = new Matrix();
mat.rotate(i*Math.PI/36);
mat.scale(0.3, 1);
cr.transform(mat);
cr.arc(0, 0, 120, 0, 2 * Math.PI);
cr.restore();
cr.stroke();
cr.save();
}
}


public static void main(String[] args) {
Gtk.init(args);
new GDonut();
Gtk.main();
}
}
In this example, we create a donut. The shape resembles a cookie, hence the name donut.
 cr.translate(width/2, height/2);
cr.arc( 0, 0, 120, 0, 2 * Math.PI);
cr.stroke();
In the beginning there is an ellipse.
 Matrix mat = new Matrix();
mat.rotate(i*Math.PI/36);
mat.scale(0.3, 1);
cr.transform(mat);
cr.arc(0, 0, 120, 0, 2 * Math.PI);
cr.restore();
cr.stroke();
cr.save();
After several rotations, there is a donut.

Donut
Figure: Donut

Gradients

In computer graphics, gradient is a smooth blending of shades from light to dark or from one color to another. In 2D drawing programs and paint programs, gradients are used to create colorful backgrounds and special effects as well as to simulate lights and shadows. (answers.com)
gradients.java
package com.zetcode;

import org.freedesktop.cairo.Context;

import org.freedesktop.cairo.LinearPattern;

import org.gnome.gdk.Color;
import org.gnome.gdk.EventExpose;
import org.gnome.gtk.DrawingArea;
import org.gnome.gtk.Gtk;
import org.gnome.gtk.Widget;
import org.gnome.gtk.Window;
import org.gnome.gtk.WindowPosition;

/**
* ZetCode Java Gnome tutorial
*
* This program draws gradients.
*
* @author jan bodnar
* website zetcode.com
* last modified March 2009
*/


public class GGradients extends Window implements Widget.ExposeEvent {

public GGradients() {

setTitle("Gradients");

initUI();

connect(new Window.DeleteEvent() {
public boolean onDeleteEvent(Widget source, Event event) {
Gtk.mainQuit();
return false;
}
});

setDefaultSize(340, 390);
setPosition(WindowPosition.CENTER);
showAll();
}

public void initUI() {
DrawingArea darea = new DrawingArea();
darea.connect(this);
add(darea);
}

public boolean onExposeEvent(Widget widget, EventExpose eventExpose) {
final Context cr;

cr = new Context(widget.getWindow());
drawGradients(cr);

return false;
}

public void drawGradients(Context cr) {

LinearPattern lg1 = new LinearPattern(0.0, 0.0, 350.0, 350.0);

int count = 1;

for (double j=0.1; j<1.0; j+= 0.1) {
if (count % 2 != 0) {
lg1.addColorStopRGB(j, 0, 0, 0);
} else {
lg1.addColorStopRGB(j, 1, 0, 0);
}
count++;
}

cr.rectangle(20, 20, 300, 100);
cr.setSource(lg1);
cr.fill();

LinearPattern lg2 = new LinearPattern(0.0, 0.0, 350.0, 0);

count = 1;

for (double i=0.05; i<0.95; i+= 0.025) {
if (count % 2 != 0) {
lg2.addColorStopRGB(i, 0, 0, 0);
} else {
lg2.addColorStopRGB(i, 0, 0, 1);
}
count++;
}

cr.rectangle(20, 140, 300, 100);
cr.setSource(lg2);
cr.fill();

LinearPattern lg3 = new LinearPattern(20.0, 260.0, 20.0, 360.0);

lg3.addColorStopRGB(0.1, 0, 0, 0 );
lg3.addColorStopRGB(0.5, 1, 1, 0);
lg3.addColorStopRGB(0.9, 0, 0, 0 );

cr.rectangle(20, 260, 300, 100);
cr.setSource(lg3);
cr.fill();
}

public static void main(String[] args) {
Gtk.init(args);
new GGradients();
Gtk.main();
}
}
In our example, we draw three rectangles with three different gradients.
 LinearPattern lg1 = new LinearPattern(0.0, 0.0, 350.0, 350.0);
Here we create a linear gradient pattern. The parameters specify the line, along which we draw the gradient. In our case it is a diagonal line.
 LinearPattern lg3 = new LinearPattern(20.0, 260.0,  20.0, 360.0);        
lg3.addColorStopRGB(0.1, 0, 0, 0 );
lg3.addColorStopRGB(0.5, 1, 1, 0);
lg3.addColorStopRGB(0.9, 0, 0, 0 );
We define color stops to produce our gradient pattern. In this case, the gradient is a blending of black and yellow colors. By adding two black and one yellow stops, we create a horizontal gradient pattern. What do these stops actually mean? In our case, we begin with black color, which will stop at 1/10 of the size. Then we begin to gradually paint in yellow, which will culminate at the centre of the shape. The yellow color stops at 9/10 of the size, where we begin painting in black again, until the end.

Gradients
Figure: Gradients

Star

In the following example, we create a moving star. The star moves, rotates and grows/shrinks.
star.java
package com.zetcode;

import java.util.Timer;
import java.util.TimerTask;

import org.freedesktop.cairo.Context;
import org.freedesktop.cairo.Matrix;

import org.gnome.gdk.Event;
import org.gnome.gdk.EventExpose;
import org.gnome.gtk.DrawingArea;
import org.gnome.gtk.Gtk;
import org.gnome.gtk.Widget;
import org.gnome.gtk.Window;
import org.gnome.gtk.WindowPosition;

/**
* ZetCode Java Gnome tutorial
*
* This program shows an animated star. Rotate,
* translate and scale operations are
* applied on the star.
*
* @author jan bodnar
* website zetcode.com
* last modified March 2009
*/

public class GStar extends Window
implements Widget.ExposeEvent {

private static Timer timer;
private int count;

private double angle = 0;
private double scale = 1;
private double delta = 0.01;

double points[][] = {
{ 0, 85 }, { 75, 75 }, { 100, 10 }, { 125, 75 },
{ 200, 85 }, { 150, 125 }, { 160, 190 }, { 100, 150 },
{ 40, 190 }, { 50, 125 }, { 0, 85 }
};

public GStar() {

setTitle("Star");

timer = new Timer();
timer.scheduleAtFixedRate(new ScheduleTask(), 100, 20);
count = 0;

initUI();

connect(new Window.DeleteEvent() {
public boolean onDeleteEvent(Widget source, Event event) {
timer.cancel();
Gtk.mainQuit();
return false;
}
});

setSizeRequest(350, 250);
setPosition(WindowPosition.CENTER);
showAll();
}

public void initUI() {
DrawingArea darea = new DrawingArea();
darea.connect(this);
add(darea);
}

public void drawStar(Context cr) {

int width = this.getWindow().getWidth();
int height = this.getWindow().getHeight();

cr.setSource(0, 0.44, 0.7);
cr.setLineWidth(1);

Matrix mat = new Matrix();

mat.translate(width/2, height/2);
mat.rotate(angle);
mat.scale(scale, scale);
cr.transform(mat);

for ( int i = 0; i < 10; i++ ) {
cr.lineTo(points[i][0], points[i][1]);
}

cr.fill();
cr.stroke();

if ( scale < 0.01 ) {
delta = -delta;
} else if (scale > 0.99) {
delta = -delta;
}

scale += delta;
angle += 0.01;
}

public boolean onExposeEvent(Widget widget, EventExpose eventExpose) {

Context cr = new Context(widget.getWindow());
drawStar(cr);

return false;
}

class ScheduleTask extends TimerTask {

public void run() {
count++;
queueDraw();
}
}

public static void main(String[] args) {
Gtk.init(args);
new GStar();
Gtk.main();
}
}
We apply translate, scale and rotate operations on a star shape.
 public boolean onDeleteEvent(Widget source, Event event) {
timer.cancel();
Gtk.mainQuit();
return false;
}
For a clean exit, we must not forget to stop the timer. Timer is and object of the java util library and is not stopped by the Gtk.mainQuit() method.
 double points[][] = { 
{ 0, 85 }, { 75, 75 }, { 100, 10 }, { 125, 75 },
{ 200, 85 }, { 150, 125 }, { 160, 190 }, { 100, 150 },
{ 40, 190 }, { 50, 125 }, { 0, 85 }
};
These points are used to build the star shape.
 Matrix mat = new Matrix();

mat.translate(width/2, height/2);
mat.rotate(angle);
mat.scale(scale, scale);
cr.transform(mat);
Here we apply the translate, rotate and scale operations on the star shape.
 for ( int i = 0; i < 10; i++ ) {
cr.lineTo(points[i][0], points[i][1]);
}
Here we draw the star.

Waiting

In this examle, we use transparency effect to create a waiting demo. We will draw 8 lines that will gradually fade out creating an illusion, that a line is moving. Such effects are often used to inform users, that a lengthy task is going on behind the scenes. An example is streaming video over the internet.
waiting.java
package com.zetcode;


import java.util.Timer;
import java.util.TimerTask;

import org.freedesktop.cairo.Context;

import org.gnome.gdk.Event;
import org.gnome.gdk.EventExpose;
import org.gnome.gtk.DrawingArea;
import org.gnome.gtk.Gtk;
import org.gnome.gtk.Widget;
import org.gnome.gtk.Window;
import org.gnome.gtk.WindowPosition;

/**
* ZetCode Java Gnome tutorial
*
* This program creates a waiting
* effect.
*
* @author jan bodnar
* website zetcode.com
* last modified March 2009
*/

public class GWaiting extends Window
implements Widget.ExposeEvent {

private static Timer timer;
private int count;

private final double[][] trs = {
{ 0.0, 0.15, 0.30, 0.5, 0.65, 0.80, 0.9, 1.0 },
{ 1.0, 0.0, 0.15, 0.30, 0.5, 0.65, 0.8, 0.9 },
{ 0.9, 1.0, 0.0, 0.15, 0.3, 0.5, 0.65, 0.8 },
{ 0.8, 0.9, 1.0, 0.0, 0.15, 0.3, 0.5, 0.65 },
{ 0.65, 0.8, 0.9, 1.0, 0.0, 0.15, 0.3, 0.5 },
{ 0.5, 0.65, 0.8, 0.9, 1.0, 0.0, 0.15, 0.3 },
{ 0.3, 0.5, 0.65, 0.8, 0.9, 1.0, 0.0, 0.15 },
{ 0.15, 0.3, 0.5, 0.65, 0.8, 0.9, 1.0, 0.0, }
};



public GWaiting() {
setPosition(WindowPosition.CENTER);

timer = new Timer();
timer.scheduleAtFixedRate(new ScheduleTask(), 100, 80);
count = 0;

initUI();

connect(new Window.DeleteEvent() {
public boolean onDeleteEvent(Widget source, Event event) {
timer.cancel();
Gtk.mainQuit();
return false;
}
});

resize(250, 150);
setTitle("Waiting");
showAll();
}

public void initUI() {
DrawingArea darea = new DrawingArea();
add(darea);
darea.connect(this);
}

public boolean onExposeEvent(Widget widget, EventExpose eventExpose) {

Context cr = new Context(widget.getWindow());
drawWaiting(cr);

return false;
}

private void drawWaiting(Context cr) {
int w = this.getWidth();
int h = this.getHeight();

cr.translate(w/2, h/2);

for (int i = 0; i < 8; i++) {

cr.setLineWidth(3);
cr.setSource(0, 0, 0, trs[count%8][i]);

cr.moveTo(0, -10);
cr.lineTo(0, -40);
cr.rotate(Math.PI/4f);
cr.stroke();
}
}

class ScheduleTask extends TimerTask {

public void run() {
count++;
queueDraw();
}
}

public static void main(String[] args) {
Gtk.init(args);
new GWaiting();
Gtk.main();
}
}
We draw eight lines with eight different alpha values.
 private final double[][] trs = {
{ 0.0, 0.15, 0.30, 0.5, 0.65, 0.80, 0.9, 1.0 },
....
};
This is a two dimensional array of transparency values used in this demo. There are 8 rows, each for one state. Each of the 8 lines will continuosly use these values.
 cr.setLineWidth(3);
We make the lines a bit thicker, so that they are better visible.
 cr.setSource(0, 0, 0, trs[count%8][i]);
Here we define the transparency value for a line.
 cr.moveTo(0, -10);
cr.lineTo(0, -40);
cr.rotate(Math.PI/4f);
cr.stroke();
These code lines will draw each of the eight lines.

Waiting
Figure: Waiting


In this chapter of the Java Gnome programming library, we did some more advanced drawing with the Cairo library.
Continue Reading

Drawing with the Cairo library

Drawing with Cairo

In this part of the Java programming tutorial, we will do some drawing with the Cairo library.
Cairo is a library for creating 2D vector graphics. We can use it to draw our own widgets, charts or various effects or animations.

Simple drawing

The stroke operation draws the outlines of shapes and the fill operation fills the insides of shapes. Next we will demonstrate these two operations.
simpledrawing.java
package com.zetcode;

import org.freedesktop.cairo.Context;

import org.gnome.gdk.Event;
import org.gnome.gdk.EventExpose;
import org.gnome.gtk.Allocation;
import org.gnome.gtk.DrawingArea;
import org.gnome.gtk.Gtk;
import org.gnome.gtk.Widget;
import org.gnome.gtk.Window;
import org.gnome.gtk.WindowPosition;

/**
* Java Gnome tutorial
*
* This program draws a simple
* drawing with the Cairo library.
*
* @author jan bodnar
* website zetcode.com
* last modified March 2009
*/

public class GSimpleDrawing extends Window implements Widget.ExposeEvent {

public GSimpleDrawing() {

setTitle("Simple drawing");

initUI();

connect(new Window.DeleteEvent() {
public boolean onDeleteEvent(Widget source, Event event) {
Gtk.mainQuit();
return false;
}
});

setDefaultSize(250, 200);
setPosition(WindowPosition.CENTER);
showAll();
}

public void initUI() {
DrawingArea darea = new DrawingArea();
darea.connect(this);
add(darea);
}

public boolean onExposeEvent(Widget widget, EventExpose eventExpose) {
final Context cr;

cr = new Context(widget.getWindow());
drawShape(cr);

return false;
}

public void drawShape(Context cr) {

cr.setLineWidth(9);
cr.setSource(0.7, 0.2, 0.0);

int width, height;
width = getAllocation().getWidth();
height = getAllocation().getHeight();

cr.translate(width/2, height/2);
cr.arc(0, 0, (width < height ? width : height) / 2 - 10, 0, 2*Math.PI);
cr.strokePreserve();

cr.setSource(0.3, 0.4, 0.6);
cr.fill();
}

public static void main(String[] args) {
Gtk.init(args);
new GSimpleDrawing();
Gtk.main();
}
}
In our example, we will draw a circle and fill it with a solid color.
 DrawingArea darea = new DrawingArea();
We will be doing our drawing operations on the DrawingArea widget.
  public boolean onExposeEvent(Widget widget, EventExpose eventExpose) {
final Context cr;

cr = new Context(widget.getWindow());
drawShape(cr);

return false;
}
When the window needs to be redrawn, the ExposeEvent is created. The actual drawing is delegated to the drawShape() method.
 cr = new Context(widget.getWindow());
We create the Context object from the gdk window of the drawing area. The context is an object onto which we do all our drawings.
 cr.setLineWidth(9);
We set the width of the line to 9 pixels.
 cr.setSource(0.7, 0.2, 0.0);
We set the color to dark red.
 int width, height;
width = getAllocation().getWidth();
height = getAllocation().getHeight();

cr.translate(width/2, height/2);
We get the width and height of the drawing area. We move the origin into the middle of the window.
 cr.arc(0, 0, (width < height ? width : height) / 2 - 10, 0, 2*Math.PI);
cr.strokePreserve();
We draw the outside shape of a circle. The strokePreserve() strokes the current path according to the current line width, line join, line cap, and dash settings. Unlike the stroke(), it preserves the path within the cairo context.
 cr.setSource(0.3, 0.4, 0.6);
cr.fill();
This fills the interior of the circle with some blue color.

Simple drawing
Figure: Simple drawing

Basic shapes

The next example draws some basic shapes onto the window.
basicshapes.java
package com.zetcode;

import org.freedesktop.cairo.Context;
import org.freedesktop.cairo.Matrix;

import org.gnome.gdk.Event;
import org.gnome.gdk.EventExpose;
import org.gnome.gtk.DrawingArea;
import org.gnome.gtk.Gtk;
import org.gnome.gtk.Widget;
import org.gnome.gtk.Window;
import org.gnome.gtk.WindowPosition;


/**
* ZetCode Java Gnome tutorial
*
* This program draws basic shapes
* with the cairo library.
*
* @author jan bodnar
* website zetcode.com
* last modified March 2009
*/

public class GBasicShapes extends Window implements Window.ExposeEvent {

public GBasicShapes() {

setTitle("Basic Shapes");

initUI();

connect(new Window.DeleteEvent() {
public boolean onDeleteEvent(Widget source, Event event) {
Gtk.mainQuit();
return false;
}
});

setDefaultSize(390, 240);
setPosition(WindowPosition.CENTER);
showAll();
}

public void initUI() {
DrawingArea darea = new DrawingArea();
darea.connect(this);
add(darea);
}

public boolean onExposeEvent(Widget widget, EventExpose eventExpose) {
final Context cr;

cr = new Context(widget.getWindow());
drawShapes(cr);

return false;
}

public void drawShapes(Context cr) {

cr.setSource(0.6, 0.6, 0.6);

cr.rectangle(20, 20, 120, 80);
cr.rectangle(180, 20, 80, 80);
cr.fill();

cr.arc(330, 60, 40, 0, 2*Math.PI);
cr.fill();

cr.arc(90, 160, 40, Math.PI/4, Math.PI);
cr.fill();

Matrix mat = new Matrix();
mat.translate(220, 180);
mat.scale(1, 0.7);
cr.transform(mat);

cr.arc(0, 0, 50, 0, 2*Math.PI);
cr.fill();
}

public static void main(String[] args) {
Gtk.init(args);
new GBasicShapes();
Gtk.main();
}
}
In this example, we will create a rectangle, a square, a circle, an arc and an ellipse.
 cr.rectangle(20, 20, 120, 80);
cr.rectangle(180, 20, 80, 80);
cr.fill();
These lines draw a rectangle and a square.
 cr.arc(330, 60, 40, 0, 2*Math.PI);
cr.fill();
Here the arc() method draws a full circle.
 Matrix mat = new Matrix();
mat.translate(220, 180);
mat.scale(1, 0.7);
cr.transform(mat);

cr.arc(0, 0, 50, 0, 2*Math.PI);
cr.fill();
If we want to draw an oval, we do some scaling first. The scale() method shrinks the y axis.

Basic shapes
Figure: Basic shapes

Colors

A color is an object representing a combination of Red, Green, and Blue (RGB) intensity values. Cairo valid RGB values are in the range 0 to 1.
colors.java
package com.zetcode;

import org.freedesktop.cairo.Context;

import org.gnome.gdk.Event;
import org.gnome.gdk.EventExpose;
import org.gnome.gtk.DrawingArea;
import org.gnome.gtk.Gtk;
import org.gnome.gtk.Widget;
import org.gnome.gtk.Window;
import org.gnome.gtk.WindowPosition;

/**
* ZetCode Java Gnome tutorial
*
* This program draws nine rectangles
* on the drawing area. Each of them
* has different color.
*
* @author jan bodnar
* website zetcode.com
* last modified March 2009
*/

public class GColors extends Window
implements Widget.ExposeEvent {

public GColors() {

setTitle("Colors");

connect(new Window.DeleteEvent() {
public boolean onDeleteEvent(Widget source, Event event) {
Gtk.mainQuit();
return false;
}
});

initUI();

setDefaultSize(350, 280);
setPosition(WindowPosition.CENTER);
showAll();
}

public void initUI() {
DrawingArea darea = new DrawingArea();
darea.connect(this);
add(darea);
}

public boolean onExposeEvent(Widget widget, EventExpose eventExpose) {
final Context cr;

cr = new Context(widget.getWindow());
drawRectangles(cr);

return false;
}


public void drawRectangles(Context cr) {
cr.setSource(0.5, 0.65, 0.45);
cr.rectangle(10, 15, 90, 60);
cr.fill();

cr.setSource(0.16, 0.7, 0.9);
cr.rectangle(130, 15, 90, 60);
cr.fill();

cr.setSource(0.274, 0.262, 0.48);
cr.rectangle(250, 15, 90, 60);
cr.fill();

cr.setSource(0.5, 0.39, 0.33);
cr.rectangle(10, 105, 90, 60);
cr.fill();

cr.setSource(0.99, 0.83, 0.24);
cr.rectangle(130, 105, 90, 60);
cr.fill();

cr.setSource(0.95, 0.38, 0.27);
cr.rectangle(250, 105, 90, 60);
cr.fill();

cr.setSource(0.85, 0.57, 0.21);
cr.rectangle(10, 195, 90, 60);
cr.fill();

cr.setSource(0.25, 0.04, 0.73);
cr.rectangle(130, 195, 90, 60);
cr.fill();

cr.setSource(0.12, 0.08, 0.03);
cr.rectangle(250, 195, 90, 60);
cr.fill();
}

public static void main(String[] args) {
Gtk.init(args);
new GColors();
Gtk.main();
}
}
We draw nine rectangles in nine different colors.
 cr.setSource(0.5, 0.65, 0.45);
The setSource() method sets a color for the cairo context. The three parameters of the method are the color intensity values.
 cr.rectangle(10, 15, 90, 60);
cr.fill();
We create a rectangle shape and fill it with the previously specified color.

Colors
Figure: Colors

Transparent rectangles

Transparency is the quality of being able to see through a material. The easiest way to understand transparency is to imagine a piece of glass or water. Technically, the rays of light can go through the glass and this way we can see objects behind the glass.
In computer graphics, we can achieve transparency effects using alpha compositing. Alpha compositing is the process of combining an image with a background to create the appearance of partial transparency. The composition process uses an alpha channel. (wikipedia.org, answers.com)
transparentrectangles.java
package com.zetcode;

import org.freedesktop.cairo.Context;

import org.gnome.gdk.Event;
import org.gnome.gdk.EventExpose;
import org.gnome.gtk.DrawingArea;
import org.gnome.gtk.Gtk;
import org.gnome.gtk.Widget;
import org.gnome.gtk.Window;
import org.gnome.gtk.WindowPosition;

/**
* ZetCode Java Gnome tutorial
*
* This program draws ten rectangles
* with different levels of transparency.
*
* @author jan bodnar
* website zetcode.com
* last modified March 2009
*/

public class GTransparentRectangles extends Window
implements Widget.ExposeEvent {

public GTransparentRectangles() {
setTitle("Transparent Rectangles");

connect(new Window.DeleteEvent() {
public boolean onDeleteEvent(Widget source, Event event) {
Gtk.mainQuit();
return false;
}
});

initUI();

setSizeRequest(590, 90);
setPosition(WindowPosition.CENTER);
showAll();
}


public void initUI() {
DrawingArea darea = new DrawingArea();
add(darea);
darea.connect(this);
}


public void doDrawing(Context cr) {

for (int i = 1; i<=10; i++) {
cr.setSource(0, 0, 1, 0.1*i);
cr.rectangle(50*i, 20, 40, 40);
cr.fill();
}
}

public boolean onExposeEvent(Widget widget, EventExpose eventExpose) {

Context cr = new Context(widget.getWindow());
doDrawing(cr);

return false;
}

public static void main(String[] args) {
Gtk.init(args);
new GTransparentRectangles();
Gtk.main();
}
}
In the example we will draw ten rectangles with different levels of transparency.
 cr.setSource(0, 0, 1, 0.1*i);
The last parameter of the setSource() method is the alpha transparency.

Transparent rectangles
Figure: Transparent rectangles


In this chapter of the Java Gnome programming library, we were drawing with Cairo library.
Continue Reading

Pango library in Java Gnome

Pango

In this part of the Java Gnome programming tutorial, we will explore the Pango library.
Pango is a free and open source computing library for rendering internationalized texts in high quality. Different font backends can be used, allowing cross-platform support. (wikipedia)
Pango provides advanced font and text handling that is used for Gdk and Gtk.

Quotes

In our first example, we show, how to change font for the Label widget.
quotes.java
package com.zetcode;

import org.gnome.gdk.Event;
import org.gnome.gtk.Fixed;
import org.gnome.gtk.Gtk;
import org.gnome.gtk.Label;
import org.gnome.gtk.Widget;
import org.gnome.gtk.Window;
import org.gnome.gtk.WindowPosition;
import org.gnome.pango.FontDescription;

/**
* ZetCode Java Gnome tutorial
*
* This program uses the pango library to
* display text.
*
* @author jan bodnar
* website zetcode.com
* last modified March 2009
*/

public class GQuotes extends Window {

public GQuotes() {

setTitle("Quotes");

initUI();

connect(new Window.DeleteEvent() {
public boolean onDeleteEvent(Widget source, Event event) {
Gtk.mainQuit();
return false;
}
});

setPosition(WindowPosition.CENTER);
showAll();
}


public void initUI() {
String text = "Excess of joy is harder to bear than any amount\n" +
"of sorrow. The more one judges, the less one loves.\n" +
"There is no such thing as a great talent without great will power.";

Label label = new Label(text);

FontDescription fontdesc = new FontDescription("Purisa 9");
label.modifyFont(fontdesc);

Fixed fix = new Fixed();

fix.put(label, 5, 5);
add(fix);
}


public static void main(String[] args) {
Gtk.init(args);
new GQuotes();
Gtk.main();
}
}
In the above code example, we have a label widget with three quotations. We change it's font to Purisa 9.
 String text = "Excess of joy is harder to bear than any amount\n" +
"of sorrow. The more one judges, the less one loves.\n" +
"There is no such thing as a great talent without great will power.";
This is the text to show in the label.
 FontDescription fontdesc = new FontDescription("Purisa 9");
The FontDescription is used to specify the characteristics of a font to load.
 label.modifyFont(fontdesc);
We change the font of the label widget to Purisa 9.

Quotations
Figure: Quotations

Pango markup

In the following example, we will use Pango markup language to modify font in the ExposeEvent event.
markup.java
package com.zetcode;

import org.freedesktop.cairo.Context;

import org.gnome.gdk.Event;
import org.gnome.gdk.EventExpose;
import org.gnome.gtk.DrawingArea;
import org.gnome.gtk.Gtk;
import org.gnome.gtk.Widget;
import org.gnome.gtk.Window;
import org.gnome.pango.FontDescription;
import org.gnome.pango.Layout;


/**
* ZetCode Java Gnome tutorial
*
* This program uses Pango markup language
* to modify the text.
*
* @author jan bodnar
* website zetcode.com
* last modified March 2009
*/

public class GPangoMarkup extends Window implements Widget.ExposeEvent {

String quote = "<span foreground='blue' size='19000'>The only " +
"victory over love is flight</span>";


public GPangoMarkup() {

setTitle("Pango Markup");

initUI();

connect(new Window.DeleteEvent() {
public boolean onDeleteEvent(Widget source, Event event) {
Gtk.mainQuit();
return false;
}
});

move(150, 150);
showAll();
}


public void initUI() {

DrawingArea darea = new DrawingArea();
darea.connect(this);
darea.queueDraw();
add(darea);
setBorderWidth(5);

}

public boolean onExposeEvent(Widget widget, EventExpose eventExpose) {

final Context cr;
final Layout layout;
final FontDescription desc;

cr = new Context(widget.getWindow());
layout = new Layout(cr);

desc = new FontDescription("Sans 12");
layout.setFontDescription(desc);
layout.setMarkup(quote);

widget.setSizeRequest(layout.getPixelWidth(), layout.getPixelHeight());
cr.showLayout(layout);

return false;
}

public static void main(String[] args) {
Gtk.init(args);
new GPangoMarkup();
Gtk.main();
}
}
Drawing is done with Cairo library. We get a Layout by passing the Cairo drawing Context.
 cr = new Context(widget.getWindow());
This code line creates a Context object.
 layout = new Layout(cr);
A Layout represents a paragraph of text, together with its attributes.
 layout.setMarkup(quote);
This line sets the markup for the layout.
 widget.setSizeRequest(layout.getPixelWidth(), layout.getPixelHeight());
This is to show all the text in the window.
 cr.showLayout(layout);
Finally, the text is drawn.

Pango markup
Figure: Pango markup

Unicode

Pango is used to work with internationalized text.
unicode.java
package com.zetcode;

import org.gnome.gdk.Event;
import org.gnome.gtk.Fixed;
import org.gnome.gtk.Gtk;
import org.gnome.gtk.Label;
import org.gnome.gtk.Widget;
import org.gnome.gtk.Window;
import org.gnome.gtk.WindowPosition;
import org.gnome.pango.FontDescription;

/**
* ZetCode Java Gnome tutorial
*
* This program shows text in
* azbuka.
*
* @author jan bodnar
* website zetcode.com
* last modified March 2009
*/

public class GUnicode extends Window {

public GUnicode() {

setTitle("Unicode");

initUI();

connect(new Window.DeleteEvent() {
public boolean onDeleteEvent(Widget source, Event event) {
Gtk.mainQuit();
return false;
}
});

setPosition(WindowPosition.CENTER);
showAll();
}

public void initUI() {

String text =
"Фёдор Михайлович Достоевский родился 30 октября (11 ноября)\n" +
"1821 года в Москве.Был вторым из 7 детей. Отец, Михаил Андреевич,\n" +
"работал в госпитале для бедных. Мать, Мария Фёдоровна\n" +
"(в девичестве Нечаева), происходила из купеческого рода.";

Label label = new Label(text);

FontDescription fontdesc = new FontDescription("Purisa 9");
label.modifyFont(fontdesc);

Fixed fix = new Fixed();

fix.put(label, 5, 5);
add(fix);

setBorderWidth(5);
}


public static void main(String[] args) {
Gtk.init(args);
new GUnicode();
Gtk.main();
}
}
We show some text in azbuka.
 String text = 
"Фёдор Михайлович Достоевский родился 30 октября (11 ноября)\n" ...
We can directly use unicode text. However, text is never put inside the source code. In real worl applications, we put text in external files. In Java these are often property files.
 Label label = new Label(text);
We normally use it in the label widget.

Unicode
Figure: Unicode


In this chapter of the Java Gnome programming tutorial, we worked with the Pango library.
Continue Reading

Dialogs in Java Gnome

Dialogs in Java Gnome

In this part of the Java Gnome programming tutorial, we will introduce dialogs.
Dialog windows or dialogs are an indispensable part of most modern GUI applications. A dialog is defined as a conversation between two or more persons. In a computer application a dialog is a window which is used to "talk" to the application. A dialog is used to input data, modify data, change the application settings etc. Dialogs are important means of communication between a user and a computer program.

Message dialogs

Message dialogs are convenient dialogs that provide messages to the user of the application. The message consists of textual and image data.
messages.java
package com.zetcode;

import org.gnome.gdk.Event;
import org.gnome.gtk.Button;
import org.gnome.gtk.ButtonsType;
import org.gnome.gtk.Gtk;
import org.gnome.gtk.MessageDialog;
import org.gnome.gtk.MessageType;
import org.gnome.gtk.Table;
import org.gnome.gtk.Widget;
import org.gnome.gtk.Window;
import org.gnome.gtk.WindowPosition;


/**
* Java Gnome tutorial
*
* This program shows four
* message dialogs.
*
* @author jan bodnar
* website zetcode.com
* last modified March 2009
*/


public class GMessages extends Window {

Window parent;

public GMessages() {

setTitle("GMessages");

initUI();

parent = this;

connect(new Window.DeleteEvent() {
public boolean onDeleteEvent(Widget source, Event event) {
Gtk.mainQuit();
return false;
}
});

setDefaultSize(250, 100);
setPosition(WindowPosition.CENTER);
showAll();
}


public void initUI() {

Table table = new Table(2, 2, true);

Button info = new Button("Information");
Button warn = new Button("Warning");
Button ques = new Button("Question");
Button erro = new Button("Error");

info.connect(new Button.Clicked() {

public void onClicked(Button button) {
MessageDialog md = new MessageDialog(null, true,
MessageType.INFO,
ButtonsType.CLOSE, "Download completed");
md.setPosition(WindowPosition.CENTER);
md.run();
md.hide();
}
});

warn.connect(new Button.Clicked() {

public void onClicked(Button button) {
MessageDialog md = new MessageDialog(parent, true,
MessageType.WARNING,
ButtonsType.CLOSE, "Unallowed operation");
md.setPosition(WindowPosition.CENTER);
md.run();
md.hide();
}
});


ques.connect(new Button.Clicked() {

public void onClicked(Button button) {
MessageDialog md = new MessageDialog(null, true,
MessageType.QUESTION,
ButtonsType.CLOSE, "Are you sure to quit?");
md.setPosition(WindowPosition.CENTER);
md.run();
md.hide();
}
});

erro.connect(new Button.Clicked() {
public void onClicked(Button button) {
MessageDialog md = new MessageDialog (null, true,
MessageType.ERROR,
ButtonsType.CLOSE, "Error loading file");
md.setPosition(WindowPosition.CENTER);
md.run();
md.hide();
}
});

table.attach(info, 0, 1, 0, 1);
table.attach(warn, 1, 2, 0, 1);
table.attach(ques, 0, 1, 1, 2);
table.attach(erro, 1, 2, 1, 2);

add(table);
}


public static void main(String[] args) {
Gtk.init(args);
new GMessages();
Gtk.main();
}
}
In our example, we will show four kinds of message dialogs. Information, Warning, Question and Error message dialogs.
 Button info = new Button("Information");
Button warn = new Button("Warning");
Button ques = new Button("Question");
Button erro = new Button("Error");
We have four buttons. Each of these buttons will show a different kind of message dialog.
 info.connect(new Button.Clicked() {

public void onClicked(Button button) {
MessageDialog md = new MessageDialog(null, true,
MessageType.INFO,
ButtonsType.CLOSE, "Download completed");
md.setPosition(WindowPosition.CENTER);
md.run();
md.hide();
}
});
If we click on the info button, the Information dialog is displayed. The MessageType.INFO specifies the type of the dialog. The ButtonsType.CLOSE specifies the button to be displayed in the dialog. The last parameter is the message dislayed. The dialog is displayed with the run() method. The hide() method hides the dialog.

Information message dialog   Warning message dialog   Question message dialog   Error message dialog

AboutDialog

The AboutDialog displays information about the application. AboutDialog can display a logo, the name of the application, version, copyright or licence information. It is also possible to give credits to the authors or translators.
aboutdialog.java
package com.zetcode;

import java.io.FileNotFoundException;

import org.gnome.gdk.Event;
import org.gnome.gdk.Pixbuf;
import org.gnome.gtk.AboutDialog;
import org.gnome.gtk.Button;
import org.gnome.gtk.Fixed;
import org.gnome.gtk.Gtk;
import org.gnome.gtk.Widget;
import org.gnome.gtk.Window;
import org.gnome.gtk.WindowPosition;


public class GAboutDialog extends Window implements Button.Clicked {

Pixbuf logo;

public GAboutDialog() {

setTitle("AboutDialog");

initUI();

connect(new Window.DeleteEvent() {
public boolean onDeleteEvent(Widget source, Event event) {
Gtk.mainQuit();
return false;
}
});

setDefaultSize(250, 200);
setPosition(WindowPosition.CENTER);
showAll();
}


public void initUI() {

try {
logo = new Pixbuf("battery.png");
} catch (FileNotFoundException e) {
e.printStackTrace();
}

Button button = new Button("About");
button.connect(this);

Fixed fix = new Fixed();
fix.put(button, 20, 20);
add(fix);

}

public void onClicked(Button button) {
AboutDialog about = new AboutDialog();
about.setProgramName("Battery");
about.setVersion("0.1");
about.setCopyright("(c) Jan Bodnar");
about.setComments("Battery is a simple tool for battery checking");
about.setLogo(logo);
about.setPosition(WindowPosition.CENTER);
about.run();
about.hide();
}

public static void main(String[] args) {
Gtk.init(args);
new GAboutDialog();
Gtk.main();
}
}
The code example uses a AboutDialog with some of it's features.
 AboutDialog about = new AboutDialog();
We create an AboutDialog.
 about.setProgramName("Battery");
about.setVersion("0.1");
about.setCopyright("(c) Jan Bodnar");
We set the name, version and the copyright.
 about.setLogo(logo);
This line creates a logo.

AboutDialog
Figure: AboutDialog


In this part of the Java Gnome tutorial, we have covered Dialogs.
Continue Reading

Advanced widgets in Java Gnome

Advanced widgets in Java Gnome

In this part of the Java Gnome programming tutorial, we will introduce some more advanced widgets.

TextView

TexView widget is used for displaying and editing multiline text. TexView widget has also the MVC design. The TextView represents the view component and TexBuffer represents the model component. The TexBuffer is used to manipulate the text data. TextTag is an attribute that can be applied to the text. The TextIter represents a position between two characters in the text. All manipulation with the text is done using text iterators.
textview.java
package com.zetcode;

import org.gnome.gdk.Event;
import org.gnome.gtk.Gtk;

import org.gnome.gtk.TextBuffer;
import org.gnome.gtk.TextIter;
import org.gnome.gtk.TextTag;
import org.gnome.gtk.TextView;
import org.gnome.gtk.Widget;
import org.gnome.gtk.Window;
import org.gnome.gtk.WindowPosition;
import org.gnome.gtk.WrapMode;
import org.gnome.pango.FontDescription;
import org.gnome.pango.Style;

/**
* ZetCode Java Gnome tutorial
*
* This program demonstrates the
* TextView widget.
*
* @author jan bodnar
* website zetcode.com
* last modified March 2009
*/

public class GTextView extends Window {

public GTextView() {

setTitle("TextView");

initUI();

connect(new Window.DeleteEvent() {
public boolean onDeleteEvent(Widget source, Event event) {
Gtk.mainQuit();
return false;
}
});

setDefaultSize(250, 200);
setPosition(WindowPosition.CENTER);
showAll();
}


public void initUI() {

final TextView view;
final FontDescription desc;
final TextBuffer buffer;
final TextTag colorText, italics, background, mleft;
TextIter pointer;

view = new TextView();

desc = new FontDescription("Sans, 10");
view.modifyFont(desc);

buffer = new TextBuffer();

colorText = new TextTag();
colorText.setForeground("blue");

italics = new TextTag();
italics.setStyle(Style.ITALIC);

background = new TextTag();
background.setBackground("lightgray");

mleft = new TextTag();
mleft.setLeftMargin(8);

pointer = buffer.getIterStart();
buffer.insert(pointer, "Plain text \n");
buffer.insert(pointer, "Colored text\n", new TextTag[] {colorText, mleft});
buffer.insert(pointer, "Text with colored background\n", background);
buffer.insert(pointer, "Text in italics", italics);

view.setBuffer(buffer);
view.setPaddingAboveParagraph(5);
add(view);

}


public static void main(String[] args) {
Gtk.init(args);
new GTextView();
Gtk.main();
}
}
The example shows some text with different TextTags applied.
 view = new TextView();
TextView widget is created.
 desc = new FontDescription("Sans, 10");
view.modifyFont(desc);
We set the font for the TextView to be Sans 10.
 colorText = new TextTag();
colorText.setForeground("blue");
A TextTag widget is created. This tag will set the color of the text to blue, if applied.
 buffer.insert(pointer, "Text in italics", italics);
Here we apply an italics text tag for the specified text.

TextView
Figure: TextView

ListView

In the following example, we use the TreeView widget in a list view mode. The ListStore is used to store data.
listview.java
package com.zetcode;

import org.gnome.gdk.Event;
import org.gnome.gtk.CellRendererText;
import org.gnome.gtk.DataColumn;
import org.gnome.gtk.DataColumnString;
import org.gnome.gtk.Gtk;
import org.gnome.gtk.ListStore;
import org.gnome.gtk.Statusbar;
import org.gnome.gtk.TreeIter;
import org.gnome.gtk.TreePath;
import org.gnome.gtk.TreeView;
import org.gnome.gtk.TreeViewColumn;
import org.gnome.gtk.VBox;
import org.gnome.gtk.Widget;
import org.gnome.gtk.Window;
import org.gnome.gtk.WindowPosition;

/**
* ZetCode Java Gnome tutorial
*
* This program demonstrates the
* TreeView widget in listview mode.
*
* @author jan bodnar
* website zetcode.com
* last modified March 2009
*/

public class GListView extends Window {

private Actress[] actresses =
{
new Actress("Jessica Alba", "Pomona", 1981),
new Actress("Sigourney Weaver", "New York", 1949),
new Actress("Angelina Jolie", "Los Angeles", 1975),
new Actress("Natalie Portman", "Jerusalem", 1981),
new Actress("Rachel Weissz", "London", 1971),
new Actress("Scarlett Johansson", "New York", 1984)
};

private Statusbar statusbar;


public GListView() {

setTitle("ListView");

initUI();

connect(new Window.DeleteEvent() {
public boolean onDeleteEvent(Widget source, Event event) {
Gtk.mainQuit();
return false;
}
});

setDefaultSize(350, 300);
setPosition(WindowPosition.CENTER);
showAll();
}


public void initUI() {

final TreeView view;
final ListStore model;
TreeIter row;
CellRendererText renderer;
TreeViewColumn column;

final DataColumnString nameCol;
final DataColumnString placeCol;
final DataColumnString yearCol;


statusbar = new Statusbar();

model = new ListStore(new DataColumn[] {
nameCol = new DataColumnString(),
placeCol = new DataColumnString(),
yearCol = new DataColumnString(),
});


for (Actress act : actresses) {
row = model.appendRow();
model.setValue(row, nameCol, act.name);
model.setValue(row, placeCol, act.place);
model.setValue(row, yearCol, String.valueOf(act.year));
}

view = new TreeView(model);

column = view.appendColumn();
column.setTitle("Name");
renderer = new CellRendererText(column);
renderer.setText(nameCol);

column = view.appendColumn();
column.setTitle("Place");
renderer = new CellRendererText(column);
renderer.setText(placeCol);

column = view.appendColumn();
column.setTitle("Year");
renderer = new CellRendererText(column);
renderer.setText(yearCol);

view.connect(new TreeView.RowActivated() {

public void onRowActivated(TreeView treeView,
TreePath treePath,
TreeViewColumn treeViewColumn) {

final TreeIter row;
final String place;
final String name;
final String year;
final String text;

row = model.getIter(treePath);

place = model.getValue(row, placeCol);
name = model.getValue(row, nameCol);
year = model.getValue(row, yearCol);

text = name + ", " + place + ", " + year;

statusbar.setMessage(text);
}
});

VBox vbox = new VBox(false, 0);

vbox.packStart(view);
vbox.packStart(statusbar, false, false, 0);
add(vbox);

}

class Actress {

public String name;
public String place;
public int year;

Actress(String name, String place, int year) {
this.name = name;
this.place = place;
this.year = year;
}
}


public static void main(String[] args) {
Gtk.init(args);
new GListView();
Gtk.main();
}
}
In our example, we show a list of six actresses in the TreeViewwidget. Each of the rows shows the name, the place of born and the year of born for each of them.
    class Actress {
public String name;
public String place;
public int year;
...
}
The Actress class is used for storing data about an actress.
 model = new ListStore(new DataColumn[] {
nameCol = new DataColumnString(),
placeCol = new DataColumnString(),
yearCol = new DataColumnString(),
});
These lines declare the model to have three string data columns.
 for (Actress act : actresses) {
row = model.appendRow();
model.setValue(row, nameCol, act.name);
model.setValue(row, placeCol, act.place);
model.setValue(row, yearCol, String.valueOf(act.year));
}
The model is filled with data from the array of actresses.
 column = view.appendColumn();
column.setTitle("Name");
renderer = new CellRendererText(column);
renderer.setText(nameCol);
A new column is created with "Name" title. Each column has a cell renderer. The cell renderer is responsible for displaying data. In our case we have the most common cell renderer, the CellRendererText. As the name suggests, it shows textual data in a TreeViewColumn.
 row = model.getIter(treePath);

place = model.getValue(row, placeCol);
name = model.getValue(row, nameCol);
year = model.getValue(row, yearCol);

text = name + ", " + place + ", " + year;

statusbar.setMessage(text);
If we double click on an item, we display the whole row in the statusbar.

ListView
Figure: ListView

Tree

In the last example of this chapter, we use the TreeViewwidget to show a hierarchical tree of data.
tree.java
package com.zetcode;

import org.gnome.gdk.Event;
import org.gnome.gtk.CellRendererText;
import org.gnome.gtk.DataColumn;
import org.gnome.gtk.DataColumnString;
import org.gnome.gtk.Gtk;
import org.gnome.gtk.Statusbar;
import org.gnome.gtk.TreeIter;
import org.gnome.gtk.TreePath;
import org.gnome.gtk.TreeStore;
import org.gnome.gtk.TreeView;
import org.gnome.gtk.TreeViewColumn;
import org.gnome.gtk.VBox;
import org.gnome.gtk.Widget;
import org.gnome.gtk.Window;
import org.gnome.gtk.WindowPosition;

/**
* ZetCode Java Gnome tutorial
*
* This program demonstrates the
* TreeView widget in tree view mode.
*
* @author jan bodnar
* website zetcode.com
* last modified March 2009
*/

public class GTree extends Window {

private DataColumnString dataCol;

private TreeStore model;
private TreeIter row;
private TreeView view;
private TreeIter rowChild;

private TreeViewColumn column;
private CellRendererText renderer;

private Statusbar statusbar;

public GTree() {

setTitle("GTree");

initUI();

connect(new Window.DeleteEvent() {
public boolean onDeleteEvent(Widget source, Event event) {
Gtk.mainQuit();
return false;
}
});

setDefaultSize(350, 300);
setPosition(WindowPosition.CENTER);
showAll();
}

public void initUI() {

statusbar = new Statusbar();

model = new TreeStore(new DataColumn[] {
dataCol = new DataColumnString(),
});

row = model.appendRow();
model.setValue(row, dataCol, "Scripting languages");
rowChild = model.appendChild( row );
model.setValue(rowChild, dataCol, "PHP");
rowChild = model.appendChild( row );
model.setValue(rowChild, dataCol, "Python");
rowChild = model.appendChild( row );
model.setValue(rowChild, dataCol, "PERL");
rowChild = model.appendChild( row );
model.setValue(rowChild, dataCol, "Ruby");

row = model.appendRow();
model.setValue(row, dataCol, "Compiling languages");
rowChild = model.appendChild( row );
model.setValue( rowChild, dataCol, "Java");
rowChild = model.appendChild( row );
model.setValue( rowChild, dataCol, "C++");
rowChild = model.appendChild( row );
model.setValue( rowChild, dataCol, "C#");
rowChild = model.appendChild( row );
model.setValue( rowChild, dataCol, "C");

view = new TreeView(model);

column = view.appendColumn();
column.setTitle("Programming Languages");
renderer = new CellRendererText(column);
renderer.setText(dataCol);

view.connect(new TreeView.RowActivated() {

public void onRowActivated(TreeView treeView,
TreePath treePath,
TreeViewColumn treeViewColumn) {

final TreeIter row;
final String text;

row = model.getIter(treePath);
text = model.getValue(row, dataCol);

statusbar.setMessage(text);
}
});

VBox vbox = new VBox(false, 0);

vbox.packStart(view);
vbox.packStart(statusbar, false, false, 0);
add(vbox);
}

public static void main(String[] args) {
Gtk.init(args);
new GTree();
Gtk.main();
}
}
This time we use the TreeView widget to show hierarchical data.
 model = new TreeStore(new DataColumn[] {
dataCol = new DataColumnString(),
});
Here we declare the TreeStore to have one string data column.
 model.setValue(row, dataCol, "Scripting languages");
We append a top level node.
 rowChild = model.appendChild( row );
model.setValue(rowChild, dataCol, "PHP");
We append a child row for the top level node.
 view = new TreeView(model);
We create the instance of the TreeView widget.
 column = view.appendColumn();
column.setTitle("Programming Languages");
renderer = new CellRendererText(column);
renderer.setText(dataCol);
We create the column and the cell renderer.
 row = model.getIter(treePath);
text = model.getValue(row, dataCol);

statusbar.setMessage(text);
Upon double click, we show the selected node in the statusbar.

Tree
Figure: Tree


In this chapter, we were talking about advanced Java Gnome widgets.
Continue Reading

Introducing Widgets in Java Gnome

 Introducing Widgets in Java Gnome

In this part of the Java Gnome programming tutorial, we continue introducing widgets.

Entry

The Entry is a single line text entry field. This widget is used to enter textual data.
entry.java
package com.zetcode;

import org.gnome.gdk.Event;
import org.gnome.gtk.Editable;
import org.gnome.gtk.Entry;
import org.gnome.gtk.Fixed;
import org.gnome.gtk.Gtk;
import org.gnome.gtk.Label;
import org.gnome.gtk.Widget;
import org.gnome.gtk.Window;
import org.gnome.gtk.WindowPosition;

/**
* ZetCode Java Gnome tutorial
*
* This program shows how to use
* an Entry widget.
*
* @author jan bodnar
* website zetcode.com
* last modified March 2009
*/


public class GEntry extends Window {

private Label label;
private Entry entry;

public GEntry() {

setTitle("Entry");

initUI();

connect(new Window.DeleteEvent() {
public boolean onDeleteEvent(Widget source, Event event) {
Gtk.mainQuit();
return false;
}
});

setDefaultSize(250, 200);
setPosition(WindowPosition.CENTER);
showAll();
}


public void initUI() {

label = new Label("...");

entry = new Entry();

entry.connect(new Entry.Changed() {
public void onChanged(Editable editable) {
label.setLabel(entry.getText());
}
});

Fixed fix = new Fixed();
fix.put(entry, 60, 100);
fix.put(label, 60, 40);

add(fix);

}


public static void main(String[] args) {
Gtk.init(args);
new GEntry();
Gtk.main();
}
}
This example shows an entry widget and a label. The text that we key in the entry is displayed immediately in the label control.
 entry = new Entry();
Entry widget is created.
 entry.connect(new Entry.Changed() {
public void onChanged(Editable editable) {
label.setLabel(entry.getText());
}
});
If the text in the Entry widget is changed, we call the onChanged() method. In this method, we get the text from the Entry widget and set it to the label.

Entry Widget
Figure: Entry Widget

Scale

The Scale is a widget, that lets the user graphically select a value by sliding a knob within a bounded interval. Our example will show a volume control.
hscale.java
package com.zetcode;

import java.io.FileNotFoundException;

import org.gnome.gdk.Event;
import org.gnome.gdk.Pixbuf;
import org.gnome.gtk.Fixed;
import org.gnome.gtk.Gtk;
import org.gnome.gtk.HScale;
import org.gnome.gtk.Image;
import org.gnome.gtk.Range;
import org.gnome.gtk.Widget;
import org.gnome.gtk.Window;
import org.gnome.gtk.WindowPosition;

/**
* Java Gnome tutorial
*
* This program shows how to use
* the HScale widget. It implements a
* volume control.
*
* @author jan bodnar
* website zetcode.com
* last modified March 2009
*/

public class GHScale extends Window {

private HScale hscale;
private Image image;

private Pixbuf mute;
private Pixbuf min;
private Pixbuf med;
private Pixbuf max;

public GHScale() {

setTitle("HScale");

initUI();

connect(new Window.DeleteEvent() {
public boolean onDeleteEvent(Widget source, Event event) {
Gtk.mainQuit();
return false;
}
});

setDefaultSize(260, 120);
setPosition(WindowPosition.CENTER);
showAll();
}

public void initUI() {

loadImages();


hscale = new HScale(0, 99, 1);
hscale.setSizeRequest(130, 45);
hscale.setCanFocus(false);

image = new Image("mute.png");

hscale.connect(new HScale.ValueChanged() {

public void onValueChanged(Range range) {
int pos = (int) hscale.getValue();

if (pos == 0) {
image.setImage(mute);
} else if (pos > 0 && pos <= 30) {
image.setImage(min);
} else if (pos > 30 && pos < 80) {
image.setImage(med);
} else {
image.setImage(max);
}
}
});

Fixed fixed = new Fixed();

fixed.put(hscale, 40, 20);
fixed.put(image, 220, 40);

add(fixed);
}

private void loadImages() {
try {
mute = new Pixbuf("mute.png");
min = new Pixbuf("min.png");
med = new Pixbuf("med.png");
max = new Pixbuf("max.png");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}


public static void main(String[] args) {
Gtk.init(args);
new GHScale();
Gtk.main();
}
}
In the example above, we have HScale and Image widgets. By dragging the scale we change the image on the Image widget.
 hscale = new HScale(0, 99, 1);
HScale widget is created. The parameters are lower boundary, upper boundary and step.
 int pos = (int) hscale.getValue();
In the onValueChanged() method we obtain the value of the scale widget.
 if (pos == 0) {
image.setImage(mute);
} else if (pos > 0 && pos <= 30) {
image.setImage(min);
} else if (pos > 30 && pos < 80) {
image.setImage(med);
} else {
image.setImage(max);
}
Depending on the obtained value, we change the picture in the image widget.

HScale Widget
Figure: HScale Widget

ToggleButton

ToggleButton is a button that has two states. Pressed and not pressed. You toggle between these two states by clicking on it. There are situations where this functionality fits well.
togglebuttons.java
package com.zetcode;

import org.gnome.gdk.Color;
import org.gnome.gdk.Event;
import org.gnome.gtk.DrawingArea;
import org.gnome.gtk.Fixed;
import org.gnome.gtk.Gtk;
import org.gnome.gtk.StateType;
import org.gnome.gtk.ToggleButton;
import org.gnome.gtk.Widget;
import org.gnome.gtk.Window;
import org.gnome.gtk.WindowPosition;

/**
* ZetCode Java Gnome tutorial
*
* This program demonstrates the ToggleButton
* widget. Three toggle buttons control the
* color of a drawing area.
*
* @author jan bodnar
* website zetcode.com
* last modified March 2009
*/

public class GToggleButton extends Window
implements ToggleButton.Toggled {

private ToggleButton tb1;
private ToggleButton tb2;
private ToggleButton tb3;

private DrawingArea darea;
private Color color;

public GToggleButton() {

setTitle("ToggleButton");

initUI();

setPosition(WindowPosition.CENTER);

setSizeRequest(350, 220);
showAll();
}


public void initUI() {

color = new Color(0, 0, 0);

connect(new Window.DeleteEvent() {
public boolean onDeleteEvent(Widget source, Event event) {
Gtk.mainQuit();
return false;
}
});

Fixed fixed = new Fixed();

tb1 = new ToggleButton("Red");
tb1.setSizeRequest(80, 35);
tb1.connect(this);

tb2 = new ToggleButton("Green");
tb2.setSizeRequest(80, 35);
tb2.connect(this);

tb3 = new ToggleButton("Blue");
tb3.setSizeRequest(80, 35);
tb3.connect(this);

darea = new DrawingArea();
darea.modifyBackground(StateType.NORMAL, Color.BLACK);
darea.setSizeRequest(150, 150);

fixed.put(tb1, 20, 20);
fixed.put(tb2, 20, 65);
fixed.put(tb3, 20, 110);

fixed.put(darea, 150, 20);

add(fixed);
}


public void onToggled(ToggleButton toggleButton) {

int red = color.getRed();
int green = color.getGreen();
int blue = color.getBlue();

if ("Red".equals(toggleButton.getLabel())) {
if (toggleButton.getActive()) {
red = 65535;
} else {
red = 0;
}
}

if ("Green".equals(toggleButton.getLabel())) {
if (toggleButton.getActive()) {
green = 65535;
} else {
green = 0;
}
}

if ("Blue".equals(toggleButton.getLabel())) {
if (toggleButton.getActive()) {
blue = 65535;
} else {
blue = 0;
}
}

color = new Color(red, green, blue);
darea.modifyBackground(StateType.NORMAL, color);
}

public static void main(String[] args) {

Gtk.init(args);
new GToggleButton();
Gtk.main();
}
}
In our example, we show three toggle buttons and a DrawingArea. We set the background color of the area to black. The togglebuttons will toggle the red, green and blue parts of the color value. The background color will depend on which togglebuttons we have pressed.
 color = new Color(0, 0, 0);
This is the color value that is going to be updated with the toggle buttons.
 tb1 = new ToggleButton("Red");
tb1.setSizeRequest(80, 35);
tb1.connect(this);
The ToggleButton widget is created. We set it's size to 80x35 pixels. It is connected to the onToggled() method.
 darea = new DrawingArea();
darea.modifyBackground(StateType.NORMAL, Color.BLACK);
darea.setSizeRequest(150, 150);
The DrawingArea widget is the widget, that displays the color, mixed by the toggle buttons. At start, it shows black color.
 if ("Red".equals(toggleButton.getLabel())) {
if (toggleButton.getActive()) {
red = 65535;
} else {
red = 0;
}
}
We update the red part of the color based on the state of the red toggle button.
 color = new Color(red, green, blue);
darea.modifyBackground(StateType.NORMAL, color);
The color value is updated and set to the DrawingArea widget.

ToggleButton widget
Figure: ToggleButton widget

Calendar

Our final widget is the Calendar widget. It is used to work with dates.
calendar.java
package com.zetcode;

import org.gnome.gdk.Event;
import org.gnome.gtk.Calendar;
import org.gnome.gtk.Gtk;
import org.gnome.gtk.Label;
import org.gnome.gtk.VBox;
import org.gnome.gtk.Widget;
import org.gnome.gtk.Window;
import org.gnome.gtk.WindowPosition;

/**
* ZetCode Java Gnome tutorial
*
* This program demonstrates the Calendar
* widget. We show a selected date in a
* label widget.
*
* @author jan bodnar
* website zetcode.com
* last modified March 2009
*/

public class GCalendar extends Window {

private Calendar calendar;
private Label label;

public GCalendar() {

setTitle("Calendar");

initUI();

connect(new Window.DeleteEvent() {
public boolean onDeleteEvent(Widget source, Event event) {
Gtk.mainQuit();
return false;
}
});

setDefaultSize(260, 120);
setPosition(WindowPosition.CENTER);
showAll();
}

private void initUI() {

VBox vbox = new VBox(false, 1);

calendar = new Calendar();
label = new Label(getDate());

calendar.connect(new Calendar.DaySelected() {

public void onDaySelected(Calendar calendar) {
label.setLabel(getDate());
}
});

vbox.add(calendar);

label.setSizeRequest(-1, 50);
vbox.add(label);

add(vbox);
}


private String getDate() {
int year = calendar.getDateYear();
int month = calendar.getDateMonth();
int day = calendar.getDateDay();
String dateLabel = month + "/" + day + "/" + year;

return dateLabel;
}


public static void main(String[] args) {
Gtk.init(args);
new GCalendar();
Gtk.main();
}
}
We have the Calendar widget and a Label. The selected day from the calendar is shown in the label.
 calendar = new Calendar();
Calendar widget is created.
 public void onDaySelected(Calendar calendar) {
label.setLabel(getDate());
};
In the onDaySelected() method we update the label to the currently selected date.

Calendar
Figure: Calendar


In this chapter, we finished talking about widgets in Java Gnome.
Continue Reading