Building a Stop Watch Widget

By , September 24, 2008

이 위젯은 표준 스톱워치를 에뮬레이트 하며 이것은 multi-file 위젯 어플리케이션의 좋은 본보기 입니다. 이 예제는 여러분에게 위젯 클래스 형식으로 생성하고 감상을 위해서 JavaFX stage 위에 말끔하게 위치시키는 것을 보여줄 것입니다.

StopwatchModel.fx

StopwatchModel Class

이것은 스톱왓치를 위한 클래스 선언입니다. 속성들과 클래스 함수들을 사용하여(전통적인 자바의 클래스 변수들과 같은) StopwatchModel는 우리가 선언한 time, hand angels 게다가 시작, 멈춤 그리고 리셋하는 함수들이 있는 곳에 위치합니다. 이 부분의 코드는 여러분이 자바에서 보았었을 것들과 가장 닮아 있습니다.

아래 코드 조각들은 time과 스톱워치의 hand-angles 마찬가지로 바닥에 표시되왔던 문자열을 서로 묶어주는 클래스 속성 timeListener 입니다.

Source Code
private attribute timerListener:ActionListener = ActionListener {
    public function actionPerformed(evt:ActionEvent): Void {
        if (lastClockTime == 0) lastClockTime = System.currentTimeMillis() as Integer;
        var now:Integer = System.currentTimeMillis() as Integer;
        var delta = now - lastClockTime;
        elapsedMillis += delta;
        var elapsedHundredthsSecond:Integer = elapsedMillis/10;

        var hundredthsExact:Number = (elapsedMillis/10.0)%10;
        var tenthsExact:Number = (elapsedMillis/100.0)%100;

        var tenths:Integer = (elapsedHundredthsSecond/10)%10;
        var seconds:Integer = (elapsedHundredthsSecond/100)%60;

        handAngle = 180 + ((360/60.0)*seconds);
        tenthsHandAngle = 180 + ((360/10.0)*tenthsExact);
        minutesHandAngle = 180 + ((360/600.0)*seconds);

        var decimalSeconds:Number = (elapsedHundredthsSecond/100.0)%60.0;
        var mins:Integer = elapsedHundredthsSecond/6000;

        timeString = "{%02d mins}:{%05.2f decimalSeconds}";
        
        lastClockTime = now;
    }
}

LightTheme.fx

LightTheme Class

이 파일은 스톱워치의 그래픽을 생성합니다. 그래픽 컨텐츠는 그 스스로 자식 그룹노드들을 가지고 있는 그룹노드이고 내부의 각 렌더링은 랜더링은 스톱워치의 이미지 부분(Main Dial, Digits, Start and Stop)들을 분리합니다. 각 부모 그룹은 개발자가 분리되게 각 객체들을 생성하고 나서 완료된 이미지들을 그래픽 안에서 원했던 위치에 서로 이동하는 것을 가능하게 하는 그 자신의 변환좌표를 가지고 있습니다. stopwatch.png 이미지 파일은 단지 hands, digits, ticks 그리고 미니 다이얼 모두가 JavaFX geometries를 이용해서 모두 생성될 동안 스톱워치의 배경이미지를 제공하고 스톱워치의 레이아웃을 생성하기 위해 서로 그룹지어집니다. 실행해 보세요, 어플리케이션은 이처럼 보여질것입니다:

JavaFX의 중요한 기능은 바인드 툴입니다- 이 툴은 변화하기 위해서 무언가가 바인드 될때 하나의 변수가 자동으로 업데이트 되는 것을 허용합니다. StopwatchModel, the handAngle, tenthsHandAngle, 그리고 minutesHandAngle 안에서 계산됩니다. LightTheme 에서 우리는 각도들이 업데이트 될때마다 새로운 이미지는 "rotate" 속성을 사용하여 minuteHand, secondHand 또는 tenthsHand가 새로운 위치를 자동으로 변경하는 것을 보여주는 "bind" 툴을 사용했습니다.

Source Code
// Hand
Group {
    content: [
        Group {
            content: [
                Circle {centerX: 140 centerY: 140 radius: 8
                    fill: Color.web("#FF0000")},
                Rectangle{x: -1.5 y: -20 width: 3 height: 120
                        fill: Color.web("#FF0000")
                        rotate: bind model.handAngle
                        translateX: 140
                        translateY: 140},

            ]
            effect: Lighting{
                light: DistantLight {azimuth: 225}
            }
        },
                Rectangle{x: -1.5 y: -40 width: 3 height: 20
                        fill: Color.web("#FFFFFF")
                        rotate: bind model.handAngle
                        translateX: 140
                        translateY: 140}
    ]
    effect: DropShadow {offsetX: 4 offsetY: 4 radius: 6 color: Color.web("#000000")}
}

StopwatchWidget.fx and Main.fx

widget을 초기화 하기 Frame Stage 위에 배치하기

우리는 이미 Stopwatch와 Stopwatch Graphic을 정의하는 클래스를 생성했었습니다. 마지막으로 해야할 일은 스톱워치의 인스턴스를 생성하고 이것을 Frame's stage에 위치시키는 것입니다. Main.fx 에서 우리는 프레임을 간단하게 생성하고 프레임의 stage 속성 안쪽에 우리의 스톱워치 위젯을 위치합니다. JavaFx는 여러분을 위해서 윈도우를 생성하고 안쪽에 여러분의 완성된 위젯을 놓을것입니다.

Source Code
Stage {
    var sw = StopwatchWidget{}
    scene: Scene {
        content: sw
        fill: null // make the background transparent
    }
}

The file StopwatchWidget.fx파일은 우리의 Stopwatch 객체로 부터 stage의 내용을 추상화 합니다. 만약 우리가 깔끔한 효과를 추가하기는 원하지만 Stopwatch의 클래스 코드를 변경하는 것을 원하지 않는다면 이것이 그것을 처리할할 장소가 될것입니다. 여기 우리는 원래의 위젯를 잃지 않고 우리의 위젯의 관점을 변경할 효과를 코드화 할수 있습니다. 그리고 만약 우리가 Stopwatch 옆에 대로 다른 위젯을 생성했다면 우리는 두개의 위젯들 사이에서 우리가 전후로 가도록 하는 스위칭 메카니즘을 만들수 있을것입니다.