Один из моих любимых набросков «Субботний вечер в прямом эфире» — « Больше ковбелла», в котором персонаж Кристофера Уокена постоянно просит «больше колокольчика» во время записи. Сегодняшний пример охватывает некоторые из простых, но мощных концепций JavaFX в контексте воображаемого приложения для iPhone, которое позволяет выбирать музыкальный жанр и управлять громкостью. Конечно, «Cowbell Metal», сокращенно до «Cowbell», является одним из доступных жанров ? Нажмите на скриншот ниже, чтобы запустить приложение, а затем я покажу вам код, стоящий за ним.
Поведение приложения и код за ним
Когда вы играете с приложением, обратите внимание, что настройка ползунка громкости изменяет отображаемый связанный уровень децибел (дБ). Кроме того, установка флажка « Отключение звука» отключает ползунок, а выбор различных жанров изменяет ползунок громкости. Это поведение обеспечивается концепциями, которые вы увидите в приведенном ниже коде, такими как привязка к классу, содержащему модель, триггеры замены и последовательности (думаю, массивы).
Вот основная программа, которая содержит декларативный скрипт, который выражает пользовательский интерфейс:
/*
* AudioConfigMain.fx - A JavaFX Script example program that demonstrates
* "the way of JavaFX" (binding to model classes, triggers, sequences, and
* declaratively expressed, node-centric UIs). Note: Because this example
* covers beginning JavaFX concepts, it is more verbose than necessary.
*
* Developed 2008 by James L. Weaver jim.weaver [at] javafxpert.com
* as a JavaFX Script SDK 1.0 example for the Pro JavaFX book.
*/
package projavafx.audioconfig.ui;
import javafx.ext.swing.*;
import javafx.stage.Stage;
import javafx.scene.*;
import javafx.scene.paint.*;
import javafx.scene.shape.*;
import javafx.scene.text.*;
import javafx.scene.transform.*;
import projavafx.audioconfig.model.AudioConfigModel;
Stage {
var acModel = AudioConfigModel {
selectedDecibels: 35
}
title: "Audio Configuration"
scene: Scene {
content: [
Rectangle {
x: 0
y: 0
width: 320
height: 45
fill: LinearGradient {
startX: 0.0
startY: 0.0
endX: 0.0
endY: 1.0
stops: [
Stop {
color: Color.web("0xAEBBCC")
offset: 0.0
},
Stop {
color: Color.web("0x6D84A3")
offset: 1.0
},
]
}
},
Text {
translateX: 65
translateY: 12
textOrigin: TextOrigin.TOP
fill: Color.WHITE
content: "Audio Configuration"
font: Font {
name: "Arial Bold"
size: 20
}
},
Rectangle {
x: 0
y: 43
width: 320
height: 300
fill: Color.rgb(199, 206, 213)
},
Rectangle {
x: 9
y: 54
width: 300
height: 130
arcWidth: 20
arcHeight: 20
fill: Color.color(1.0, 1.0, 1.0)
stroke: Color.color(0.66, 0.67, 0.69)
},
Text {
translateX: 18
translateY: 69
textOrigin: TextOrigin.TOP
fill: Color.web("0x131021")
content: bind "{acModel.selectedDecibels} dB"
font: Font {
name: "Arial Bold"
size: 18
}
},
SwingSlider {
translateX: 120
translateY: 69
width: 175
enabled: bind not acModel.muting
minimum: bind acModel.minDecibels
maximum: bind acModel.maxDecibels
value: bind acModel.selectedDecibels with inverse
},
Line {
startX: 9
startY: 97
endX: 309
endY: 97
stroke: Color.color(0.66, 0.67, 0.69)
},
Text {
translateX: 18
translateY: 113
textOrigin: TextOrigin.TOP
fill: Color.web("0x131021")
content: "Muting"
font: Font {
name: "Arial Bold"
size: 18
}
},
SwingCheckBox {
translateX: 280
translateY: 113
selected: bind acModel.muting with inverse
},
Line {
startX: 9
startY: 141
endX: 309
endY: 141
stroke: Color.color(0.66, 0.67, 0.69)
},
Text {
translateX: 18
translateY: 157
textOrigin: TextOrigin.TOP
fill: Color.web("0x131021")
content: "Genre"
font: Font {
name: "Arial Bold"
size: 18
}
},
SwingComboBox {
translateX: 204
translateY: 148
width: 93
items: bind for (genre in acModel.genres) {
SwingComboBoxItem {
text: genre
}
}
selectedIndex: bind acModel.selectedGenreIndex with inverse
}
]
}
}
Обратите внимание, как оператор связывания используется в разных местах, чтобы пользовательский интерфейс отображал состояние модели. В нескольких местах связывание с инверсией используется для обеспечения двусторонней синхронизации пользовательского интерфейса и класса модели. Теперь взглянем на класс модели и, в частности, триггер на замену, который вызывается, когда пользователь выбирает жанр:
/*
* AudioConfigModel.fx - The model class behind a JavaFX Script example
* program that demonstrates "the way of JavaFX" (binding to model classes,
* triggers, sequences, and declaratively expressed, node-centric UIs).
*
* Developed 2008 by James L. Weaver jim.weaver [at] javafxpert.com
* as a JavaFX Script SDK 1.0 example for the Pro JavaFX book.
*/
package projavafx.audioconfig.model;
/**
* The model class that the AudioConfigMain.fx script uses
*/
public class AudioConfigModel {
/**
* The minimum audio volume in decibels
*/
public var minDecibels:Integer = 0;
/**
* The maximum audio volume in decibels
*/
public var maxDecibels:Integer = 160;
/**
* The selected audio volume in decibels
*/
public var selectedDecibels:Integer = 0;
/**
* Indicates whether audio is muted
*/
public var muting:Boolean = false;
/**
* List of some musical genres
*/
public var genres = [
"Chamber",
"Country",
"Cowbell",
"Metal",
"Polka",
"Rock"
];
/**
* Index of the selected genre
*/
public var selectedGenreIndex:Integer = 0 on replace {
if (genres[selectedGenreIndex] == "Chamber") {
selectedDecibels = 80;
}
else if (genres[selectedGenreIndex] == "Country") {
selectedDecibels = 100;
}
else if (genres[selectedGenreIndex] == "Cowbell") {
selectedDecibels = 150;
}
else if (genres[selectedGenreIndex] == "Metal") {
selectedDecibels = 140;
}
else if (genres[selectedGenreIndex] == "Polka") {
selectedDecibels = 120;
}
else if (genres[selectedGenreIndex] == "Rock") {
selectedDecibels = 130;
}
};
}
Как всегда, пожалуйста, оставьте комментарий, если у вас есть какие-либо вопросы!
Узнайте JavaFX в Стокгольме, Швеция, в январе 2009 года
Я буду говорить о JavaFX на конференции Jfokus 2009 в январе. Находясь в этом районе, я также проведу двухдневный общедоступный класс JavaFX в Стокгольме 29 и 30 января 2009 года под названием «Богатая разработка интернет-приложений с использованием JavaFX» .
С уважением,
Джим Уивер
JavaFXpert.com