11.07.2015 Views

JSR-296: The Swing Application Framework - Java

JSR-296: The Swing Application Framework - Java

JSR-296: The Swing Application Framework - Java

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

<strong>JSR</strong>-<strong>296</strong>: <strong>The</strong> <strong>Swing</strong><strong>Application</strong> <strong>Framework</strong>Hans Muller, Josh Marinacci<strong>Swing</strong> EngineeringSun Microsystemshttp://appframework.dev.java.netTS-39422007 <strong>Java</strong>One SM Conference | Session TS-3942 |


Learn Enough to <strong>Application</strong>.launch()!Write less, finish more<strong>Java</strong> Specification Request (<strong>JSR</strong>)-<strong>296</strong>,<strong>Swing</strong> <strong>Application</strong> <strong>Framework</strong>: how itstarted, what it is, how to use it, why youwant it2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 2


AgendaHow Did We Get Here? <strong>The</strong> Back Story<strong>The</strong> Entire <strong>Application</strong> <strong>Framework</strong> APISummary, Plans, Futures, OutstandingIssues, Things You’re Not Likely toRememberA Demo!Helpful Links, Q&A2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 3


Agenda [font size reflects duration]How did we get here? <strong>The</strong> back story<strong>The</strong> entire<strong>Application</strong><strong>Framework</strong> APISummary, plans, futures, outstanding issues, things you’re not likely to rememberA Demo!Helpful links, Q&A2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 4


AgendaHow Did We Get Here? <strong>The</strong> Back Story<strong>The</strong> Entire <strong>Application</strong> <strong>Framework</strong> APISummary, Plans, Futures, OutstandingIssues, Things You’re Not Likely toRememberA Demo!Helpful links, Q&A2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 5


How Did We Get Here?● <strong>Swing</strong> version 0.1 debuts in 1997●●It’s widely adoptedDevelopers let us know that building <strong>Swing</strong>applications can be difficult. <strong>The</strong>y tell us that astandard application framework would make thejob easier.2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 6


How Did We Get Here? (Cont.)●More than 8 years pass2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 7


How Did We Get Here? (Cont.)● Late Spring 2006● <strong>Swing</strong> Team files two <strong>JSR</strong>s aimed at simplifyingbuilding applications:●●●<strong>JSR</strong> 295 Beans Binding<strong>JSR</strong> <strong>296</strong> <strong>Swing</strong> <strong>Application</strong> <strong>Framework</strong>Both <strong>JSR</strong>s●●●Focus on issues common to typical <strong>Swing</strong> applicationsAre intended for <strong>Java</strong> Platform, Standard Edition (<strong>Java</strong>SE platform) SE 7Have prototypes available, java.net projects2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 8


This Presentation Is About <strong>JSR</strong>-<strong>296</strong>●An <strong>Application</strong> <strong>Framework</strong> for <strong>Swing</strong>2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 9


But Aren’t <strong>Application</strong> <strong>Framework</strong>sGiant Scary Monsters?Can be too much frame, not enough work2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 10


Not Scary●●<strong>Swing</strong> <strong>Application</strong> <strong>Framework</strong> goals●●●As small and simple as possible (not more so)Explain it all in one hourWork very well for small/medium appsNo module system, integral docking framework,generic data model, scripting language, GUImarkup schema2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 11


AgendaHow Did We Get Here? <strong>The</strong> Back Story<strong>The</strong> Entire <strong>Application</strong> <strong>Framework</strong> APISummary, Plans, Futures, OutstandingIssues, Things You’re Not Likely toRememberA Demo!Helpful links, Q&A2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 12


Disclaimer●●●This is a review of my prototype<strong>The</strong> details will almost certainly change<strong>The</strong> fundamentals could change too2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 13


What the <strong>Framework</strong> Does●●●●●LifecycleResourcesActionsTasksSession state2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 14


<strong>Framework</strong> Architecture2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 15


Real <strong>Framework</strong> Architecture<strong>Application</strong>ContextsingletonLocalStorageActionManager<strong>Application</strong>ActionMap<strong>Application</strong>Action@Action<strong>Application</strong>singletonSessionStorageResourceManagerResourceMapResourceConverter@ResourceTaskService, Task,TaskMonitor2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 16


Using the <strong>Framework</strong>●●●●Create a subclass of <strong>Application</strong>Create and show your GUI in the startup methodUse <strong>Application</strong>Context services to●●●define/manage actions and tasksload/inject resourcessave/restore session stateCall <strong>Application</strong>.launch from your main method2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 17


Using the <strong>Framework</strong>: Hello Worldpublic class MyApp extends SingleFrame<strong>Application</strong> {@Override protected void startup() {JLabel label = new JLabel("Hello World");show(label);}public static void main(String[] args) {<strong>Application</strong>.launch(MyApp.class, args);}}// SingleFrame<strong>Application</strong> is a subclass of <strong>Application</strong>2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 18


<strong>Application</strong> Class●●●●Subclass defines your application’s lifecycleMost apps will start with a class that extends<strong>Application</strong>, like SingleFrame<strong>Application</strong>Subclasses override lifecycle methods●●<strong>Application</strong> instance is constructed on the EDTLifecycle methods run on the EDT (except launch)Most lifecycle methods do little by default●…other than being called at the appropriate time2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 19


<strong>Application</strong> Lifecycle Methodslaunch()Calls initialize(), startup() and ready() on the EDT.A static method, usually called from main().initialize()startup()ready()exit()Performs initializations that must happen before the GUIis created, like setting the look and feel.Create the initial GUI and show it.All applications will override this method.Any work that must wait until the GUI is visible andready for input.Call shutdown, if the exitListeners don't veto.Main frame’s WindowListener calls exit().shutdown()Take the GUI down, final cleanup.2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 20


May I Exit? <strong>Application</strong> Exit Listeners●●To quit the app, call exit()<strong>The</strong> exit() method checks exitListeners firstpublic interface ExitListener extends EventListener {boolean canExit(EventObject e);void willExit(EventObject e);}●If they all return true:●●call <strong>Application</strong>.shutdown()System.exit()2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 21


ExitListener Exampleclass MaybeExit implements <strong>Application</strong>.ExitListener {public boolean canExit(EventObject e) {JFrame f = getMainFrame();String s = "Really Exit?"; // *ResourceMapint o = JOptionPane.showConfirmDialog(f, s);return o == JOptionPane.YES_OPTION;}public void willExit(EventObject e) { }}<strong>Application</strong> app = <strong>Application</strong>.getInstance();app.addExitListener(new MaybeExit());2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 22


What the <strong>Framework</strong> Does●●●●●LifecycleResourcesActionsTasksSession state2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 23


<strong>Application</strong> Resources●●●Defined with ResourceBundlesOrganized in resources subpackgesUsed to initialize properties specific to:●●●localeplatforma few related values…2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 24


ResourceMaps●●●Encapsulate list of ResourceBundles whosenames are based on a class:●●Generic ResourceBundle; just the class namePer OS platform, class_os, e.g., MyForm_OSXAutomatically parent-chained●●Package-wide resources<strong>Application</strong>-wide resourcesSupport string to type resource conversion●Extensible2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 25


Getting a ResourceMap●●Resources for mypackage/MyForm.java●●●mypackage/resources/MyForm.propertiesmypackage/resources/PackageResources.propertiesmypackage/resources/MyApp.propertiesResourceMap for MyForm:<strong>Application</strong>Context c = <strong>Application</strong>Context.getInstance();ResourceMap r = c.getResourceMap(MyForm.class);2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 26


Using ResourceMaps: Example# resources/MyForm.propertiesaString = Just a stringaMessage = Hello {0}anInteger = 123aBoolean = TrueanIcon = myIcon.pngaFont = Arial-PLAIN-12colorRGBA = 5, 6, 7, 8color0xRGB = #556677<strong>Application</strong>Context c = <strong>Application</strong>Context.getInstance();ResourceMap r = c.getResourceMap(MyForm.class);r.getString("aMessage", "World") => "Hello World"r.getColor("colorRBGA") => new Color(5, 6, 7, 8)r.getFont("aFont") => new Font("Arial", Font.PLAIN, 12)2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 27


Resource InjectionResourceMap.injectComponents(Component root)ResourceMap.injectComponent(Component target)●Initialize properties from like-named resources● myPanel.setForeground(Color c)● myLabel.setIcon(Icon i)ResourceMap.injectFields(Object target)●Initialize marked fields from like-named resources●●@Resource Color foreground;@Resource Icon icon;2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 28


Resource Injection Example●resourceMap.injectComponents(myPanel)component.getName():labelbutton1 button2 button3# resources/MyPanel.propertieslabel.text = Choose one:label.font = Lucida-PLAIN-18button1.icon = smiley.gifbutton2.icon = scared.gifbutton3.icon = sad.gif2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 29


Resource Injection Advantages●●●Localizable by defaultNo need to explicitly lookup/set resources●●But:●●●Easy to reconfigure visual app propertiesreview visual app propertiesnot intended to be a “styles” mechanismnot intended for general purpose GUI markup@Resource injection requires privileges2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 30


Resource Injection in theSingleFrame<strong>Application</strong> classpublic class MyApp extends SingleFrame<strong>Application</strong> {@Override protected void startup() {JLabel label = new JLabel();label.setName(“label”);show(label); // creates JFrame “mainFrame”}public static void main(String[] args) {<strong>Application</strong>.launch(MyApp.class, args);}}# resources/MyApp.propertieslabel.text = Hello Worldlabel.font = Lucida-PLAIN-64mainFrame.title = Hello2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 31


<strong>The</strong> sayHello Action in action●Disable the sayHello Action:sayHello.setEnabled(false);2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 32


What the <strong>Framework</strong> Does●●●●●LifecycleResourcesActionsTasksSession state2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 33


Actions: A (very) brief review●Encapsulation of an ActionListener and:●●some purely visual propertiesenabled and selected boolean properties// define sayHello Action – pops up message DialogAction sayHello = new AbstractAction("Hello") {public void actionPerformed(ActionEvent e) {String s = textField.getText();JOptionPane.showMessageDialog(s);}};// use sayHello – set the action propertytextField.setAction(sayHello);button.setAction(sayHello);2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 34


<strong>The</strong> sayHello Action in Action●Disable the sayHello Action:sayHello.setEnabled(false);2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 35


Actions: What We Like●●●Encapsulation of default GUI + behavior<strong>The</strong> enabled and selected propertiesReusability2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 36


What We’re Not So Happy About●●●●●Overhead: creating Action objects is a painVisual properties should be localized!Asynchronous Actions are difficultProxy linkages can be messyIt's tempting to make a little spaghetti:●Backend logic that depends on Actions: find all theactions you need to enable/disable2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 37


<strong>The</strong> new @Action annotation// define sayHello Action – pops up message Dialog@Action public void sayHello() {String s = textField.getText();JOptionPane.showMessageDialog(s);}// use sayHello – set the action propertyAction sayHello = getAction("sayHello");textField.setAction(sayHello);button.setAction(sayHello);●●●ActionEvent argument is optionalUsed to define a “sayHello” ActionMap entryEncapsulation of default GUI + behavior2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 38


Where did the Action come from?// utility method: look up an action for this classAction getAction(String name) {<strong>Application</strong>Context c = <strong>Application</strong>Context.getInstance();ActionMap actionMap = c.getActionMap(getClass(), this);return actionMap.get(name);}●<strong>Application</strong>Context.getActionMap()●●●creates an Action for each @Action methoddefault key is the action's method namecreates and caches an ActionMap2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 39


Action Resources●Loaded from the target class's ResourceMap# resources/MyForm.propertiessayHello.Action.text = Say &HellosayHello.Action.icon = hello.pngsayHello.Action.accelerator = control HsayHello.Action.shortDescription = Say hello modally2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 40


public class MyApp extends SingleFrame<strong>Application</strong> {@Action public void sayHello() {JLabel label = new JLabel();label.setName("label");show(JOptionPane.createDialog(label));}@Override protected void startup() {show(new JButton(getAction("sayHello")));}public static void main(String[] args) {<strong>Application</strong>.launch(MyApp.class, args);}}# resources/MyApp.propertiessayHello.Action.text = Say&HellosayHello.Action.shortDescription = say hellolabel.text = Hello WorldmainFrame.title = Hello2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 41


@Action enabled/selected linkage●●●@Action parameter names bound property●<strong>The</strong> rest of the app depends on the property, not theAction object@Action(enabledProperty = “name”)@Action(selectedProperty = “name”)2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 42


Defines 3 Actions: revert, save, deletepublic class MyForm extends JPanel {@Action(enabledProperty = "changesPending")public void revert() { ... }@Action(enabledProperty = "changesPending")public void save() { ... }@Action(enabledProperty = "!selectionEmpty")public void delete() { ... }// <strong>The</strong>se properties are bound, when they change// PropertyChangeEvents are firedpublic boolean getChangesPending() { ... }public boolean isSelectionEmpty() { ... }}// ...2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 43


Enabled Property: Beans Bindingpublic MyHomePanel {@Action(enabledProperty = "purchaseEnabled")public void purchase() { ... }public boolean isPurchaseEnabled() { }public void setPurchaseEnabled(boolean b) { }}new Binding(aHomeListing, "${available}",myHomePanel, "purchaseEnabled").bind();new Binding(homeListingTable, "${selectedElement.available}",myHomePanel, "purchaseEnabled").bind();2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 44


One Action, Multiple Looksbutton1 button2 button3Note: all three buttons sharethe sayHello Action# resources/MyForm.propertiessayHello.Action.text = Say HellosayHello.Action.icon = hello.pngbutton2.text = ${null}button3.icon = ${null}●●Override Action's visual properties●●action resource is set firstother resources override action's visualsCommon case: Menu/Toolbar/Button2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 45


What the <strong>Framework</strong> Does●●●●●LifecycleResourcesActionsTasksSession state2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 46


Don’t Block the EDT●●●Use a background thread for●●Computationally intensive tasksTasks that might block, like network or file IOBackground thread monitoring/management●●●●Starting, interrupting, finishingProgressMessagesDescriptive information<strong>Swing</strong>Worker: most of what we need2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 47


Tasks Inherit the <strong>Swing</strong>Worker API●●●Task isa <strong>Swing</strong>Worker isa Future●●Futures compute a value on thread<strong>The</strong>y can be canceled/interrupted<strong>Swing</strong>Worker adds:●●●EDT done() and PropertyChange methodsPublish/process for incremental resultsProgress property percent completeTasks add…2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 48


Tasks: Support for Monitoring●●●●Task title, description properties●●For users (humans)Initialized from ResourceMapTask message property, method●●●myTask.setMessage(“loading ” + nThings)myTask.message(“loadingMessage”, nThings)(resource) loadingMessage = loading {0} thingsTask start/done time propertiesTask userCanCancel property2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 49


Tasks: Completion●●<strong>Swing</strong>Worker.done overrides can be tricky●●call <strong>Swing</strong>Worker.get() for exceptioncheck for cancellation, interruptionTask completion methods:protected void succeeded(T result)protected void failed(Throwable cause)protected void cancelled()protected void interrupted(InterruptedException e)protected void finished()2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 50


Asynchronous @Action example@Action public Task sayHello() { // Say hello repeatedlyreturn new SayHelloTask();}private class SayHelloTask extends Task {@Override protected Void doInBackground() {for(int i = 0; i


Tasks That Block the GUI●●●Task BlockingScope property:●●NONE, ACTION, COMPONENT, ANCESTOR,WINDOW, APPLICATIONANCESTOR blocks tagged ancestor<strong>Application</strong> deals with blocking the GUIprotected void block(Task task, Object... target)protected void unblock(Task task)Reasonable default behavior2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 52


TaskService●●Defines how a Task is executed, e.g.●●●seriallyby a thread pooletc...TaskService isa ExecutorService●●named, constructed lazily@Action(taskService = “database”)2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 53


<strong>Application</strong>Context providesTask Service AccessTaskService getTaskService(String name)List getTaskServices()void addTaskService(TaskService taskService)void removeTaskService(TaskService taskService)2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 54


Tasks and TaskServicesTaskService“ConcurrentTasks”T0T1 T2 T3 T4 ...TaskService“SingleTaskQueue”T0 T1 T2 ......2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 55


Watching Tasks That Aren’t Done:TaskMonitor●●●Desktop apps often have many running TasksTaskMonitor provides a summary●●Bound properties, same as TaskForeground task: first one startedHandy for StatusBar implementations2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 56


Actions and Tasks Summary●●●Define Actions with @Actions, resources●●●Link enabled/selected to a property@Action(enabledProperty = name)@Action(selectedProperty = name)Asynchronous @Actions return Tasks●●●Provide title/description resourcesUse message/progress methods/propertiesUse the block parameter and resourcesConnect your status bar to a TaskMonitor2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 57


What the <strong>Framework</strong> Does●●●●●LifecycleResourcesActionsTasksSession state2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 58


Session State●●Make sure the application remembers whereyou left thingsMost applications should do this●●●●But they don’tWhat state to save?Where to store it (and what if you’re unsigned)?How to safely restore the GUI2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 59


SessionStorage, LocalStorage●●●●<strong>Application</strong>Context.getSessionStorage()Save(rootComponent, filename)●●●Supported types, named components onlyWindow bounds, JTable column widths, etcArchived with XMLEncoderRestore(rootComponent, filename)●●ConservativeRestored with XMLDecoderLocalStorage abstracts per-user files●Works for unsigned apps too!2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 60


Using SessionStorage●●●SingleFrame<strong>Application</strong> saves/restoresautomatically, at startup/shutdown timeYou can customize what’s stored/restored●●●Create SessionStorage.Property implementationsSessionStorage.putProperty(forClass, ssp)Usually, you will not need toSave/restore arbitrary objects too:<strong>Application</strong>Context c = <strong>Application</strong>Context.getInstance();c.getSessionStorage().save("data.xml", myHashMap);2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 61


DEMOBuilding an <strong>Application</strong> With NetBeans Software!2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 62


Summary●●●●<strong>Swing</strong> <strong>Application</strong> <strong>Framework</strong> supports●Actions, resources, tasks, sessions<strong>Application</strong> and <strong>Application</strong>Context singletons●●You subclass <strong>Application</strong>, SingleFrame<strong>Application</strong>Call <strong>Application</strong>.launch() in main<strong>JSR</strong>-<strong>296</strong> expert group is responsible● for defining the framework’s final form● finishing in time for <strong>Java</strong> platform 7Get the code and learn more on the project site:http://appframework.dev.java.net2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 63


For More Information●●●Source code, docs, and binaries on java.netproject: http://appframework.dev.java.netQuestions, comments, etc to:users@appframework.dev.java.netRelated sessions●●TS-3316—Why Spaghetti Is Not Tasty: ArchitectingFull-Scale <strong>Swing</strong> Apps, Thursday, 2:50–3:50PMTS-3569—Beans Binding: Thursday, 4:10–5:10PM2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 64


Q&AHans Muller, Josh Marinacci2007 <strong>Java</strong>One SM Conference | Session TS-3942 | 65

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!