Статьи

Получение колоды: еще один пользовательский узел JavaFX

В публикации «Собственные узлы» JavaFX: пример графического меню я начал показывать вам, как создавать собственные элементы управления пользовательским интерфейсом в JavaFX. Я также сказал, что категория JFX Custom Nodes была запущена в этом блоге, в котором будут представлены пользовательские узлы, которые вы и я создадим.

Сегодняшний пример показывает простой пользовательский узел с именем DeckNode, который я разработал как способ хранения набора экземпляров Node и одновременного отображения одного из этих узлов. Он используется для дополнения примера графического меню, показывая узел, который относится к данной кнопке меню. Обратите внимание, что концепция очень похожа на Java CardLayout , поэтому я не удивлюсь, если в какой-то момент подобный класс появится в пакете javafx.scene.layout . Просто для ухмылки я предоставил возможность указать время появления для отображаемого узла. Вот снимок экрана примера приложения с одним из узлов в «колоде», отображаемым как заставка: 

Decknodeexample_5  

Одна из целей JavaFX состоит в том, чтобы графические дизайнеры и разработчики могли эффективно сотрудничать в создании великолепно выглядящих приложений. Чтобы продемонстрировать это, Марк Дингман (директор User eXperience в Malden Labs ) создал несколько графических макетов для вымышленного приложения CD, показанного выше. Будущие публикации в блоге превратят эти макеты в функциональные страницы, используя комбинацию элементов управления пользовательского интерфейса из JavaFX SDK и пользовательских узлов, которые мы создадим в этом блоге. Вот пример макетированной страницы в виде графики, которая отображается в результате нажатия кнопки « Воспроизвести» :

Decknodeexample_play

Кстати, Malden Labs под техническим руководством Тома Терио (Tom Theriault) взяла на себя обязательство использовать JavaFX для некоторых довольно интересных систем. В любом случае, если вы хотите опробовать сегодняшний пример, нажмите на эту ссылку Java Web Start, помня, что вам понадобится как минимум JRE 5. Кроме того, установка Java SE 6 update 10 ускорит развертывание.

Webstartsmall2

Вот код для класса DeckNode , содержащийся в файле с именем DeckNode.fx :

/*
* DeckNode.fx -
* A node that shows a deck of nodes one at a time.
*
* Developed 2008 by James L. Weaver (jim.weaver at lat-inc.com)
* to demonstrate how to create custom nodes in JavaFX
*/

package com.javafxpert.custom_node;

import javafx.animation.*;
import javafx.lang.*;
import javafx.scene.*;

/**
* A node that shows a deck of nodes one at a time. When the
* visibleNodeId attribute is assigned a value, the Node whose
* id is the same as the name becomes visible. Note that the
* the id attribute of each Node must be assigned a unique name.
* This class also has an attribute in which a fade-in duration
* may be specified.
*/
public class DeckNode extends CustomNode {
/**
* A sequence that contains the Node instances in this "deck"
*/
public attribute content:Node[];

/**
* The id of the node that is to be visible
*/
public attribute visibleNodeId on replace {
var nodes = for (node in content where node.id == visibleNodeId) node;
visibleNodeRef = if (sizeof nodes > 0) nodes[0] else null;
fadeTimeline.start();
}

/**
* The amount of time to fade-in the new Node
*/
public attribute fadeInDur:Duration = 1ms;

/**
* This attribute is interpolated by a Timeline, and the opacity
* attribute of this DeckNode class is bound to it. This helps
* enable the fade-in effect.
*/
private attribute opa:Number;

/**
* Override the opacity attribute so that it can be bound to the
* opa attribute that is interpolated by a Timeline
*/
override attribute opacity = bind opa;

/**
* A Timeline to control the fade-in behavior
*/
private attribute fadeTimeline =
Timeline {
keyFrames: [
KeyFrame {
time: bind fadeInDur
values: [
opa => 1.0 tween Interpolator.LINEAR,
]
}
]
};

/**
* A reference to the Node in the Node instances that is visible
*/
private attribute visibleNodeRef:Node;

/**
* Create the Node
*/
public function create():Node {
Group {
content: bind visibleNodeRef
};
}
}

Ниже показан основной скрипт для этой программы в файле с именем DeckNodeExampleMain.fx :

/*
* DeckNodeExampleMain.fx -
* An example of using the DeckNode custom node. It also demostrates
* the MenuNode and ButtonNode custom nodes
*
* Developed 2008 by James L. Weaver (jim.weaver at lat-inc.com)
* to demonstrate how to create custom nodes in JavaFX
*/
package com.javafxpert.deck_node_example.ui;

import javafx.application.*;
import javafx.scene.*;
import javafx.scene.geometry.*;
import javafx.scene.image.*;
import javafx.scene.layout.*;
import javafx.scene.paint.*;
import javafx.scene.text.*;
import javafx.scene.transform.*;
import java.lang.System;
import com.javafxpert.custom_node.*;

var deckRef:DeckNode;

Frame {
var stageRef:Stage;
var menuRef:MenuNode;
title: "DeckNode Example"
width: 500
height: 400
visible: true
stage:
stageRef = Stage {
fill: Color.BLACK
content: [
deckRef = DeckNode {
fadeInDur: 700ms
content: [
Group {
var vboxRef:VBox;
var splashFont =
Font {
name: "Sans serif"
style: FontStyle.BOLD
size: 12
};
id: "Splash"
content: [
ImageView {
image:
Image {
url: "{__DIR__}images/splashpage.png"
}
},
vboxRef = VBox {
translateX: bind stageRef.width - vboxRef.getWidth() - 10
translateY: 215
spacing: 1
content: [
Text {
content: "A Fictitious Audio Application that Demonstrates"
fill: Color.WHITE
font: splashFont
},
Text {
content: "Creating JavaFX Custom Nodes"
fill: Color.WHITE
font: splashFont
},
Text {
content: "Application Developer: Jim Weaver"
fill: Color.WHITE
font: splashFont
},
Text {
content: "Graphics Designer: Mark Dingman"
fill: Color.WHITE
font: splashFont
},
]
}
]
},
Group {
id: "Play"
content: [
ImageView {
image:
Image {
url: "{__DIR__}images/playlist.png"
}
}
]
},
Group {
id: "Burn"
content: [
ImageView {
image:
Image {
url: "{__DIR__}images/burning.png"
}
}
]
},
Group {
id: "Config"
content: [
ImageView {
image:
Image {
url: "{__DIR__}images/config.png"
}
}
]
},
Group {
id: "Help"
content: [
ImageView {
image:
Image {
url: "{__DIR__}images/help.png"
}
}
]
}
]
},
menuRef = MenuNode {
translateX: bind stageRef.width / 2 - menuRef.getWidth() / 2
translateY: bind stageRef.height - menuRef.getHeight()
buttons: [
ButtonNode {
title: "Play"
imageURL: "{__DIR__}icons/play.png"
action:
function():Void {
deckRef.visibleNodeId = "Play";
}
},
ButtonNode {
title: "Burn"
imageURL: "{__DIR__}icons/burn.png"
action:
function():Void {
deckRef.visibleNodeId = "Burn";
}
},
ButtonNode {
title: "Config"
imageURL: "{__DIR__}icons/config.png"
action:
function():Void {
deckRef.visibleNodeId = "Config";
}
},
ButtonNode {
title: "Help"
imageURL: "{__DIR__}icons/help.png"
action:
function():Void {
deckRef.visibleNodeId = "Help";
}
},
]
}
]
}
}

deckRef.visibleNodeId = "Splash";

 

Обратите внимание, что последняя строка приведенного выше списка — это то, что заставляет узел, который мы назвали «Всплеск», отображать при запуске приложения. 

Код для других пользовательских узлов, используемых в этой программе ( ButtonNode.fx и MenuNode.fx ), содержится в публикации « Собственные узлы» JavaFX: пример графического меню , поэтому вы можете посетить этот пост. В какой-то момент я добавлю эти пользовательские узлы в файл JAR, если разработчики найдут их полезными. Как всегда, пожалуйста, оставьте комментарий, если у вас есть какие-либо вопросы о комментариях!

Спасибо,
Джим Уивер