JavaFX 1.2 迁移指南(英文)

分类: JAVAFX技术, JavaFX编程.
标签: , , ,

本文经授权转载自Stephen Chin的英文文章The Definitive 1.2 Migration Guide中文翻译参见这里

Below is the JavaFX 1.2 migration guide written by Stephen Chin. The original article can be found on his blog steveonjava.com. I post his article here for readers who cannot visit Stephen’s blog due to networking problem. Steve, thanks a lot for allowing me to share it here. The Chinese translation can be found here.

The Definitive 1.2 Migration Guide

by Stephen Chin


If you have made it this far, you are a serious JavaFX hacker!  This section covers the most common language, functionality, and API changes that you will encounter when migrating applications from JavaFX 1.1.  If you notice anything that is not covered, feel free to add it in the comments and I will update the guide as appropriate.


General:

  • JavaFX 1.2 is not binary compatible – If you use any jars or third-party JavaFX libraries (such as JFXtras), they must be recompiled for the new release or you will get compilation errors.  Speaking of JFXtras, a new version which has been updated for JavaFX 1.2 is nearly ready, and will be announced here when it is complete!
  • All internal-only APIs are broken – More details broken out by section below, but if you rely on any impl_ or com.sun packages, your code will definitely need to be updated.
  • Linux and Solaris are now supported – This is more of a feature than a migration issue, but if you have users on multiple platforms you can now proudly state that Linux is supported.


Language Changes:

  • No more variable shadowing in nested blocks – It previously was valid to name a variable the same in both the inner and outer block of an expression.  The variable in the inner block would simply replace the one in the outer.  However, this will throw a compiler error in JavaFX 1.2.  The fix is simple…  just use a different variable name.
  • Use Mixins instead of Multiple Inheritance – JavaFX no longer supports multiple inheritance.  Instead you can extend one class and as many mixins as you like.  Mixins are like interfaces in Java, except they can have variables and implementations that are shared by all the classes that extend them.  The only change you have to make in your application to start using mixins is to add the mixin keyword when you define a new class like this:
public mixin class Resizable { /* variables and functions here */ }
  • Commas are required in sequences – Sequences now require commas between elements (except those that end in braces).  This is a little less convenient, but actually a very good thing, because it avoids several language pitfalls that were hard to track down before.


Node Changes:

  • Node.boundsInScene is gone – This was removed for performance reasons, fortunately there is an easy replacement that offers the same functionality:
node.localToScene(node.boundsInLocal)
  • Node.focusable -> Node.focusTraversable – Small API change, but good to know when you get the compilation error on focusable not found.  This is part of a larger focus fix where any Node that is visible, focusTraversable, and not disabled will be eligible for focus (a key listener is no longer required).
  • CustomNode.create() gets called before init – Previously the CustomNode create() method would get called after init and before postinit.  Now that it gets called even earlier than init, some of your code may not work correctly.  Make sure that any variables you are depending upon in the create() method are either initialized inline or have a bind declaration so they get updated once set.
  • SwingControl.enabled -> Node.disable – There is a new disable flag on the Node class that is used universally across all controls to enable or disable them.  This conflicted with the old SwingControl.enabled variable, which has now been removed.
  • Rectangle2D -> Bounds – All references to Rectangle2D have been changed to the new javafx.geometry.Bounds class, which may have a ripple effect through your code.


Layout Changes:


  • min/max/pref -> getters – All of the Resizable methods (minimumWidth, minimumHeight, maximumWidth, maximumHeight, preferredWidth, preferredHeight) have been replace with function getters (getMinWidth, getMinHeight, getMaxWidth, getMaxHeight, getPrefWidth, getPrefHeight respectively).  The prefWidth/Height functions take an extra parameter, which is the amount of space in the opposite dimension.  This is very useful for doing height or width constrained layouts, such as Flows, but can be ignored by passing -1.
  • impl_layoutX/Y -> layoutX/Y – The impl_layoutX and impl_layoutY methods have been replaced with official layoutX and layoutY variables.  It is recommended that you use these variables over translateX/Y if you are moving nodes into position.
  • impl_requestLayout() -> requestLayout() – The requestLayout function has similarly moved from an internal to a public API.
  • impl_layout -> doLayout() – Rather than having a function to set the layout on, you now override Parent.doLayout().
  • Panel class added for declarative layouts – If you are looking for a functional alternative to Container, take a look at the new Panel class, which lets you set the layout declaratively.  It also has variables to override the default min/max/pref values without subclassing Container.
  • New functions on Container to help with layouts – There are a whole slew of new functions on the Container class that make it easier to work with the new layout system.  Make sure to read through them, because they will both save you time and help you follow the best practices for layout design.
  • Different transformation order – Previously the transforms[] variable allowed you to apply transformations included in the layoutBounds, while scaleX/translateX/rotate etc. were applied after layout.  Now both transforms[] and the transformation variables are calculated after layout uniformly.


Skin/Control Changes:


  • Skin.scene -> Skin.node – The name of the Node on Skin has changed from scene to node, which helps reduce confusion with the Scene class.
  • Skin.compute* methods removed – There were a series of computePreferredWidth/Height/etc. methods that were removed.  Instead you can directly use the getPrefWidth/Height/etc. methods on the Resizable class mentioned above.
  • Skin is now abstract – The Skin class is now abstract, and required that you implement your own contains and intersects methods.  You can either do this by using the new JFXtras AbstractSkin class or using the following boilerplate code:
override function contains(localX:Number, localY:Number):Boolean {
    return node.contains(localX, localY);
}

override function intersects(localX:Number, localY:Number,
   localWidth:Number, localHeight:Number):Boolean {
    return node.intersects(localX, localY, localWidth, localHeight);
}
  • New Behavior class – There is a new Behavior class that is meant to be used together with Control and Skin to provide reusable behaviors.
  • TextBox.text -> rawText, TextBox.value -> text – There was some swizzling of variables on the TextBox class.  What used to be text changed to rawText, and value now has the same semantics text used to have.


Asynchronous Changes:


  • RemoteTextDocument has been removed – Use HttpRequest directly instead.
  • AbstractAsyncOperation has been removed – Use the new Task infrastructure instead for communcating with Java code running in a background thread.


Animation Changes:


  • Transition.interpolate -> Transition.interpolator – A small name change to make room for a new interpolate flag that allows you to turn on or off interpolation altogether.
  • Transition now extends Timeline - This is a welcome change, which makes it much easier to work with Transitions and Timelines together.  To support this change ParallelTransition and SequentialTransition now take a sequence of Timeliens.


Java Equivalent Functions:

  • java.lang.Math -> javafx.util.Math – There is a new JavaFX math library, which is a drop-in replacement for the Java math library.  The main advantage of using the new JavaFX math library is that all functions are supported on mobile devices (including pow, log, etc.).
  • java.lang.Properties -> javafx.util.Properties – Another class that is similar in functionality to the Java equivalent, but portable to mobile.  Be warned, however, that the JavaFX properties file format is not the same as the standard Java properties file format.


CSS Changes:

  • CSS Update Defect (RT-4817) – Stylesheet updates no longer affect newly added Nodes due to a known defect.  In the meantime, you can do this to force a stylesheet refresh:
def senators = bind model.senators on replace {
    delete sceneRef.stylesheets;
    sceneRef.stylesheets = "{__DIR__}styles.css";
}
  • CheckBoxSkin.textFill doesn’t accept styles (RT-4819) - The check mark will pick up the style you set, but the text won’t.  The workaround for now is to create a checkbox with empty text and add a text node beside it with the correct styling and event handlers.
  • Can’t update the skin property of Control from CSS (RT-4820) – Another bug in the skin support.  You can set this in code instead for now.


Production Suite:

  • UiStub -> FXDNode – UiStub has been replaced with FXDNode, which includes some extra functionality, such as backgroundLoading, and placeholder images.


Miscellaneous:

  • Image.fromBufferedImage() removed – This has moved to SwingUtils.toFXImage().  Remember that if you use this function it will limit portability to mobile devices.
  • Color.fromAWTColor() removed – Yet another AWT-ism that has been removed. The JavaFX Color class is pretty thorough, so there shouldn’t be any reason to work with AWT Colors.
  • Duration.toDate is gone – As far as I know there is no equivalent functionality, but you can always get a duration’s value as a long and manipulate it directly.
  • Different variable names for the Affine class – If you use the Affine class, then your code is likely to break due to the new, more descriptive, method names, but the functionality is the same.


Whew!  …that was quite a lot to take in.  If you are interested to read more about the JavaFX 1.2 release including the new controls, layouts, and other functionality, the best source is to checkout the Pro JavaFX book that Jim, Dean, Weiqi, and I are writing.  It is almost fully updated for the JavaFX 1.2 release, and is available in Alpha right now from the book website.


I want to give a special thanks to Richard Bair and Amy Fowler from the Sun JavaFX team for providing a lot of valuable information on the JavaFX 1.2 release along the way.

Happy hacking on JavaFX 1.2!

评论 (0) 2009年06月13日

快速升级到JavaFX 1.2的方法

分类: JAVAFX技术.
标签: , , ,

javafxblogs.com Rss_google Rss_zhuaxia Rss_xianguo


JavaFX 1.2给我们带来了许多功能和性能上的提升,因此,我需要对原来的JavaFX 1.1的IDE和SDK进行升级来使用JavaFX 1.2的新特性。对于从来没有使用过JavaFX的用户来说,安装JavaFX SDK 1.2应该很简单,可以从javafx.com下载一个NetBeans 6.5.1+JavaFX 1.2 SDK混合包,那就OK了。可是对于我这种已经使用NB 6.5.1和JavaFX 1.1.1的用户,就需要考虑一些其它问题。因为我有不少程序是按照JavaFX 1.1的API写的,骤然升级可能会使得无法使用这些程序。同时由于两个SDK的IDE版本都是NetBeans 6.5.1,重新安装一遍也太浪费空间和时间,于是我查阅了一些资料并找到了快速升级的方式,同时还可以保留两个版本的SDK。


如果需要同时支持2个版本的JavaFX SDK,可以在升级前先把旧版本备份一下,这样可以避免被新的SDK覆盖。JavaFX SDK 1.1的缺省目录在C:\Program Files\NetBeans 6.5.1\javafx2\javafx-sdk,把它拷贝到另外一个目录,如C:\jfxsdk11\ 。


接下来就是升级了。在NB6.5.1 中,选择菜单Tools-〉Plugins,这时会列出一些可更新的plugin,如果没有看到列表,可以点击“Reload Catalog”按钮。如果plugin太多,可以在Search框中输入JavaFX过滤一下。有3个Plugin和JavaFX相关:

Plugins    说   明
JavaFX Kit     改进过的NetBeans IDE, Version 1.8
JavaFX SDK for Windows     JavaFX SDK 1.2, Versions 1.7
JavaFX Weather Sample     JavaFX演示程序, Versions 1.7



其中前面两个plugin是必需的,演示程序可自己决定取舍。选择安装之后,需要重新启动NetBeans。重新启动后,新的JavaFX SDK1.2 就安装完成了。如果要配置JavaFX 1.1的环境,则可以在菜单Tools->Java Platforms中配置。点击“Add Platform…”按钮添加平台,下一步中再选择JavaFX平台,输入平台名称如”Java SDK 1.1″,平台文件夹中输入刚才备份的目录C:\jfxsdk11\,点击”结束”即可。系统可能会有一个不支持之类的警告,但是不用理会。

如果你的项目需要使用JavaFX 1.1,可在项目的属性(右键点击该项目,选Properties)中配置libraries(库),可以选择JavaFX平台。这样,在同一个NetBeans IDE中就可以同时使用两个JAVAFX SDK环境了。当然,如果你没有太多JavaFX 1.1的程序,或者现有的程序和JavaFX 1.2兼容,那就基本上没有必要配置两个SDK版本了。


在用JavaFX 1.2重新编译了原来的程序后,发现JavaFX1.2的性能提升了不少。原来我用JavaFX 1.1写的吃豆人游戏,要占用50%左右的CPU利用率,现在只需要10-20%,进步还是比较明显的。所以建议尽可能使用JavaFX 1.2。


最新文章:

JavaFX吃豆人游戏的编写过程之三
JavaFX 1.2的新特性
JavaFX吃豆人游戏的编写过程之二
JavaFX游戏吃豆人的编写过程


英文文章连载:
第一篇文章,2009年5月14日:
Writing the Pac-Man Game in JavaFX - Part 1

第二篇文章,2009年5月21日:
Writing the Pac-Man Game in JavaFX - Part 2

第三篇文章,2009年5月28日:
Writing the Pac-Man Game in JavaFX - Part 3

第四篇文章,2009年6月4日:
Writing the Pac-Man Game in JavaFX - Part 4

评论 (0) 2009年06月07日

JavaFX许愿树程序:Effect功能的应用(3)

分类: JAVAFX技术, 许愿树.
标签:

在上篇文章中,我们可以在许愿树上悬挂许多愿望星了。现在,我们给程序增加些功能,可以在星星上记录许愿者的名字和愿望。你可以点击以下画面启动许愿树,点击许愿树后,可以看到一个弹出的窗口来输入姓名和愿望,点击“OK”确认。如果再次点击同一颗星星,就可以修改愿望的内容,快来试试看吧:(JDK1.5+或JDK 1.6)



点击启动许愿树程序


点击启动许愿树程序3

我们来看看如何增加一个半透明的输入窗口,代码在Dialog类中。首先,我们定义一个CustomNode。javafx.scene.CustomNode提供了用户自定义图形结点(Node)的方法,程序中需要继承该类,然后实现create()函数并返回自定义的Node。我们的CustomNode由一个Group实例来实现,包括一个蓝色半透明的外围框,两个输入框,两个文本以及一个“OK”按钮。Dialog.fx的代码如下:

( JAVAFX参考文章:
用JavaFX的Effect实现许愿树(1)
用JavaFX的Effect功能编写许愿树(1)
JavaFX 1.1和1.0的兼容性 http://blog.sina.com.cn/javafxcenter
JavaFX和Java之间的互操作性
Java和JavaFX的互操作性


/*
 * Dialog.fx
 *
 * http://www.javafxblogs.com
 */

package wishtree;

import javafx.ext.swing.SwingButton;
import javafx.ext.swing.SwingTextField;
import javafx.scene.CustomNode;
import javafx.scene.Group;
import javafx.scene.layout.VBox;
import javafx.scene.Node;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.scene.text.TextOrigin;
import javafx.stage.Stage;

/**
 * @author Henry Zhang
 */

public class Dialog extends CustomNode {

  public var stage: Stage;
  public var star : Star;

  var w = bind stage.width;
  var h = bind stage.height;

  public var nameField : SwingTextField;
  public var wishField : SwingTextField;

  public function show( s: Star): Void {
    star = s;
    wishField.text = s.wish;
    nameField.text = s.name;
    visible = true;
  }

  public override function create(): Node {
    Group {
      blocksMouse: true;
      translateX: bind w / 6
      translateY: bind h / 4

      content: [
        Rectangle {
          stroke: Color.WHITE
          strokeWidth: 3
          width: bind w * 2 / 3
          height: bind h / 2
          fill : Color.BLUE;
          opacity: 0.5
          arcHeight: 10
          arcWidth: 10
        },
        // 本文发表自 http://www.javafxblogs.com
        VBox {
          spacing: 15
          translateX: bind w / 6
          translateY: bind h / 8
          content: [
            Text {
              content: "名字:"
              textOrigin: TextOrigin.TOP
              fill: Color.YELLOW
              font: Font.font ( null, FontWeight.BOLD, 20);
            },
            nameField = SwingTextField {
              text: "your name"
              width: bind w / 4
            },
            Text {
              content: "愿望:"
              textOrigin: TextOrigin.TOP
              fill: Color.YELLOW
              font: Font.font ( null, FontWeight.BOLD, 20);
            },
            wishField = SwingTextField {
              text:  "我希望..."
              width: bind w * .4
            },
            SwingButton {
              text: "OK"
              action: function():Void {
               star.name = nameField.text;
               star.wish = wishField.text;

               visible = false;
              }
            }
          ]
         },
     ]
   }
  }
}



在create()函数中,我们定义了圆角矩形的透明度为0.5,即可产生半透明的效果,arcHeight和arcWidth两个变量决定了圆角的大小。JavaFX技巧、编程和技术JavaFX Guy技术应用博客

 // http://www.javafxblogs.com
 Rectangle {
          stroke: Color.WHITE
          strokeWidth: 3
          width: bind w * 2 / 3
          height: bind h / 2
          fill : Color.BLUE;
          opacity: 0.5
          arcHeight: 10
          arcWidth: 10
        },

VBox的作用是把UI元素在垂直排列,相当于LayoutManager的作用。当点击OK按钮时,我们把对话框隐藏,并且把输入值赋给相关的Star对象。Group的属性中,我们设置了blocksMouse的属性,从而防止鼠标事件传导到下层的图形元素中。


接下来,我们把Main.fx略作修改,在生成Star实例时加入事件处理逻辑,使得星星在点击时可以弹出修改对话框,代码如下:

var tree : ImageView = ImageView {
  x: 80
  y: 0
  image: Image {
           url: "{__DIR__}images/tree.png"
           width: 640
           preserveRatio: true
         }
  onMousePressed:
    function(e:MouseEvent) : Void {

      // do nothing when the dialog is enabled
      if ( dialog.visible ) return;

      if ( e.y < 343 ) {
        currentStar = Star{
                  translateX: e.x
                  translateY: e.y

                  onMousePressed: function(e:MouseEvent) : Void {
                    // do nothing when the dialog is enabled
                    if ( dialog.visible ) return;

                    var self = e.node as Star;
                    dialog.show(self);
                  }
                 } ;

        dialog.show(currentStar);
        insert currentStar after stage.scene.content[currentIndex++];
      }
    }
};


至此,单机版的许愿树就完成了。代码可以在这里下载:许愿树代码。下一步,我们会把这个单机版的改成联网版,这样不同的用户可以通过网页在同一棵许愿树上许愿了。需要做的工作包括把用户的许愿请求发送到网站,然后存入数据库中,再通过许愿树展现出来。服务器端的代码可重用原来PHP版本的代码,或者新写都可以。

评论 (0) 2009年05月17日

JavaFX许愿树程序:Effect功能的应用(1)

分类: JAVAFX技术, 许愿树.
标签: ,

看了同事用写了个许愿树程序(C/S架构的),其中client端的图形界面是由flash来实现。那么如果这个界面用JavaFX来写会怎样呢?我想这一定是很有趣的事情,于是就决定动手写个程序,比较一下。


JavaFX博客:http://www.javafxblogs.com/


首先写个主程序,把画面的Scene做出来。在这个画面中,蓝天背景和白云都需要使用图形效果(effect),在JavaFX中支持了多种图形效果,Lighting,Blur,Shadow等等,可以大大丰富我们的用户界面。我们的程序采用线性渐变(LinearGradient)效果来画蓝天,用高斯模糊(GaussianBlur)效果来画白云,程序如下:

/*
 * Main.fx
 *
 * http://www.javafxblogs.com
 *
 */
package wishtree;

import javafx.scene.effect.GaussianBlur;
import javafx.scene.effect.PerspectiveTransform;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Stop;
import javafx.scene.Scene;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.stage.Stage;

/**
 * @author Henry Zhang
 * JavaFX编程  http://developers.sun.com.cn/blog/henry
 * JavaFX技术交流应用  http://www.javafxblogs.com
 */

var xx = 170;
var yy = 430;

var tree : ImageView = ImageView {
   x: 80
   y: 0
   image: Image {
            url: "{__DIR__}images/tree.png"
            width: 640
            preserveRatio: true
          }
   };

var tree2 =
  Image {
    url: "{__DIR__}images/tree2.png"
    width: 130
    preserveRatio: true
 };

var stage =
  Stage {
    title: "Wish Tree"
    width: 830
    height: 620
    resizable: false

    scene: Scene {
           fill: LinearGradient {
                  startX: 0,
                  startY: 0.0,
                  endX: 0,
                  endY: 1.0
                  proportional: true
                  stops: [
                    Stop { offset: 0.0
                           color: Color.web("#14acf8") },
                    Stop { offset: 1.0
                           color: Color.web("#a4e6f8") }
                         ]
                   }

    content: [
      ImageView {
        x: 50
        y: 280
        image: Image {
                 url: "{__DIR__}images/cloud2.png"
                 preserveRatio: true
                 width: 160
               }
        effect: GaussianBlur { radius: 25 }
      },
      ImageView {
        x: 520
        y: 300
        image: Image {
            url: "{__DIR__}images/cloud2.png"
            preserveRatio: true
            width: 150
            }
        effect:  GaussianBlur { radius: 33 }
      }, // http://www.javafxgame.com  JavaFX Demo Game

      ImageView {
        x: 560
        y: 500
        image: tree2
      },
      ImageView {
        x: 460
        y: 470
        image: tree2
     }, // http://www.compare-review-information.com JavaFX Sample code
      ImageView {
        x: 60
        y: 500
        image: tree2
      },
      ImageView {
        x: 190
        y: 470
        image: tree2
      },

      tree,

      ImageView {
        x: 120
        y: 360
        image: Image {
          url: "{__DIR__}images/sign.png"
          width: 180
          preserveRatio: true
        }
      },
      ImageView {
        x: 20
        y: 60
        image: Image {
          url: "{__DIR__}images/cloud2.png"
          preserveRatio: true
          width: 250
        }
        effect: GaussianBlur { radius: 40 }
      },
      ImageView {
        x: 520
        y: 90
        image: Image {
          url: "{__DIR__}images/cloud2.png"
          preserveRatio: true
          width: 100
        }
        effect:  GaussianBlur { radius: 20}
      },
      ImageView {
        x: 620
        y: 190
        image: Image {
          url: "{__DIR__}images/cloud2.png"
          preserveRatio: true
          width: 180
        }
        effect:  GaussianBlur { radius: 25}
      },
      ImageView {
        x: 600
        y: 380
        image: Image {
          url: "{__DIR__}images/cloud2.png"
          preserveRatio: true
          width: 150
        }
        effect:  GaussianBlur { radius: 33 }
      },
      ImageView {
        x: 0
        y: 490
        image: Image {
          url: "{__DIR__}images/cloud.png"
        }
        effect:  GaussianBlur { radius: 30 }
      },
      Text {
        x:170
        y: 450
        content: "许愿树"
        fill: Color.YELLOW
        font: Font.font ( null, FontWeight.BOLD, 30);
        effect: PerspectiveTransform {
                  ulx: xx    uly: yy
                  urx: xx+80 ury: yy-10
                  llx: xx-2  lly: yy+40
                  lrx: xx+80 lry: yy+38
                }
        }
      ]
    }
}


在程序中,我们把Stage的scene属性用渐变效果填充,可以得到蓝天的效果。在这个渐变效果中,startX和endX的值一样,startY和endY的值不同,因此是沿着Y方向(竖直)的渐变方式。起始颜色为深蓝(”#14acf8″),结束颜色为浅蓝(”#a4e6f8″),在整个Stage的Y方向均匀变化,相关代码如下:

       fill: LinearGradient {
               startX: 0
               startY: 0
               endX: 0
               endY: 1.0
               proportional: true
               stops: [ Stop { offset: 0.0 color: Color.web("#14acf8") },
                        Stop { offset: 1.0 color: Color.web("#a4e6f8") }]
             }

白云的模糊效果是通过高斯算法来获取,例如在下面代码中,ImageView的effect属性:
GaussianBlur{ radius: 40 },radius表示模糊渐变发范围的大小,数值越大,模糊度越大。

      ImageView {
        x: 20
        y: 60
        image: Image {
          url: "{__DIR__}images/cloud2.png"
          preserveRatio: true
          width: 250
        }
        effect:  GaussianBlur { radius: 40 }
      }


由于我们需要显示几朵不同大小的白云,我们需要把白云Image(cloud2.png)作大小调整,上面码中,我们通过改变width的值,并设置preserveRatio=true来保证长宽比例不变,这样就“创造”出不同大小的云块。相关代码段如下:( 本文见:http://www.javafxblogs.com )


  preserveRatio: true
  width: 250


还有要说明的一点是,在木牌子上的“许愿树”3个字,我们采用了维度变换( PerspectiveTransform )的效果,可以把2维的文字变成具有3维感觉的字形,呈梯形状。在PerspectiveTransform需要定义梯形的4个角的坐标,从而把原来长方形的区域映射成变形的字体。相关代码如下:

 Text {
        x:170
        y: 450
        content: "许愿树"
        fill: Color.YELLOW
        font: Font.font ( null, FontWeight.BOLD, 30);
        effect: PerspectiveTransform {
                  ulx: xx    uly: yy
                  urx: xx+80 ury: yy-10
                  llx: xx-2  lly: yy+40
                  lrx: xx+80 lry: yy+38
                }
        }


好了,到这里许愿树程序的界面就完成了,在下一篇文章中会继续介绍如何在树上“悬挂”愿望星星。如果你有JDK 1.5以上的环境(JDK1.6更佳),快点击下图来看看这个JavaFX版本的“愿望树”吧。当你的浏览器首次运行JavaFX程序时,会有一些等待下载的时间。



点击启动WishTree程序

点击启动程序

参见:http://www.javafxblogs.com( 未完待续, 完整代码可在下一篇文章中下载 )

评论 (0) 2009年05月12日

JavaFX 多维数组的使用

分类: JAVAFX技术, JavaFX技巧, JavaFX编程.
标签:

JavaFX的sequence是与java中的数组类似的一种数据结构。sequence使用起来比数组灵活,例如可以支持元素的插入和删除,应该说更像Collection这样的数据结构。和数组明显不同的是,sequence不支持多维结构。因此,当我们需要使用多维数组时,可以在Java语言中定义一个多维数组,然后在JavaFX中调用。


下面是一个包含2维数组的Java程序:

/**
 *
 * @author Henry Zhang
 * JavaFX技术应用 http://www.javafxblogs.com
 *
 */
public class ArrayClass {

  public static int arr [ ][ ] = new int[2][2];

  static {
    for ( int i=0; i<2; i++)
      for ( int j=0; j<2; j++ )
        arr[i][j] = i+j;
  }
}


在JavaFX中我们可以这样调用:

var x = ArrayClass.arr;

for ( i in [0..1] )
  for ( j in [0..1] )
    println("array[{i}][{j}] = {x[i][j]}");


输出结果如下:


array[0][0] = 0
array[0][1] = 1
array[1][0] = 1
array[1][1] = 2


JavaFX 技术应用
JavaFX技术交流应用中心

评论 (0) 2009年05月09日

JavaFX 语法显示工具

分类: JAVAFX技术, JavaFX编程.
标签: , , ,

最近写一些关于JavaFX的文章,发现需要一个语法显示工具以方便读者阅读。其实常用的IDE如NetBeans、Eclipse等都可以对语法的关键字、字符串常量等语法成分进行区别加亮显示。在博客或网页上通常有一类称为Syntax Highlighter的软件,可以是client端或server端的工具,把文章中的程序代码转化为彩色字体显示出来。常见的编程语言如Java,C/C++,C#,VB,JavaScript,Php等都有语法工具的支持,但JavaFX还没有,于是我决定自己做一个。


无论用那种工具,有关JavaFX的关键字列表都是必需的。因此,我花了些时间在google上,终于在openjfx网站上找到了所有关键字(保留字)。接下来就是改写javascript和CSS,最终生成JavaFX语法显示的页面。例如下面的代码范例:

package pacman;
import java.lang.Math;
import pacman.MazeData;
import pacman.PacMan;

/**
 * @author Henry Zhang
 */

public class MoveDecision {

  // x and y of an intended move
  public var x: Number;
  public var y: Number;

  // evaluate if the move is valid and its score if it's valid
  public function evaluate(pacMan:PacMan, isHollow:Boolean): Void {
    if ( x < 1 or y < 1 or y >= MazeData.GRID_SIZE
         or x >= MazeData.GRID_SIZE){
      score = -1;
      return ;
    }
  }
 . . .
}

如果要使用这个Syntax Highlighter,可以先下个SH 1.5.1的版本 ,然后再增加我这几个文件:

shBrushJavaFX.js
SyntaxHighlighter.css


具体的使用说明可以参考该工具的说明文档。



评论 (0) 2009年05月02日

JavaFX 1.1和JavaFX 1.0的兼容性

分类: JAVAFX技术.
标签:

下载了包含JavaFX 1.1.1的NetBeans 6.5.1来安装。我的机器上原来有NetBeans 6.5的IDE,可以开发JavaFX 1.0的应用。在安装NetBeans 6.5.1时,没有升级的选项,而是完全的安装。在装完之后,发现原来的NetBeans 6.5的IDE还在,这样就有两个版本的NetBeans了,感觉有点浪费空间。庆幸的是,在启动新版本后,原来NetBeans 6.5的项目都自动出现在新的IDE中。把原来项目作了编译,没有发现语法错误,可以直接运行。看来源代码级的兼容性还行。

在一些网站上看到说两个版本的JavaFX二进制不兼容,试了一下,果然无法加载。因此JavaFX 1.0的目标码要注意不要使用JavaFX 1.1的Runtime了。

(转载请注明出处:Java,JavaFX技术交流 http://www.javafxblogs.com)

比较了一下两者的JNLP文件,发现只有一行不同:

JavaFX 1.0:
<extension name=”JavaFX Runtime” href=”http://dl.javafx.com/javafx-rt.jnlp”/>

JavaFX 1.1:
<extension name=”JavaFX Runtime” href=”http://dl.javafx.com/1.1/javafx-rt.jnlp”/>

只要原来的目标码指向旧的JavaFX Runtime,应该是可以运行的。一句话,旧的JavaFX代码如果要使用新的JavaFX运行环境,需要源代码重新编译。

评论 (0) 2009年04月15日

JavaFX和Java之间的互操作性

分类: JAVAFX技术.
标签: , ,

JavaFX官方博客上读了一篇文章,是讨论从java代码中调用JavaFX类的方法。现在的情况是,JavaFX可以调用Java的类,基本没有什么限制,而反过来,Java却不可以随便调用JavaFX的类。这点可以从JavaFX项目的编译过程看出原因。以NetBeans为例,Build的过程是先编译Java代码(javac),然后才是JavaFX代码(javafxc),这样一来,java代码不知道有javafx类,而javafx类却可以”看见”java类。搜索一下我们可以发现,很多程序员都在寻找各种从java中调用JavaFX类的方法。有一篇有趣的(英文)文章是介绍如何通过反向工程来分析JavaFX类的结构。就连那篇JavaFX官网上的文章,也采用了非标准的API来实现这一目的,而且也”保证”这种方法肯定会在下一版本中失效。

那么我们到底需不需要java和javafx之间的这种互操作性呢?我觉得这种互操作性是很有必要的。如果两者可以近似于可以混用的程度,从长远上看,JavaFX可以有更大的生命力。试想一下运用MVC的设计模式(Model-View-Controller),我们可以用java和javafx结合在一起开发应用:用java来写”M”和”C”两部分,用javaFX来写”V”部分,这将是非常有趣的一件事情。

目前,有几种”标准”的方法来从Java调用JavaFX。
1) 使用ScirptEngineManager类,的文章提到,我们可以这样做:

package calc;
import java.io.InputStreamReader;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class CalculatorLauncher {
public static void main(String[] args) {
 try {
 ScriptEngineManager manager=new ScriptEngineManager();
 ScriptEngine engine = manager.getEngineByExtension("fx");
 InputStreamReader reader = new InputStreamReader
 (CalculatorLauncher.class.getResourceAsStream("Calculator.fx"));
 engine.eval(reader);
   } catch (ScriptException ex) {
  }
 }
}

但是,这种方法其实没有多大意义,因为它就是象System.exec(”calc”)那样做个系统调用而已。我觉得还不如用System.exec(”javafx Calculator.fx”)更加直接一些。

2) 采用Java Reflection来解析JavaFX的bytecode,得到各个method或属性,然后进行各种调用。原理上这是可行的。但是由于reflection非常复杂,使得实用性大打折扣,同时,代码也没有什么可读性了。

3)第三种方法是定义一个java的interface,然后在JavaFX中实现这个 interface。例如:

public interface JavaInterface
{ ... }

在 MyJavaFXClass.fx中, 可以这样写:

public class MyJavaFXClass extends JavaInterface
{ ... }

在java代码中,只需按照interface来调用JavaFX对象即可。这种方法可以解决大部分互操作性的问题。唯一的麻烦就是必需定义一大堆interface,但是这是我目前位置发现的一种最好的解决形式。
JavaFX现在是刚发布的第一版,所以我们无需对它苛求太多了。不过我还是希望javaFX的设计者在下一版本中认真考虑这个问题。

评论 (1) 2009年01月15日