Feeds:
Posts
Comments

Archive for the ‘JavaFX’ Category

JavaOne is over! But before we cover the last day, back to day 3.

I’m still marveling about the Treasure Island party. Terri Nunn of Berlin said that “Oracle gives the best f*****g corporate parties!” and she’s probably right. I have never been to a corporate party on this scale, well, except for last year’s Oracle party. In fact, I’ve never been to a party of any kind that big, ever.

There were almost too many bands. I would have liked to have seen the English Beat but they played early and by the time we got onto the island the set was almost over. We heard some of Berlin but we were trying to get food at the time. I caught most of Don Henley’s set, which was great. Like all of us, he’s getting older, but he seems to be taking care of his voice. He sounded pretty good. I popped over to see the Black Eyed Peas for a little bit, but I just don’t get them. I’m really out of touch. When people started talking about Fergie I thought “What does the Duchess of York have to do with this?”

* * *

Looks like highlights videos from the keynotes are up on the web now. Check out http://medianetwork.oracle.com and click on News and Events and then choose JavaOne or Oracle OpenWorld.

* * *

We had another fabulous lunch at Henry’s Hunan!

* * *

Today’s sessions included Hardcore CSS with Rich Bair and Jasper Potts. I knew most of this stuff since I did my share of work on it in JavaFX, and I wrote a bunch of the manual, but I wanted to be there and show support for the team. The power of using CSS to control region backgrounds and borders and shapes is really amazing and I give Rich and Jasper a lot of credit for thinking it up and implementing most of it.

I also attended Rich GUI Testing Made Easy given by my colleague Alex Ruiz and Yvonne Price. The talk was basically about using the FEST to test Swing GUIs. The code was a bit small to read but I picked up on a few key concepts.

The last session I attended was Concurrency Grab Bag by Sanjin Lee of eBay. This was a discussion of various concurrency issues and “gotchas” they’ve run into at eBay. I was familiar with most of the material already but it was good to see a treatment of the material rooted in practice, as compared to the somewhat more academic approach from people like Goetz and Lea. I’d have thought that the conference was winding down at that point, but the session was packed and there were lots of questions. In fact, I think this was a repeat performance of the talk. The earlier one was probably so popular that they had to schedule a repeat session. [Update: slides here.]

This session was in fact in the last session slot of the conference. The audio tech put on Scott McKenzie’s San Francisco (Be Sure to Wear Flowers in Your Hair) as people were leaving the room, which I thought was a nice touch.

* * *

I usually find the end of a conference a bit melancholy, as people drift away, take off early to catch their planes, leaving the final sessions sparsely attended and the conference center lonely and empty. This was a bit different. The conference hotels were as crowded as ever, buzzing with new batches of tourists, business travelers, airline staffs, etc. checking in.

Workers were scurrying about tearing down all the JavaOne and OpenWorld paraphernalia. A few JavaOne attendees were hanging around. It was pretty easy to spot them: developers’ sense of fashion contrasted sharply with the snappy Japanese airline crew uniforms and with the trendy European tourists. Oh, the laptops helped give it away too. 🙂 I wandered around a bit longer but it was clear that there was nothing left for me to do but go home.

On that note it’s time for me to recap of my impressions of the conference.

This JavaOne was unique in many ways, not only because it was the first run by Oracle, but because it was the first not in Moscone. Sure, there were activities and events and keynotes at Moscone, but those were primarily OpenWorld events. JavaOne itself took place in two conference hotels, the Hilton Union Square and the Parc 55. (The third conference hotel, the Nikko, seemed dedicated to Oracle Develop sessions.)

I have to say that I didn’t like having the conference in the hotels. Even within the same hotel, the rooms were fairly spread out. Then there was the matter of getting between the hotels. It seemed like you were forever going through the back door to get in. At the Hilton, you either walked in through the garage or you used the employee entrance! (But the latter made it easy to punch your Hilton employee time card on the way to the next session.) The hallways were narrow and between sessions they were quite crowded with people trying to get from one area to another.

The rooms were all too small and so they filled up quickly — too quickly. As an Oracle employee I couldn’t reserve places in the session rooms. This was irritating but understandable — paid conference attendees should indeed have priority. But I also heard that even paid attendees had trouble getting in. Some popular sessions were filled even before the conference started.

Since the conference was spread out, there were no obvious gathering places like there were in Moscone, like the movie/game area upstairs in Moscone South or the beanbag area downstairs in Moscone North. If you hung out in one of those places for a few minutes, you’d be guaranteed to see someone you knew and hadn’t seen since last year’s conference. This kind of networking is what conferences are all about! In the hotel setup, the foot traffic all led through various rabbit warrens of corridors, so there was no central gathering place or main artery of traffic. Things just seemed all scattered and disorganized and it was really hard to find people. There were people I knew were at the conference, but I just never ran into them. That didn’t seem to happen before.

It’s not at all clear to me that there is any benefit of combining OpenWorld and Oracle Develop with JavaOne. (With the possible exception of JavaOne attendees getting to attend the Treasure Island event.) I don’t know if there was any cross-pollination. The only JavaOne things at Moscone were a couple keynotes; everything else there was OpenWorld stuff the suits attended. Also, as I mentioned, Oracle Develop seemed segregated in the Nikko. The only effect that combining the conferences had was to make things more crowded and expensive and to push JavaOne out of Moscone.

The technical program seemed a little flat as well this year. Maybe this was because there were some talks I wasn’t able to attend because they were full. It also might have been because of Google’s last-minute pullout. I heard they had 13 sesssions and 6 BOFs. But I also think it’s because of a development slowdown caused by the waning days of Sun and the transition to Oracle. It took a lot of energy to get through that, and a lot of people left before and during the transition, so that took away from developing stuff that could have been presented at the conference. A lot of plans and roadmaps were announced, and there seems to be renewed momentum around Java development at Oracle, so let’s hope this will lead to more material for next year’s program.

Read Full Post »

JavaOne 2010 day 3 update

One thing I forgot to mention from day 2: the technical general session with Mark Reinhold and others. I was mainly interested in Reinhold’s stuff. He gave a brief overview of JDK7 and JDK8 roadmaps, including some interesting background on closures (the Lambda project) and default methods. Unfortunately this stuff won’t be in until JDK8 (2012). It’s notable how much closures have evolved from the CICE and BGGA proposals that have kicked around for a couple years, though the current Lambda proposal bears some resemblance to CICE to my eye.

* * *

I attended a Java Desktop lunch at Anzu. There were about 30 people there, including lots of FX folks, but also lots of others, including a special surprise appearance from James Gosling! James isn’t officially at the conference but is hanging around and meeting with lots of people. After his departure from Oracle he’s turned into a bit of a rabble rouser. See his eWeek interview for example.

* * *

Stephen Chin and Dean Iverson had a BOF on JFXtras. Historically the role of the JFXtras project has been to fill in the gaps and to add “extra” features that aren’t in the core JavaFX platform. With the transition of JavaFX from JavaFX Script to Java as the main API and implementation language, the role of the JFXtras project will change. Specifically, Steve announced an initiative to continue the development and evolution of the JavaFX Script language in open source, and eventually to rehost it on top of the new Java-based JavaFX APIs when they are delivered. Steve already has a grab bag of features he wants to add to the language, such as a map type and the ability to bind over a key in a map (even if it’s not yet present in the map). Steve’s provisional name for the project is “Visage.” He doesn’t have a site up yet for this effort, but keep an eye on his blog. I’ll update this post with links when they become available.

* * *

Kevin Rushforth and Jim Graham gave a talk on JavaFX Graphics. They gave an overview of the scene graph along with some information about JavaFX 3D capabilities that will be in the next release. They had some cool demos too, including a few snippets and behind-the-scenes information about the FX demo that was shown during Thomas Kurian’s JavaOne keynote. Kevin and Jim also showed some other, more pedestrian demos, some of which were based on my Flood Game sample program. Thanks for the shout-out, Kevin!

* * *

Of course, no JavaOne day 3 update would be complete without a description of the Oracle Appreciation party (“Rockopolis”) on Treasure Island. This is really part of Oracle OpenWorld, and one of the advantages of JavaOne being combined with OpenWorld is that JavaOne attendees get to partake of the Big Event. This year the top acts included Don Henley, the Black-Eyed Peas, the English Beat, and Steve Miller.

Now, officially this event is for Oracle customers and partners, not employees. The employee speaker badges don’t include tickets for the event, but it turned out that there were some extra tickets available so most of my team was able to go. In addition, a lot of regular (non-employee) conference attendees didn’t actually want to go, so that made more tickets available. Finally, through some … connections … several of us were able to score VIP tickets, which promised better food, shorter lines, and special reserved areas near the stages. Fortunately, I remembered to bring earplugs!

There was even a black market for the tickets. I heard that they were going on Craigslist for $100. Not too surprising really, since the ticket included free food and drinks, carnival games and rides, and six A-list musical groups. (No, I didn’t participate in the black market!)

Really the Treasure Island event was quite a spectacle. As I described last year, it was pretty much like an entire county fair that had been set up for one day. Truly amazing.

Read Full Post »

JavaOne 2010 days 1 & 2

I’m currently attending JavaOne, the first JavaOne hosted and sponsored by Oracle. So far the biggest change is that technical sessions start at 8:00am. I know, was speaking at one. 🙂 I had to get up at 4:45am to get into San Francisco on time. But, who am I to complain?

Actually, the real big news so far is the demise of JavaFX Script. The reviews from the blogosphere/twittersphere are mixed. Some people are loving it. Indeed, one of the comments I received on my JavaFX Script talk from last year’s JavaOne was “It’s beyond me why anyone would create such a language.” People such as this commenter are perhaps glad to see JavaFX Script go away.

On the other hand, there is also some disappointment, some criticism, some mourning, and even some denial. But this is the price — or perhaps the cost — of progress. (But see also below.)

There’s been some misinformation floating around the twittersphere about “JavaFX is dead” and some such. This is decidedly not the case. JavaFX Script is indeed on its way out (though existing programs will still run for a while, and you can still develop new ones, should you decide to do such a thing) but JavaFX itself is most definitely alive and will continue develop. Here’s a clarifying statement from the JavaFX Architect, Richard Bair (what Mr. Bair meant to say was…) about the changes coming in JavaFX 2.0:

http://fxexperience.com/2010/09/javafx-2-0/

Also, the official JavaFX roadmap statement is here:

http://javafx.com/roadmap

* * *

The talk I gave this morning (along with my colleague, Paru Somashekar) was on JavaFX UI Controls. Originally we were going to present a lot more code examples, but with the move away from JavaFX Script we had to retool the talk. In the end we showed a survey of the controls and some demos of the controls in action but relatively little code. We did do a small comparison of JavaFX Script to a new, provisional Java-based API for JavaFX. Overall the talk was well attended (better than I expected for an 8am tech session!) and I thought it was a success.

One questioner at the session criticized the dropping of support for JavaFX Script and in particular its declarative syntax. He was very polite, apologizing for making a statement instead of a question and also for shooting the messenger. I didn’t get a chance to talk to the gentleman, but I wanted to say that I wasn’t offended by his comment. On the JavaFX team we knew that dropping JavaFX Script would be painful for some. Anyone who’s affected needs to speak out about it. I don’t think the decision will be reversed but it might be possible for those impact to get some help with migration.

* * *

We had a great lunch at Henry’s Hunan. I’m still full. Oh, well there was also that big cookie I had during the afternoon break.

* * *

It’s a bit odd not being in Moscone. Unlike I think all prior JavaOnes, this year JavaOne is in a trio of hotels: the SF Hilton, Hotel Nikko, and the Parc 55. The hotel meeting rooms are smaller, so they fill up sooner, and in general Oracle employees (such as myself) can only get in if there’s space available — which there often is not. As a result I’ve been unable to get into a few sessions that I wanted to attend. Oh well, I’ll have to pick up the presentation slides later on. But, who am I to complain?

* * *

This evening I’m attending a few BOFs: on Jigsaw, OpenJDK, and on Visual Design with CSS. After that I’ll head home, attempting not to fall asleep during the drive, and fall into bed at the end of a very long day.

Read Full Post »

Anyone who’s used any of the JavaFX UI Controls (in javafx.scene.control) has probably noticed that most of the controls don’t have any listeners. Why is this? Without listeners, how can you detect when the user has changed the state of the control?

The first, easy answer is that you can often avoid the need for listeners by binding to the state of the control. Let’s consider a simple CheckBox example. Suppose you wanted to change the visibility of something based on whether the checkbox is selected. In Swing, you’d do something like adding an item listener to the checkbox, and when it got called, you’d look in the event to see which checkbox got changed and whether it was selected or deselected, and then modify the visibility of your component (or whatever) accordingly.

In JavaFX, you’d do something kind of the opposite. Instead of having a listener get called that “pushes” the side effect of the checkbox state change into some target object, you’d instead bind the “visible” state of the target object to the selected state of the checkbox. Here’s how:

var cb:CheckBox;

Stage {
    scene: Scene {
        content: [
            HBox {
                spacing: 10
                padding: Insets { top: 10 right: 10 bottom: 10 left: 10 }
                content: [
                    cb = CheckBox {
                        text: "Check Me!"
                        selected: true
                    }
                    Label {
                        text: "sample label text"
                        visible: bind cb.selected
                    }
                ]
            }
        ]
    }
}

The bind-expression makes sure that the Label’s “visible” variable will always track the state of the CheckBox, and so the Label will appear and disappear as you check and uncheck the CheckBox. Simple.

This is all well and good if your situation calls for some state to be updated when the CheckBox changes state, and the update computation is something simple enough to be written using a bind-expression. But what if you have some kind of process that you need to perform, say, one that requires having some function called. Wouldn’t you need a listener? Yes, but it’s fairly simple to construct your own.

Like many languages, JavaFX Script has block structure, where any code block “{ … }” can declare local variables that are scoped to that block (i.e., they are not visible outside that block). It’s also legal to declare local variables within the “{ … }” of an object literal, even though it’s a syntactically different construct from a code block. What’s not very well known is that it’s also possible to override variables of the class you’re instantiating. By itself, overriding a variable doesn’t let you do much except to override the initial value of a variable. Since this is already within an object literal, you’re providing initial values already, so what’s the point? Overriding useful because it provides a point of (re)declaration of the variable where you can supply an “on replace” trigger. This is code that gets called whenever the value is changed … just like a listener!

Let’s try this out. Instead of just toggling the visibility of the label, let’s toggle a timeline that rotates it:

Stage {
    scene: Scene {
        content: [
            HBox {
                spacing: 10
                padding: Insets { top: 10 right: 10 bottom: 10 left: 10 }
                content: [
                    CheckBox {
                        text: "Check Me!"
                        override var selected on replace {
                            if (selected) tl.play() else tl.pause();
                        }
                    }
                    label = Label {
                        text: "sample label text"
                    }
                ]
            }
        ]
    }
}

var tl = Timeline {
    repeatCount: Timeline.INDEFINITE
    keyFrames: [
        at (2s) {
            label.rotate => 360
        }
    ]
}

(See Footnote 1.)

This is a little non-obvious but it works quite well.

Now, there’s a problem with this technique. In order to override a variable, that variable must be public. Let’s say that we wanted to create a ListView and create the equivalent of a listener that gets called whenever the selection changes. We’ll just do this, right?

ListView {
    items: [ "One", "Two", "Three" ]
    override var selectedItem on replace {
        println("selection is now {selectedItem}"); // ERROR
    }
}

Oh no, this doesn’t work! The “selectedItem” variable isn’t public, it’s public-read. (Why? See Footnote 2.) This is a bit of a pain to work around. We cannot override public-read variables, but we can still bind to them. This means we can use the foreign trigger idiom to create a new variable that tracks the value of the variable we’re interested in, and then add a trigger to our new variable. Here’s how:

var list = ListView {
    items: [ "One", "Two", "Three" ]
    var sel = bind list.selectedItem on replace {
        println("selection is now {sel}");
    }
}

This is fairly cumbersome, since we have to create and name a new local variable and hang our “listener” code there, and we have to make sure the ListView is accessible to it via a named variable. This is probably about as much boilerplate as adding a listener using an anonymous class in Java. Still, we’re used to much more concise syntax in JavaFX Script. It’d probably be nicer to have a function variable such as “onSelectionChanged” whose value is a function that gets called when the ListView’s selection changes. Adding callback APIs like this hasn’t been a very high priority up until now, though, since it’s possible (if inconvenient) to use the controls without them using the bind or override-and-bind-with-trigger techniques. We’re definitely considering adding them, though, since it makes the API much more approachable.

Footnote 1. This is a bit sloppy. Those of you who compile this code will note that the “label.rotate => 360” line gets a compiler warning to the effect that “label is not a constant but will be treated as such”. This means that, at the time the KeyFrame object of the Timeline is created, a snapshot of the current value of “label” is taken and stored within the KeyFrame. This means that “label” needs to have been initialized to the right value before the Timeline and KeyFrame are created. In fact, I first created the Timeline above the Stage/Scene/HBox hierarchy, and the animation didn’t work! Moving it below makes it work, but the compiler still issues the warning.

Footnote 2. Why are selectedItem and selectedIndex public-read instead of public? If they were both public, the implementation would have to have triggers to handle the cases where the application wrote to them. Each trigger would have to write to the other variable, which in turn would invoke its trigger. This doesn’t cause infinite recursion, though, since the trigger won’t fire if the variable is set to a value equal to its current value. But it’s still a pain. Oh, another problem is, what if the application set selectedItem to an object that’s not a member of the ListView? The trigger would have to set the variable back to a legal value, and add a flag to avoid recursive trigger invocation as noted here. (Also note that Toggle.selected and ToggleGroup.selectedToggle are both public and have this problem. Trust me, dealing with this kind of situation is a real pain.)

Read Full Post »

We’ve just updated the JavaFX API documentation. The main documentation is here:

http://java.sun.com/javafx/1.3/docs/api/

Probably the most significant change is the addition of a new CSS Reference Guide. This document is linked from the javafx.scene package docs and from the Scene and Node class docs, but it’s actually a bit hard to find. For your convenience, the direct link is here:

http://java.sun.com/javafx/1.3/docs/api/javafx.scene/doc-files/cssref.html

You’ll probably want to bookmark it. A lot of the information is out there already, having been derived from the examples in the caspian.css file (which is included in one of the jar files in the SDK). The styles in caspian.css show a lot of what you can do with CSS in JavaFX. However, even caspian.css doesn’t show everything that you can do with CSS. The CSS Reference Guide is comprehensive. For instance, check out all of what you can do with a Region using CSS. Or, take a look at all the properties of charts you can customize. There’s really a lot in there.

I’ll post some examples later. Meanwhile, dive in and enjoy!

Read Full Post »

Applying Styles to Scenes

There’s been some confusion about styling scenes and what it means to have a CSS rule that uses “.scene” as the selector. For example, the caspian.css file that’s included in JavaFX, the JavaFX tutorial Applying CSS to UI Controls, and Dean Iverson’s article Into the Background all include style rules that look something like this:

.scene {
    -fx-background: cornflowerblue;
    /* ... */
}

There have been a bunch of questions about this, for example in the forum threads here and here, and in comments at the bottom of the Applying CSS to UI Controls tutorial. People are tinkering with this rule and it’s not working the way they expect. The pieces of this part of the system fit together in funny ways, so I certainly can see why there’s lots of confusion. Let’s dive in.

First, let’s create a simple scene:

Stage {
    scene: Scene {
        width: 150
        height: 150
        stylesheets: "{__DIR__}styles.css"
        content: [
            Rectangle { x: 50 y: 50 width: 50 height: 50 }
        ]
    }
}

Now let’s try to style the scene. The various examples use the -fx-background and -fx-fill properties. Which one is correct? Let’s try both, using different colors so that we can tell which one took effect. Place the following into the styles.css file:

.scene {
    -fx-background: cornflowerblue;
    -fx-fill: orchid;
}

What happens? Basically, nothing. We get a black rectangle on a white background, just as if we hadn’t specified any CSS at all.

Well, that sucks.

The main problem is that Scene objects don’t have any CSS-settable attributes. There are a couple things on Scene that seem like they ought to be settable from CSS, such as the fill and cursor variables. But they don’t work, and that’s a bug. See JIRA issue RT-8653. If you want to set the background color of a Scene, you have to use a rectangle or ScrollView and style that instead. See Dean Iverson’s article Into the Background which covers this pretty well.

If a style rule for “.scene” doesn’t apply any properties to the Scene, what does it do? Let’s first examine an assumption here, which is that a style rule with “.scene” actually applies to Scene objects. This is a reasonable assumption because we’ve set things up for the controls so that “.button” styles apply to Button, “.slider” styles apply to Slider, and so forth. This convention that applies to the controls, but it doesn’t apply everywhere. You can’t, for instance, declare a style rule for “.rectangle” and expect it to apply to all Rectangle objects. Try it! It doesn’t work. To style a Rectangle, you have to give it a styleClass value and then use that in your CSS. For example:

// Main.fx
Rectangle { styleClass: "myrect" ... }

// styles.css
.myrect { -fx-fill: dodgerblue; }

gives the following result:

Now back to Scene. If the “.scene” styles don’t apply to Scene objects, what do they apply to?

Let’s examine a little puzzle in the scene graph API. The scene graph is a tree of nodes, and all trees have a root. Every Node has a parent variable, which is of type Parent (a subclass of Node). If you walk up the scene graph following the parent variable, you’ll eventually get to the root. That’s the Scene, right? But it can’t be, because a Scene isn’t a Node. What is the root Node then? Let’s find out.

var rect:Rectangle;
...
Stage {
    scene: Scene {
        ...
        content: [
            rect = Rectangle {
                styleClass: "myrect"
                x: 50 y: 50 width: 50 height: 50
            }
        ]
    }
}

println("parent={rect.parent}");
// and while we're at it
println("styleClass={rect.parent.styleClass}");

The output will be something like this:

parent=Scene$Root@27d314cc
styleClass=scene

Whoa, what’s that? Inside of every Scene, there’s a hidden node called Scene$Root that’s the parent of every Node in the Scene’s content sequence. It’s a subclass of Parent. It’s the actual root node of the scene graph. And, most importantly for this discussion, it handles CSS on behalf of the Scene. Indeed, its styleClass is “scene”. So, style rules that use “.scene” as their selector are really applying styles to this hidden Scene$Root object.

We’re a little closer, since we now know that “.scene” styles apply to the Scene$Root object and not the Scene object itself. But Scene$Root doesn’t actually have any properties that are affected by CSS. What good does it do to set properties on Scene$Root if they don’t actually affect it?

To understand what’s going on, we have to talk about two features of CSS. First, a feature of JavaFX CSS is that colors can be specified not only using standard color names such as “dodgerblue” or by using RGB syntax like “#0093ff”, but they also can also be looked up by name using properties defined by styles above them in the hierarchy.  Second, as in standard CSS, some properties are inherited. Let’s examine these features in more detail.

Color Lookup

Continuing with the simple rectangle example from above, let’s define style rule for .scene that defines some new color names:

.scene {
    -smarks-special-fill-color: #40d080;
    -smarks-special-border-color: #d02040;
}

I just made up the property names -smarks-special-fill-color and -smarks-special-border color. They don’t exist anywhere else, and merely setting these properties won’t have any effect on anything. However, the property names and values are applied to Scene$Root, so we can put them to use. Define

.myrect {
    -fx-fill: -smarks-special-fill-color;
    -fx-stroke: -smarks-special-border-color;
    -fx-stroke-width: 5;
}

(I also made the stroke width thicker so that it’s easier to see the border.) The result is as follows:

This works because in JavaFX CSS, you can use an arbitrary property name as the value for a color property. This property name is looked up on all ancestor nodes, and if a value is found, that color is used in its place.

Now, I could have specified those colors directly in the .myrect rule and it would have worked just fine. However, if I had several different style rules (say, for different shapes) that wanted to use the same colors, I’d have those color values spread around in a bunch of different rules in my style sheet. If I wanted to change a color, I’d have to change it in several places. Since the Scene$Root node is the ancestor of every node that appears in any Scene, and since its styleClass is “scene”, I can place some color definitions in the “.scene” style rule and they’ll be visible to be looked up from any node in the scene graph. The “.scene” style is thus about as close as we can get to a global repository of color properties. Indeed, if you look at the “.scene” rule from the caspian.css file, just about all if its declarations are for color properties.

Inheritance

Let’s change the scene’s content to have some Text nodes in order to show inheritance of font properties:

content: [
    Text { x: 30 y:  60 content: "Hello, JavaFX!" }
    Text { x: 30 y: 100 content: "CSS is fun!" }
]

This will use the default font, which will give a result like this:

Now let’s modify the .scene style rule as follows:

.scene {
    -fx-font: 18pt "Times-Italic";
}

The result will change to the following:

Why did this have an effect? The reason is that, as in standard CSS, font properties are inherited down the hierarchy. More precisely, if a font value isn’t provided for a particular node, the font property is looked up in ancestor nodes until a value is found. Since Scene$Root is at the root of the hierarchy, and the “.scene” properties have been applied to it, the font defined there ends up being used by the Text nodes. Of course, I could override the font by specifying a font value directly in the code, or by creating a style with a font property and arranging for it to apply to the Text nodes or to an ancestor. Since I didn’t do that, the font property from the “.scene” rule applies. It’s effectively a specification of the default font to be used everywhere in the scene graph.

In summary, the “.scene” style rule doesn’t apply properties to the Scene itself (though maybe it should). Instead, it stores properties on the Scene$Root node. These properties aren’t used directly, but can be inherited (for fonts) and can be looked up (for colors) by nodes anywhere in the scene graph. Thus, the “.scene” style rule is where global color and font properties can be defined, which makes it easier to develop and maintain consistent style sheets.

Read Full Post »

SVJUGFX Talk Tonight!

I’m talking at the Silicon Valley JavaFX Users Group tonight. The topic is Hands On JavaFX — Scripting The Scene Graph.

Time and location information is available at the SVJUGFX website. If you’re not in the SF Bay Area, a webcast will also be available. Information is at that link.

I’ve posted the presentation materials on my website here. They’ll be helpful if you miss the talk and want to review it, or if you’re watching remotely and want to follow along (or read ahead).

See you there!

Read Full Post »

Older Posts »