Skip to main content

How to rock around the clock?

Posted by malenkov on December 18, 2008 at 12:00 AM PST

JavaFX has been released recently and now many beginners google on how to start programming. Let us consider a very simple example of drawing a clock face in JavaFX.

First, draw a second hand. Pay attention to the position of the hand relative to the origin of coordinates, which will be used as a center of rotation. For example, rotate the hand by 60° (10 seconds).

 

        Rectangle {
          x:       - 2
          y:       - 100
          width:     4
          height:    120
          arcWidth:  4
          arcHeight: 4
          transforms: Rotate {
            angle: 60
          }

        }

Now draw the minute hand and rotate it, for example, by 301° (50 minutes and 10 seconds).

 

        Rectangle {
          x:       - 4
          y:       - 80
          width:     8
          height:    100
          arcWidth:  8
          arcHeight: 8
          transforms: Rotate {
            angle: 301
          }

        }

Next, draw the hour hand and rotate it, for example, by 175° (5 hours and 50 minutes).

 

        Rectangle {
          x:       - 6
          y:       - 60
          width:     12
          height:    80
          arcWidth:  12
          arcHeight: 12
          transforms: Rotate {
            angle: 175
          }

        }

Finally, mark the clock face. Draw 12 ticks with incremental rotation of 30°.

 

        for (i in [1 .. 12]) Rectangle {
          x:       - 2
          y:       - 100
          width:     4
          height:    20
          arcWidth:  4
          arcHeight: 4
          transforms: Rotate {
            angle: 30 * i
          }

        }

For clock refresh I use an indefinite timeline which updates current time every second by using the Calendar.getInstance method.

  def timer = Timeline {
    repeatCount: Timeline.INDEFINITE
    keyFrames: KeyFrame {
      time: 1s
      action: function() {
        calendar = Calendar.getInstance()
      }
    }
  }

Note that the code above uses a Java class, the Calendar, whose behavior in J2ME differs from that in J2SE. Specifically, it does not initialize the current time in the getInstance method. If you want to use this application on a mobile device, fix that behavior. For example, create the following method.

  function getCalendar() {
    def calendar = Calendar.getInstance();
    calendar.setTime(new Date());
    calendar
  }

In this example, the clock face is declared as a custom node so that the clock widget can be used in other applications. To further customize, set the following instance variables:
var fill: Paint; // Defines parameters to fill the interior of a Shape using the settings of the Paint context.
var stroke: Paint; // Defines parameters of a stroke that is drawn around the outline of a Shape using the settings of the specified Paint.
var radius: Number; // Defines the radius of the clock face.
var thick: Number; // Defines the thickness of the second hand. Thickness of other hands is calculated automatically.
var paused = true; // Handles the timeline. To start refreshing every second, set the value of the variable to false.

To create an applet with the clock widget, a simple JavaFX application was developed. There are some interesting details that should be described. First, in order to use transparent windows, you should not only set the transparent style of the stage, but also remove the background color of the scene.

var stage: Stage = Stage {
  title: "Clock (JavaFX sample)"
  style: StageStyle.TRANSPARENT
  scene: Scene {
    fill: null
    width: 320
    height: 320
    content: Clock {
      paused: false
      ...

Secondly, having the clock in the center of the screen is annoying. So adding an ability to drag the window would be good.

      onMouseDragged: function(event) {
        stage.x += event.dragX;
        stage.y += event.dragY;
      }

Finally, a linear gradient is created automatically using the colors sequence.

def colors = [ Color.CYAN, Color.GREEN, Color.YELLOW ];
...
      stroke: colors[sizeof colors / 2]
      fill: LinearGradient {
        def factor = sizeof colors - 1.0;
        stops: for (color in colors) Stop {
          color: color
          offset: indexof color / factor
        }
      }

Now you are prepared to look at the AnalogClock sample to learn how to add text labels for each tick and much more.

 

My other samples are: Draw, FlyingLetters, Magnetism, VideoCube, and WeatherWidget.

original post

Related Topics >>

Comments

SceneGraph home: https://scenegraph.dev.java.net/

You can use SceneGraph library in Java, but JavaFX script provides declarative syntax that simplifies creation of Java2D scenes.

Nice example. But... could anyone explain why a new "language"/script has been invented? Could the same stuff be "formulated" using the good-old Java? What is the point really?

You can drag it, just point the cursor inside one of the hands

The application can't be dragged because of security. Seems that the yellow triangle prevents dragging to the second monitor. I'll file a bug.

Kirill, I've commented out FX applet. I'll try to solve the problem.

Nice example but one small criticism - it's stuck on my primary monitor. When I try to drag it off to the second monitor it refuses and stays at the locked at the screen border whilst my mouse continues on to the other monitor. I know Swing behaves properly in these circumstances but it's a pretty poor thing for JavaFX to behave like this .

Do you really want to prevent people that have the right Java installed from reading your blog. The dtfx.js script kicks me out of this page telling me to install Java (which i already have, including 6u10, 6u11 and 6u12). I had to blacklist javafx.com in NoScript extension to be able to read this blog.