javablogspot

Just another WordPress.com weblog

Posts Tagged ‘swings’

WebKit Component for Java, Second Contestant

Posted by damuchinni on March 14, 2009

While there weren’t any news related to Sun’s JWebPane, there is a new contestant: WebKit for SWT by Genuitec. The website says:

WebKit for SWT (ver. 0.5) is an embeddable Java™ WebKit browser component developed by Genuitec. This component can be used in the development of a wide range of Java SWT applications that require integration of rich HTML5, CSS3, JavaScript and Flash content and functionality.

The solution seems a little bit more high-level than Sun’s approach: While Sun is integrating WebKit directly, Genuitec build on top of Google’s chromium. The biggest difference however at this time: They provide code, documentation and samples.

Posted in Java, swings | Tagged: , , | Leave a Comment »

The Swing Cookbook

Posted by damuchinni on March 11, 2009

an Darwin’s Java Cookbook presents a collection of recipes for solving hundreds of problems that Java developers encounter. For example, in the first edition, one of Chapter 2’s recipes discusses how to use the classpath effectively. To the best of my knowledge, O’Reilly hasn’t published a similar cookbook that deals exclusively with Swing.

A Swing-only cookbook might make Swing more accessible to those inexperienced with this toolkit. Perhaps it would help for Chapter 1’s recipes to target the Swing Application Framework, which is intended to make Swing applications easier to write, and which should debut in Java SE 7. Later chapters could each target one or more Swing components.

For example, one chapter might present recipes for both the JList and JComboBox components. (Because of their similarity, grouping JList and JComboBox recipes in the same chapter seems logical.) Although some recipes would be JList-specific, and other recipes would target only JComboBox, still other recipes would focus on both components. Custom cell rendering is one example.

JList and JComboBox each manage a list of items. They rely on a cell renderer component to render each item in a cell. Although the default cell renderer is adequate for most rendering tasks, scenarios exist where you’ll want to install a custom cell renderer to handle a specific kind of rendering. For example, Figure 1 shows a custom cell renderer presenting a flag icon beside a country’s name.

Figure 1: The flag icons are courtesy of British developer Mark James.

Prior to rendering an item in a cell, JList and JComboBox obtain an item-specific rendering component by invoking the ListCellRenderer interface’s Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) method. The returned component performs the rendering, taking into account the method’s arguments:

list references the JList whose cell is to be rendered. (For a JComboBox, list references the JList part of this component.)
value references the object that is to be rendered in the cell.
index identifies value’s location in the list. In some cases, such as when focus shifts away from the list, -1 is passed to index.
isSelected indicates whether the cell being rendered is currently selected (true) or not (false).
cellHasFocus indicates whether the cell being rendered has the input focus (true) or not (false). For JComboBox, this argument is always false because a combobox’s text field, instead of the list, gets the focus.
JList and JComboBox default their cell renderers to instances of the DefaultListCellRenderer class, which implements ListCellRenderer. These defaults can be replaced by invoking JList’s void setCellRenderer(ListCellRenderer cellRenderer) and JComboBox’s void setRenderer(ListCellRenderer aRenderer) methods.

Before invoking setCellRenderer() or setRenderer(), you need to declare and instantiate a class that implements ListCellRenderer and provides the rendering logic. The easiest way to handle the rendering in a look-and-feel independent manner is to subclass an existing component such as a JLabel. This is precisely what the custom cell renderer illustrated in Figure 1 and specified in Listing 1 accomplishes.

Listing 1: Countries.java

// Countries.java

import java.awt.*;

import java.net.URL;

import java.util.*;

import javax.swing.*;
import javax.swing.border.Border;

public class Countries extends JFrame
{
Countries (String title)
{
super (title);
setDefaultCloseOperation (EXIT_ON_CLOSE);

FlowLayout layout = new FlowLayout (FlowLayout.CENTER, 5, 5);
layout.setAlignOnBaseline (true);
getContentPane ().setLayout (layout);

Country [] carray;
JList list = new JList (carray = createCountriesArray ());
// list.setEnabled (false);
list.setCellRenderer (new CountryCellRenderer (null));
list.setVisibleRowCount (8);
list.setSelectedIndex (0);
getContentPane ().add (new JScrollPane (list));

JComboBox cb = new JComboBox (carray);
// cb.setEnabled (false);
cb.setRenderer (new CountryCellRenderer (cb));
getContentPane ().add (cb);

pack ();
setVisible (true);
}

Country [] createCountriesArray ()
{
String [] citems =
{
“AD,Andorra”,
“AE,United Arab Emirates”,
“AF,Afghanistan”,
“AG,Antigua and Barbuda”,
“AI,Anguilla”,
“AL,Albania”,
“AM,Armenia”,
“AN,Netherlands Antilles”,
“AO,Angola”,
“AR,Argentina”,
“AS,American Samoa”,
“AT,Austria”,
“AU,Australia”,
“AW,Aruba”,
“AX,Åland Islands”,
“AZ,Azerbaijan”,
“BA,Bosnia and Herzegovina”,
“BB,Barbados”,
“BD,Bangladesh”,
“BE,Belgium”,
“BF,Burkina Faso”,
“BG,Bulgaria”,
“BH,Bahrain”,
“BI,Burundi”,
“BJ,Benin”,
“BM,Bermuda”,
“BN,Brunei Darussalam”,
“BO,Bolivia”,
“BR,Brazil”,
“BS,Bahamas”,
“BT,Bhutan”,
“BV,Bouvet Island”,
“BW,Botswana”,
“BY,Belarus”,
“BZ,Belize”,
“CA,Canada”,
“CC,Cocos (Keeling) Islands”,
“CD,Congo, the Democratic Republic of the”,
“CF,Central African Republic”,
“CG,Congo”,
“CH,Switzerland”,
“CI,Cote d’Ivoire Côte d’Ivoire”,
“CK,Cook Islands”,
“CL,Chile”,
“CM,Cameroon”,
“CN,China”,
“CO,Colombia”,
“CR,Costa Rica”,
“CU,Cuba”,
“CV,Cape Verde”,
“CX,Christmas Island”,
“CY,Cyprus”,
“CZ,Czech Republic”,
“DE,Germany”,
“DJ,Djibouti”,
“DK,Denmark”,
“DM,Dominica”,
“DO,Dominican Republic”,
“DZ,Algeria”,
“EC,Ecuador”,
“EE,Estonia”,
“EG,Egypt”,
“EH,Western Sahara”,
“ER,Eritrea”,
“ES,Spain”,
“ET,Ethiopia”,
“FI,Finland”,
“FJ,Fiji”,
“FK,Falkland Islands (Malvinas)”,
“FM,Micronesia, Federated States of”,
“FO,Faroe Islands”,
“FR,France”,
“GA,Gabon”,
“GB,United Kingdom”,
“GD,Grenada”,
“GE,Georgia”,
“GF,French Guiana”,
“GH,Ghana”,
“GI,Gibraltar”,
“GL,Greenland”,
“GM,Gambia”,
“GN,Guinea”,
“GP,Guadeloupe”,
“GQ,Equatorial Guinea”,
“GR,Greece”,
“GS,South Georgia and the South Sandwich Islands”,
“GT,Guatemala”,
“GU,Guam”,
“GW,Guinea-Bissau”,
“GY,Guyana”,
“HK,Hong Kong”,
“HM,Heard Island and McDonald Islands”,
“HN,Honduras”,
“HR,Croatia”,
“HT,Haiti”,
“HU,Hungary”,
“ID,Indonesia”,
“IE,Ireland”,
“IL,Israel”,
“IN,India”,
“IO,British Indian Ocean Territory”,
“IQ,Iraq”,
“IR,Iran, Islamic Republic of”,
“IS,Iceland”,
“IT,Italy”,
“JM,Jamaica”,
“JO,Jordan”,
“JP,Japan”,
“KE,Kenya”,
“KG,Kyrgyzstan”,
“KH,Cambodia”,
“KI,Kiribati”,
“KM,Comoros”,
“KN,Saint Kitts and Nevis”,
“KP,Korea, Democratic People’s Republic of”,
“KR,Korea, Republic of”,
“KW,Kuwait”,
“KY,Cayman Islands”,
“KZ,Kazakhstan”,
“LA,Lao People’s Democratic Republic”,
“LB,Lebanon”,
“LC,Saint Lucia”,
“LI,Liechtenstein”,
“LK,Sri Lanka”,
“LR,Liberia”,
“LS,Lesotho”,
“LT,Lithuania”,
“LU,Luxembourg”,
“LV,Latvia”,
“LY,Libyan Arab Jamahiriya”,
“MA,Morocco”,
“MC,Monaco”,
“MD,Moldova, Republic of”,
“ME,Montenegro”,
“MG,Madagascar”,
“MH,Marshall Islands”,
“MK,Macedonia, the former Yugoslav Republic of”,
“ML,Mali”,
“MM,Myanmar”,
“MN,Mongolia”,
“MO,Macao”,
“MP,Northern Mariana Islands”,
“MQ,Martinique”,
“MR,Mauritania”,
“MS,Montserrat”,
“MT,Malta”,
“MU,Mauritius”,
“MV,Maldives”,
“MW,Malawi”,
“MX,Mexico”,
“MY,Malaysia”,
“MZ,Mozambique”,
“NA,Namibia”,
“NC,New Caledonia”,
“NE,Niger”,
“NF,Norfolk Island”,
“NG,Nigeria”,
“NI,Nicaragua”,
“NL,Netherlands”,
“NO,Norway”,
“NP,Nepal”,
“NR,Nauru”,
“NU,Niue”,
“NZ,New Zealand”,
“OM,Oman”,
“PA,Panama”,
“PE,Peru”,
“PF,French Polynesia”,
“PG,Papua New Guinea”,
“PH,Philippines”,
“PK,Pakistan”,
“PL,Poland”,
“PM,Saint Pierre and Miquelon”,
“PN,Pitcairn”,
“PR,Puerto Rico”,
“PS,Palestinian Territory, Occupied”,
“PT,Portugal”,
“PW,Palau”,
“PY,Paraguay”,
“QA,Qatar”,
“RE,Reunion Réunion”,
“RO,Romania”,
“RS,Serbia”,
“RU,Russian Federation”,
“RW,Rwanda”,
“SA,Saudi Arabia”,
“SB,Solomon Islands”,
“SC,Seychelles”,
“SD,Sudan”,
“SE,Sweden”,
“SG,Singapore”,
“SH,Saint Helena”,
“SI,Slovenia”,
“SJ,Svalbard and Jan Mayen”,
“SK,Slovakia”,
“SL,Sierra Leone”,
“SM,San Marino”,
“SN,Senegal”,
“SO,Somalia”,
“SR,Suriname”,
“ST,Sao Tome and Principe”,
“SV,El Salvador”,
“SY,Syrian Arab Republic”,
“SZ,Swaziland”,
“TC,Turks and Caicos Islands”,
“TD,Chad”,
“TF,French Southern Territories”,
“TG,Togo”,
“TH,Thailand”,
“TJ,Tajikistan”,
“TK,Tokelau”,
“TL,Timor-Leste”,
“TM,Turkmenistan”,
“TN,Tunisia”,
“TO,Tonga”,
“TR,Turkey”,
“TT,Trinidad and Tobago”,
“TV,Tuvalu”,
“TW,Taiwan, Province of China”,
“TZ,Tanzania, United Republic of”,
“UA,Ukraine”,
“UG,Uganda”,
“UM,United States Minor Outlying Islands”,
“US,United States”,
“UY,Uruguay”,
“UZ,Uzbekistan”,
“VA,Holy See (Vatican City State)”,
“VC,Saint Vincent and the Grenadines”,
“VE,Venezuela”,
“VG,Virgin Islands, British”,
“VI,Virgin Islands, U.S.”,
“VN,Viet Nam”,
“VU,Vanuatu”,
“WF,Wallis and Futuna”,
“WS,Samoa”,
“YE,Yemen”,
“YT,Mayotte”,
“ZA,South Africa”,
“ZM,Zambia”,
“ZW,Zimbabwe”
};

ArrayList clist = new ArrayList ();
for (String citem: citems)
{
String [] cdata = citem.split (“,”);
clist.add (new Country (cdata [1],
getClass ().getResource (“icons/”+
cdata [0].toLowerCase ()+
“.png”)));
}

Country [] carray = clist.toArray (new Country [0]);
Arrays.sort (carray);
return carray;
}

public static void main (String [] args)
{
Runnable r = new Runnable ()
{
public void run ()
{
// Always create Swing UIs on event-dispatching
// thread.

new Countries (“Countries”);
}
};
EventQueue.invokeLater (r);
}
}

class Country implements Comparable
{
private String name;
private ImageIcon flagIcon;

private URL path;

Country (String name, URL path)
{
this.name = name;
this.path = path;
}

String getName ()
{
return name;
}

ImageIcon getFlagIcon ()
{
// Lazily load flag icon. Make sure that each country’s flag icon is
// loaded only once.

if (flagIcon == null)
flagIcon = new ImageIcon (path);

return flagIcon;
}

public int compareTo (Country o)
{
return name.compareTo (o.name);
}
}

class CountryCellRenderer extends JLabel implements ListCellRenderer
{
private Border border;

private JComboBox cb;

CountryCellRenderer (JComboBox cb)
{
this.cb = cb;

// Leave a 10-pixel separator between the flag icon and country name.

setIconTextGap (10);

// Swing labels default to being transparent; the container’s color
// shows through. To change a Swing label’s background color, you must
// first make the label opaque (by passing true to setOpaque()). Later,
// you invoke setBackground(), passing the new color as the argument.

setOpaque (true);

// This border is placed around a cell that is selected and has focus.

border = BorderFactory.createLineBorder (Color.RED, 1);
}

public Component getListCellRendererComponent (JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus)
{
Country c = (Country) value;
setText (c.getName ());
setIcon (c.getFlagIcon ());

if (isSelected)

{
setBackground (list.getSelectionBackground ());
setForeground (list.getSelectionForeground ());
}
else
{
setBackground (list.getBackground ());
setForeground (list.getForeground ());
}

setFont (list.getFont ());

// list.isEnabled() always returns true for a combobox’s list, even if
// the combobox is disabled.

setEnabled (cb != null ? cb.isEnabled () : list.isEnabled ());

if (isSelected && cellHasFocus) // cellHasFocus ignored for JComboBox
setBorder (border);
else
setBorder (null);

return this;
}
}

Listing 1 is organized into Countries, Country, and CountryCellRenderer classes. The main Countries class creates the user interface and stores the URLs of various flag icons along with country names into an array of Country objects. Each of these objects is passed to CountryCellRenderer’s getListCellRendererComponent() method to obtain a JLabel that can render the object.

These classes offer a variety of techniques that are worth remembering for your own Swing applications and custom cell renderers:

JFrame’s content pane defaults to a JPanel managed by a BorderLayout layout manager. Rather than wrap a component in a JPanel and add that panel to the content pane’s panel, to display the component at its preferred size, simply set the content pane’s panel’s layout manager to a FlowLayout, which makes every effort to display components at their preferred sizes. Wrapping a component in a JPanel, which is then added to the content pane’s panel, also works (but results in unnecessary JPanel creation) because JPanel’s default layout manager is FlowLayout.
Java SE 6 introduced the void setAlignOnBaseline(boolean alignOnBaseline) method to FlowLayout to allow components to be vertically aligned according to their baselines (when true is passed to alignOnBaseline). This method makes it possible to present the combobox near the top of its container instead of in the middle.
An instance of a custom cell renderer class can be shared among multiple JLists and JComboBoxs provided that the class provides no instance-specific fields. For example, Listing 1’s CountryCellRenderer class contains a cb field. This field is set to null if the custom cell renderer is assigned to a JList, or the JComboBox instance on which the custom cell renderer is being assigned. The JComboBox is needed to determine if this component is disabled, whereas the list reference passed to getListCellRendererComponent() is sufficient for determining whether a JList is disabled. Because the cb field has a dual role, Listing 1 requires two instances of CountryCellRenderer.
The Country class’s getFlagIcon() method uses ImageIcon to load the flag icon. It lazily loads this icon when actually required, and also to ensure that the flag icon is loaded only once — the custom cell renderer invokes getFlagIcon() multiple times for each country.
The Country class implements Comparable to allow the array of Country objects (created in the Countries class’s createCountriesArray() method) to be sorted (via Arrays.sort()) according to country name.
DefaultListCellRenderer supports setting a border for a focused JList’s selected item. CountryCellRenderer’s getListCellRendererComponent() method also sets a red border for the selected item of a focused JList, to show that this component is focused. Rather than create a border object each time getListCellRendererComponent() is invoked, which is inefficient, I create the border exactly once, in CountryCellRenderer’s constructor.
Although it’s convenient for CountryCellRenderer to offload the rendering task to JLabel, which handles icon and text rendering, there is a problem with JLabel that must be overcome before it can be used to show a selected item. Specifically, JLabel’s opacity defaults to transparent, which allows the underlying container’s background color to show through. As a result, a selection bar never appears. You can fix this problem by making JLabel opaque, which is accomplished in CountryCellRenderer’s constructor.
Finally, it’s important to create as few objects as possible in getListCellRendererComponent() because this method is frequently called. Creating too many objects on the heap can lead to garbage collections pauses that can disrupt the smooth flow of program execution. Fortunately, getListCellRendererComponent() creates no objects (unless I’m mistaken). Furthermore, it reuses the same JLabel object.
After compiling Countries.java, it’s easy to package this application into an executable JAR file by first creating a manifest file that contains Main-Class: Countries and (assuming the manifest file is named manifest.mf) executing jar cfm Countries.jar manifest.mf *.class icons. You then specify java -jar Countries.jar to execute this application.

With a bit of work, the previous cell-rendering material could be turned into a recipe in the hypothetical Swing cookbook’s chapter on JList and JComboBox. (Recipes on rendering table and tree cells could appear in chapters that deal with JTable and JTree.) However, is creating a Swing cookbook a good idea, especially in light of JavaFX, which simplifies user interface development?

Posted in swings | Tagged: | Leave a Comment »

Struts2 Spring plugin can be called multiple times at startup

Posted by damuchinni on March 8, 2009

I have been writing a web application that has a plugin framework. The plugins needed to be Struts2 and Spring aware so that they would have tight integration into the web application. In order to make things easier I have been using the struts-spring-plugin.jar that comes bundled with the Struts2 download. The problem was that the following happened when my application initialised:

The Struts2 framework would initialise and call the struts-spring-plugin to set the Spring ApplicationContext;
My PluginManager would initialise and set the Spring ApplicationContext within Struts so that my plugins Spring beans would be included and could be found by both Struts and Spring;
The struts-spring-plugin would be called again and overwrite my Spring ApplicationContext that I had just set.
I tried to track down that third call but could find out where it originated from, all I could get is that it came from a class that was instantiated through the sun reflection classes. Once I had figured out the problem the solution is pretty simple. Just create a copy of the org.apache.struts2.spring.StrutsSpringObjectFactory (from the struts-spring-plugin.jar) in your project and modify it as follows:

try {
// Try and set the SpringObjectFactory with the last child of the Spring ApplicationContexts tree from the MyPluginManager.
MyPluginManager myPluginManager = MyPluginManager.getInstance();
setApplicationContext(myPluginManager.getPluginsXmlWebApplicationContext());

} catch (ExceptionMyPluginManagerNotInitialised empmni) {
// We couldn’t set the applicationContext with the one from the MyPluginManager so use the default
setApplicationContext(appContext);
}

The MyPluginManager is the class that manages my plugins. When it initialises the plugins it stores the XmlWebApplicationContext used to initialise that plugin. Each plugin has a new XmlWebApplicationContext that has either the ROOT XmlWebApplicationContext or the last pluginXmlWebApplicationContext as the parent. This means that the last pluginXmlWebApplicationContext is the last in the chain of XmlWebApplicationContext and so can see all of the spring beans from the root context AND the plugins. That is the XmlWebApplicationContext that is used in the above codes call to:

setApplicationContext(myPluginManager.getPluginsXmlWebApplicationContext());

Now Struts uses my child XmlWebApplicationContext and not the ROOT XmlWebApplicationContext.

Posted in Java, Springs, struts | Tagged: , , , | Leave a Comment »

SwingPad 0.2 update

Posted by damuchinni on March 2, 2009

The release of Griffon 0.1 is quickly approaching (files for the 0.1-RC2 distribution are ready), this means SwingPad 0.2 will also be released soon, in the meantime it has been updated with MacWidgetsBuilder’s latest version and the brand new SwingxtrasBuilder. But the news do not stop here, there are two new features that will help you get acquainted with SwingBuilder nodes

* Ctrl-SPACE – will display an autocompletion popup window, it only works for node names.
* Node list table – filterable by builder, group, node name.

Here is an snapshot of the second feature:

Swingpad-0.2-nodelist

Stay tuned for more SwingPad news in the coming days.

Posted in swings | Tagged: | Leave a Comment »

Java desktop links of the week, March 2nd

Posted by damuchinni on March 2, 2009

Wow – it’s March already – where does time go? Here are the links from the last week that I think were important – as always, email/twitter/courier pigeon me any news that you think is relevant. Have a great week!
Swing

* As always, Alex Ruiz (@alexRuiz) has been busy, this week announcing the 1.1 release of FEST-Swing which is a Java library that provides a fluent interface for functional Swing GUI testing.
* Ken Orr has announced that he will be at JavaOne, presenting on the topic of component-oriented design. This will be an interesting talk, given the inheritance-oriented design that went into Swing, and the issues that has created, particularly in terms of method-overload.
* elliotth gave the Swing 2.0 counter-argument this week, suggesting that the point of Swing 2.0 is misguided and irrelevant. For the purposes of proper and full discourse, I appreciate his post, although I wish he had comments enabled so that a discussion could occur.

JavaFX

* Michael Heinrichs has posted the third in his series of blog posts about best practices for JavaFX mobile. I never knew of this blog until now. The first post suggests to avoid unnecessary bindings, the second post suggests to keep the scenegraph as small as possible, and the third post has two tips: use simple shapes over images, and use small shapes over complex shapes.
* More demos have been developed to show off the ease of developing in JavaFX. JFXStudio has a simple ’sink a ship’ game, Sergey Malenkov has posted a demo that creates a fireworks display (which Kirill Grouchnikov (@kirillcool) recreated in his Trident animation framework), and Santiago Pericas-Geertsen has created a Space Invaders-esque game for JavaFX.

Posted in JSF, swings | Tagged: , , , | Leave a Comment »