In the process of getting Music Explorer FX ready to be open sourced (which hopefully will happen any day now), I couldn’t help but take a trip down memory lane with some of the early iterations, which I thought I’d share here.
For reference, this is a screen shot of the current state of the Music Explorer (you can click on any of the images below for a larger view):
Here’s the initial prototype created almost eight months ago:
All of the data was canned at this point. Note how small the images are in order to accommodate eight artists (instead of six). The big, bulky, blue borders have some subtle gradients which caused performance issues even when cached. Bummer.
This was one of the initial search screens. Note the main logo looks quite different. Also, I didn’t have custom icons at this point as all of the buttons just have text labels.
This is what the search results used to look like. I was too in love with gradients. I still am, really.
In this version, the data is now live. The audio player is fixed to the bottom left corner and is there regardless of if there is audio or not. The audio player is actually built around Josh Marinacci’s sample MediaComponent at this point in the evolution. Note the artists still clearly don’t fit right on the screen. Also, I still won’t let the idea of gradients die.
Here things fit much better as I’ve finally settled on six instead of eight artists. The audio player is moved underneath the current artist and I have my first set of gigantic custom icons for switching between modes. Also, my love of gradients reached new heights (or new lows depending on your aesthetic sense) with the inclusion of the background.
My friends finally have an intervention on my behalf. Gradients gone ;(
I received a lot of great feedback during the development of MEFX. A reoccurring criticism was that the application was too dark. The above screen shot proves that I am either passive aggressive, or have no artist sense (probably both).
MEFX is almost to the state that it’s in today. The icons have tightened up. Some great advice I received was to “let the artist images define the color”, which I attempted to do by removing the color from the borders and adopting a more muted color scheme.
Finally, again, for reference, here is what MEFX looks like today:
The buttons are smaller still, and look more like tabs that appear to just “tuck underneath” the current artist. The audio player only appears if there is music to play and appears to be part of the artist’s node.
While I was writing this, Ben Galbraith’s excellent talk on Craftsmanship came to mind. In it he talks about (among other things) the value of polishing something over and over and over.
While I’m not sure that I can claim Craftsmanship in the Music Explorer, I can certainly relate to the value of doing something again and again and again.
The process of polishing was often extremely painful. I would agonize over how to incorporate the feedback I’d received, often to the point of wanting to chuck out the whole thing. I would stare at the application, knowing that it wasn’t quite right, but at a loss for how to make it better.
Then, eventually, through sheer stubborn persistence, I’d get some sort of glimpse of an idea of something different — and a few experiments later, I couldn’t imagine it ever looking different from the new way.
Well that’s it. Thanks for checking this out.
Do you have your own? Feel free to comment below…
The JavaFX team is running a contest for blogging about developer experience with the newly released 1.2 feature set. The top 10 posts each receive $500 USD. This blog post is my contest submission.
—————-
Let me start by saying thank you to Sun Microsystems for sponsoring this contest, and to the JavaFX team for crafting such a fine RIA development platform.
Finally, I’d like to extend a very heartfelt “thank you” to the judges of the contest for reading each and every submission. I don’t envy the position you must be in, having to cull through each submission — each one chronicling a developer’s story, because while deep down we’re all winners, in a more accurate sense, only ten of us are.
Indeed, what does a $500 blog entry even look like? I imagine it must be bursting at the seams with insight and purpose. So while I have no doubt that you, the honorable judges, are up to this daunting task of discernment, I trust that the $20 I’ve forwarded to each of you will aid in the decision making process.
Actually, I’m feeling pretty good about my chances here, since after all, this is a blogging contest, and they don’t give out blogs to just anybody (case in point: I was put on an 18 month waiting list for this blog). So unless you’re accepting handwritten submissions, this is likely a slam dunk. But don’t worry — I’ll still take it seriously (wink).
So let’s get to it, shall we? JavaFX 1.2: The Developer Experience!
There are so many earth-shatteringly new features in the 1.2 release, it’s hard to know where to begin. Let’s start with the most obvious surprise addition: Charts. The charting support in JavaFX 1.2 is awesome! Just awesome! I love it.
Let’s see, what’s next? Oh, I know! All of the new controls! The new controls are AWESOME! Just really great! And they look stupendous in the new Look and Feel, Caspian. Good stuff. Love it.
Ok, covered that…what’s next? That might be it, right?
Ok. So, here’s the deal: I haven’t actually downloaded JFX 1.2 yet, but I promise that I will real soon. In fact, on that note, perhaps $500 would (ahem) speed that process along a bit, if you know what I’m saying…and I think you do. Just crown me as one of the winners and then I’ll promise to write up a more thorough post at a later date, ok?
Ok, fine, we’ll play by your rules. Let me download it and check it out. Don’t go anywhere.
[Many days later...]
Ok, so, I’ll devote the rest of this entry to my experience with migrating a JavaFX 1.1 application, Music Explorer FX, to 1.2.
The first thing that I was confronted with upon loading up the Music Explorer Netbeans project for the first time in 1.2 was the massive number of overly-apologetic compiler errors. After about the hundredth “Sorry, but I was trying to understand…”, though, I was starting to suspect its sincerity.
Perhaps you guys want to consider implementing an “Incrementally Irritable” Compiler where the first 10 or so errors nets you a polite “Pardon me, but I think you erred”, but by the, say, 50th error, you’ve degraded into a “bitch, plz!”
(Note: the contest guidelines likely have anti-profanity rules which you might be tempted to invoke to disqualify me after my use of the word “bitch” above. I would argue, however, that while “bitch” is a indeed a coarse term, it was used in a humorous way, which I’m sure elicited at least a smile, if not a full blown “lol” (if neither, then you must be finding this post torturous to wade through, but might I remind Your Honor that you took an oath to read each and every post in this contest. You have to finish.) Besides, “bitch” is not profanity according to WikiAnwsers.)
Anyway, these errors weren’t a surprise as I did read up enough on the 1.2 changes to expect them. After comma separating my sequences and changing all my “Image.fromBufferedImage” to “SwingUtils.toFXImage”, I was building successfully and ready to run the application.
When I bring up the application, though, I just get a black screen, so something isn’t right here. After some digging it turns out that I was binding to a Group on the Scene, which, while it seemed to work in 1.1, doesn’t seem to in 1.2. No worries though. So I simply removed the Group and did a bind directly to the underlying sequence and things start up normally again.
Great. So overall a pretty painless migration to get the app running again. Let’s see if the application still works though.
Oops. When I try to search for an artist, I get the following exception:
Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: com.sun.javafx.runtime.sequence.ObjectArraySequence cannot be cast to com.citytechinc.ria.musicexplorerfx.model.Artist
The exception seems to occur when I pull data (a Sequence) from the Java layer back up to the JavaFX layer. In my attempt to futz with some of the return types to get this cryptic exception to go away I run across this Jim Dandy:
Note: An internal error has occurred in the OpenJFX compiler. Please file a bug at the
Openjfx-compiler issues home (https://openjfx-compiler.dev.java.net/Issues)
after checking for duplicates. Include in your report:
- the following diagnostics
- file C:\Documents and Settings\sanderson\Local Settings\Temp\ javafx_err_2753540138989817596.txt
- and if possible, the source file which triggered this problem.
Thank you.
Oh my! That seems like a rather serious error. You’d probably really like to get your hands on “javafx_err_2753540138989817596.txt” I bet. Perhaps $500 might help it find its way into a bug report.
But I kid! This whole “sequence across the Java layer” issue is bugging me though, so I tried to simply and isolate with a small test case. To that end, here’s a simple JavaFX class called ValueObject:
public class ValueObject {
public override function toString():String {
"Value Object";
}
}
Here’s a simple Java class representing the Java layer:
public class JavaLayer {
Object doNothing(Object obj) {
return obj;
}
}
All it will do is take an object from JavaFX and return it. Here we put it together in a separate JavaFX script:
var seq:Object[];
insert ValueObject {} into seq;
var javaLayer = new JavaLayer();
var javaSeq = javaLayer.doNothing(seq);
var javaObjSeq = javaSeq as Object[];
for (element in javaObjSeq) {
var val = element as ValueObject; // throws ClassCastException
}
We insert a new ValueObject into a Sequence, pass it to the Java layer, which does nothing but pass it back to us. Somewhere in this translation between boundaries, though, some sort of type information gets munged since the cast to ValueObject in the “for” loop results in this:
java.lang.ClassCastException: com.sun.javafx.runtime.sequence.ObjectArraySequence cannot be cast to seqtest.ValueObject
I would expect “javaObjSeq” to be of type “ObjectArraySequence” (it’s actually of type SingletonSequence, which makes sense since it has one element — btw, a quick naming suggestion on “SingletonSequence”: it might make more sense to name it “SingleElementSequence” so it doesn’t clash with the name and intention of the “Singleton” design pattern), but it turns out that its contents is also of type “ObjectArraySequence”, even though, if we ask “element” to print itself, it prints “Value Object”, which indicates that it is in fact of type “Value Object”.
So this is very confusing to me, be it a bug or a misunderstanding on my part. At any rate, something changed between 1.1 and 1.2 here.
Leaving the mundanity of data transfer issues behind us, something else I was able to do was upgrade some of my wrapped Swing components to official JavaFX 1.2 controls. You can consult this post for more details. In fact, in all fairness that post should also count towards the contest as well since it’s all on the same theme. Alternately you could consider it a double-entry if you feel that both posts taken together deserve a double prize of $1000.
Whew, so I’ve kind of run out of steam and time on this migration, as I’m sure you, dear judge(s), have run out of patience. This contest ends today, which for me, is a day off, and my two children are asking me to repair the pillow fort that I made for them out of the couch cushions not 20 minutes ago. And since, I think you’ll agree, that the central message of JavaFX is really that of a harmony between not just developer and development, but also between developer and life in general — including family life — that you’ll forgive me for ending this (I can only hope) award-winning post prematurely.