Третий день
конференции Devoxx 2008 состоял из выступления Дэнни Кауарда и отличной беседы о параллелизме от Брайана Гетца.
Keynote: JavaFX: платформа для многофункциональных интернет-приложений
Дэнни Кауард,
Роберт Брюин должны были сделать ключевую запись, но, к сожалению, у него была деловая встреча. Таким образом, у всех нас есть очень разумная замена динамика, Дэнни Кауард. Он сделал достойную ключевую заметку о стратегии JavaFX. Очевидно, что маркетинговый уклон речи был направлен на то, чтобы догнать Adobe Flex и другие наивные технологии.
Что было действительно хорошо, так это то, что демонстрация FX впервые была показана перед живой аудиторией. Насколько я знаю, в этом году не было никаких взрывов, в отличие от JavaOne. Давайте не будем забывать, что европейские разработчики, большинство из которых, не имеют возможности вылететь в Калифорнию. Образцы JavaFX определенно пошатнулись, особенно когда из браузера на рабочий стол вытащен пример видео с 9-ю коробками высокого разрешения. Браузер был просто закрыт, и медиа проигрывалось без перерыва. Боже мой, я не могу сказать вам, как я был горд и как я был рад видеть клиентскую часть Java внезапно рок-н-ролл. Были слезы на моих глазах, очень немного. О, да, пример того, как поработать, если вы когда-нибудь поймаете этого умного Джоша Мариначчи, называется Video9Box.
BorderLayout Component
Ваш действительно недавно скачал JavaFX 1.0 SDK и, к его большому сожалению, обнаружил, что в комплекте больше нет компонента BorderPanel. Это было для меня головной болью, и я предполагаю, что другие разработчики чувствовали боль, портирующую код от предварительного просмотра до полного выпуска кандидата. Вот моя версия «отсутствующего» BorderLayout.
// XenonBorderPanel.fx, (c) Licence: LGPL: Peter Pilgrim, Created on 08-Dec-2008, 17:31:14
package com.xenonsoft.goliath.game.ui;
import javafx.lang.FX;
import javafx.scene.paint.Color;
import javafx.scene.Node;
import javafx.scene.Group;
import javafx.scene.layout.Container;
import javafx.scene.layout.Resizable;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.ext.swing.SwingButton;
import javafx.ext.swing.SwingComponent;
import java.lang.Math;
/**
* A class to keep a record of the child constraints
*/
protected class ChildConstraint {
public var prefWidth: Number = 0;
public var prefHeight: Number = 0;
public var resizeWidth: Number = 0;
public var resizeHeight: Number = 0;
override function toString(): String {
return "[width={%7.2f width},height={%7.2f height}, resizeWidth={%7.2f resizeWidth},resizeHeight={%7.2f resizeHeight}]"
}
}
/**
* @author Peter Pilgrim
*/
public class XenonBorderPanel extends Container, Resizable {
public var debug = false;
protected function updateChildComponent( newChild:Node, oldChild: Node )
{
if ( newChild != oldChild ) {
if ( oldChild != null ) {
delete oldChild from content;
}
if ( newChild != null ) {
insert newChild into content;
}
}
}
public var top: Node on replace oldValue {
updateChildComponent(top,oldValue);
};
public var left: Node on replace oldValue {
updateChildComponent(left,oldValue);
};
public var right: Node on replace oldValue {
updateChildComponent(right,oldValue);
};
public var bottom: Node on replace oldValue {
updateChildComponent(bottom,oldValue);
};
public var center: Node on replace oldValue {
updateChildComponent(center,oldValue);
};
// Protected variables to this class and subclasses
protected var leftChildConstraint: ChildConstraint;
protected var rightChildConstraint: ChildConstraint;
protected var topChildConstraint: ChildConstraint;
protected var bottomChildConstraint: ChildConstraint;
protected var centerChildConstraint: ChildConstraint;
/** maximum preferred width of top, center and bottom children */
protected var maxPrefWidth: Number;
/** the maximum height of left, center and right children */
protected var middleHeight;
/** full width of left, center and right children summed */
protected var fullWidth;
public var spacing:Number on replace {
impl_requestLayout();
}
init {
impl_layout = doBorderLayout;
}
public function requestLayout():Void {
impl_requestLayout();
}
public function getPreferredSize(node:Node): ChildConstraint {
var constraint = ChildConstraint{ };
if ( node != null ) {
if ( node instanceof SwingComponent) {
// Swing Component do not initialise the shadow FX variables min/max/prefs
var component = (node as SwingComponent).getJComponent();
constraint.prefWidth = component.getPreferredSize().width;
constraint.prefHeight = component.getPreferredSize().height;
constraint.resizeWidth = constraint.prefWidth;
constraint.resizeHeight = constraint.prefHeight;
}
else {
constraint.prefWidth = node.boundsInLocal.width;
constraint.prefHeight = node.boundsInLocal.height;
constraint.resizeWidth = constraint.prefWidth;
constraint.resizeHeight = constraint.prefHeight;
}
if (debug) FX.println("getPreferredSize() ) id={node.id} constraint={constraint}");
}
return constraint;
}
public function setChildBounds( node: Node, x: Number, y: Number, constraint: ChildConstraint): Void
{
if (node instanceof Resizable) {
var resizable = node as Resizable;
resizable.width = constraint.resizeWidth;
resizable.height = constraint.resizeHeight;
}
node.impl_layoutX = x;
node.impl_layoutY = y;
if (debug) FX.println("setChildBounds() id={node.id} x={%7.2f x}, y={%7.2f y}, constraint={constraint}");
}
public function calculatePreferredSize():Void {
leftChildConstraint = getPreferredSize(left);
rightChildConstraint = getPreferredSize(right);
topChildConstraint = getPreferredSize(top);
bottomChildConstraint = getPreferredSize(bottom);
centerChildConstraint = getPreferredSize(center);
// Compute maximum center preferred width
maxPrefWidth = Math.max(topChildConstraint.prefWidth, centerChildConstraint.prefWidth);
maxPrefWidth = Math.max(maxPrefWidth,bottomChildConstraint.prefWidth);
// Computer maximum center preferred height
middleHeight = Math.max(leftChildConstraint.prefHeight, centerChildConstraint.prefHeight);
middleHeight = Math.max(middleHeight, rightChildConstraint.prefHeight);
// Compute the full width of the border layout minimum requirement
fullWidth = 2*spacing + leftChildConstraint.prefWidth + maxPrefWidth + rightChildConstraint.prefWidth;
minimumWidth = fullWidth;
// Compute the minium height of the border layout
minimumHeight = 2*spacing + topChildConstraint.prefHeight + middleHeight + bottomChildConstraint.prefHeight;
preferredWidth = fullWidth;
preferredHeight = 2*spacing + topChildConstraint.prefHeight + middleHeight + bottomChildConstraint.prefHeight;
}
public function doBorderLayout(g:Group):Void {
var x:Number = 0;
var y:Number = 0;
calculatePreferredSize();
// calculate the real size
if ( width > 0.0 and width > preferredWidth and center != null) {
centerChildConstraint.resizeWidth = width - (2 * spacing + leftChildConstraint.prefWidth + rightChildConstraint.prefWidth);
maxPrefWidth = Math.max(topChildConstraint.prefWidth, centerChildConstraint.resizeWidth);
maxPrefWidth = Math.max(maxPrefWidth,bottomChildConstraint.prefWidth);
}
if ( height > 0.0 and height > preferredHeight and center != null) {
centerChildConstraint.resizeHeight = height - (2*spacing + topChildConstraint.prefHeight + bottomChildConstraint.prefHeight);
middleHeight = Math.max(leftChildConstraint.prefHeight, centerChildConstraint.resizeHeight);
middleHeight = Math.max(middleHeight, rightChildConstraint.prefHeight);
}
fullWidth = 2*spacing + leftChildConstraint.prefWidth + maxPrefWidth + rightChildConstraint.prefWidth;
if ( top != null ) {
topChildConstraint.resizeWidth = fullWidth;
setChildBounds(top, x, y, topChildConstraint);
y += topChildConstraint.prefHeight + spacing;
}
x = 0;
if ( left != null ) {
leftChildConstraint.resizeHeight = middleHeight;
setChildBounds(left, x, y, leftChildConstraint);
x += leftChildConstraint.prefWidth + spacing;
}
if ( center != null ) {
setChildBounds(center, x, y, centerChildConstraint);
x += centerChildConstraint.resizeWidth + spacing;
}
if ( right != null ) {
rightChildConstraint.resizeHeight = middleHeight;
setChildBounds(right, x, y, rightChildConstraint);
x += rightChildConstraint.prefHeight + spacing;
}
x = 0;
y += middleHeight + spacing;
if ( bottom != null ) {
bottomChildConstraint.resizeWidth = fullWidth;
setChildBounds(bottom, x, y, bottomChildConstraint);
}
if (debug) {
FX.println("boundsInParent={boundsInParent}");
FX.println("parent.boundsInLocal={parent.boundsInLocal}");
FX.println("parent.boundsInParent={parent.boundsInParent}");
FX.println("parent.boundsInScene={parent.boundsInScene}");
}
}
}
public function run(): Void {
var border: XenonBorderPanel;
var stage: Stage;
var scene: Scene;
stage = Stage {
title: "Test XenonBorderPanel"
width: 600;
height: 800;
onClose: function() {
FX.exit();
}
scene: scene = Scene {
content: border = XenonBorderPanel {
width: bind scene.width
height: bind scene.height
top: SwingButton {
// foreground: Color.AZURE
id: "Top"
text: "Top"
action: function(): Void {
FX.println("Top");
}
}
center: SwingButton {
id: "Center"
text: "Center"
action: function(): Void {
FX.println("Center");
}
}
bottom: SwingButton {
id: "Bottom"
text: "Bottom"
action: function(): Void {
FX.println("Bottom");
}
}
left: SwingButton {
id: "Left"
text: "Left"
action: function(): Void {
FX.println("Left");
}
}
right: SwingButton {
id: "Right"
text: "Right"
action: function(): Void {
FX.println("Right");
}
}
}
}
}
}
// The End
Я не даю никаких гарантий для его полной эксплуатации. Если у вас уже был опыт разработки пользовательских интерфейсов, например, X Windows / OSF Motif, то это должно быть действительно легко. Посмотрите мой другой блог в
четверг Devoxx для некоторых пунктов маркировки на этом BorderLayout.
От параллельного к параллельному
Брайан Гетц
Мне очень понравилась эта презентация, потому что она так четко объясняла концепцию виртуальных машин. Суть идеи Гетца заключалась в том, что мы перемещаемся с нарезанных по времени однопроцессорных машин к многоядерным процессорам, где физически возможна действительно параллельная работа. Эта презентация не имела бы никакого смысла, без диаграммы закона Мура и Гетца, объясняющих, как скорость процессора застоялась и в какой-то «чиповой» линейке фактически уменьшалась год от года, тогда как число ядер в чипе удваивается. У нас уже есть четырехъядерный процессор для настольных компьютеров, а некоторые высокопроизводительные корпоративные профили имеют стоечные системы с 768 ядрами.
Гетц утверждал, что речь идет не об одновременном использовании каждого отдельного ядра на машине для нашей программы, а о том, можем ли мы, как разработчики программного обеспечения, идти в ногу с аппаратными инновациями. Он отметил, что раньше Javac имел менее часто используемые флаги оптимизации, но поскольку JVM Sun Hotspot стала лучше оптимизировать динамический байт-код, оказалось, что компилятор может создавать плохо организованный байт-код. HotSpot реорганизует байт-код с помощью его алгоритмов адаптивного профилирования и регенерации.
Последующая часть разговора Гетца была о предложении JSR 166y, которое включает в себя новые параллельные утилиты, такие как Fork-Join. В целом это был разговор, который нельзя пропустить.
Аль Кода
Visual VM выглядит как идеальный инструмент для профилирования. Это круто!
Кричи ауты!
Джо Вориндекер , спикер и член JAVAWUG.
Фабрицио Джудичи (Fabrizio Giudici) , итальянский блогер, супремос
Алекс Бакли , рад поговорить с вами об отсутствии замыканий в JDK 7 и различных других небольших языковых изменениях.