Die Diamand-Schreibweise zur Abkürzung von generischen Instanziierungen ist in Java 7 Build 72 eingegangen.
- http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6840638
- http://download.java.net/jdk7/changes/jdk7-b72.html
- http://download.java.net/jdk7/
Die Diamand-Schreibweise zur Abkürzung von generischen Instanziierungen ist in Java 7 Build 72 eingegangen.
Findbugs http://findbugs.sourceforge.net/ hat die Versionsnummer erhöht und unter anderem neue Detektoren aufgenommen. Von der Webseite:
- New bug patterns; in some cases, bugs previous reported as other bug patterns are reported as instances of these new bug patterns in order to make it easier for developers to understand the bug reports
- BC_IMPOSSIBLE_DOWNCAST
- BC_IMPOSSIBLE_DOWNCAST_OF_TOARRAY
- EC_INCOMPATIBLE_ARRAY_COMPARE
- JLM_JSR166_UTILCONCURRENT_MONITORENTER
- LG_LOST_LOGGER_DUE_TO_WEAK_REFERENCE
- NP_CLOSING_NULL
- RC_REF_COMPARISON_BAD_PRACTICE
- RC_REF_COMPARISON_BAD_PRACTICE_BOOLEAN
- RV_RETURN_VALUE_OF_PUTIFABSENT_IGNORED
- SIC_THREADLOCAL_DEADLY_EMBRACE
- UR_UNINIT_READ_CALLED_FROM_SUPER_CONSTRUCTOR
- VA_FORMAT_STRING_EXPECTED_MESSAGE_FORMAT_SUPPLIED
- Providing a bug rank (1-20), and the ability to filter by bug rank. Eventually, it will be possible to specify your own rules for ranking bugs, but the procedure for doing so hasn’t been specified yet.
- Fixed about 45 bugs filed through SourceForge
- Various reclassifications and priority tweaks
- Added more bug annotations to a variety of bug reports. This provides more context for understanding bug reports (e.g., if the value in question was is the return value of a method, the method is described as the source of the value in a bug annotation). This also provide more accurate tracking of issues across versions of the code being analyzed, but has the downside that when comparing results from FindBugs 1.3.8 and FindBugs 1.3.9 on the same version of code being analyzed, FindBugs may think that mistakenly believe that the issue reported by 1.3.8 was fixed and a new issue was introduced that was reported by FindBugs 1.3.9. While annoying, it would be unusual for more than a dozen issues per million lines of codes to be mistracked.
Schreibe eine Klasse Location, die longitude und latitude speichert. Die Attribute sind vom Type double. Gib Setter/Getter an und einen Standard- und parametrisieren Konstruktor. Die Klasse Location soll die Abstands-Utility-Funktionen aus http://www.tutego.de/blog/javainsel/2009/09/latitudelongitude-distance-in-java/ bekommen.
Die Klasse Locations soll beliebig viele Location-Objekte speichern können. Dazu ist eine addLocation()-Methode nötig, die einen Ort als String mit einer Location annimmt und in eine intern Datenstruktur übernimmt. addLocation() soll überladen sein, dass man einmal den Ort über ein Location-Objekt bestimmt und einmal über Longitude und Latitude. Eine toString()-Methode soll angeben, wie viele Orte enthalten sind. Eine Methode Location findLocation(String location) soll die Location für einen Ort zurückgeben. Schreibe eine Methode List within(Location loc, double radius) Methode, die alle Orte liefert, die nicht weiter als radius von dem Ort entfernt sind. Nutzt die passende statische Funktionen aus Location für den Abstand! Nimm eine überladene Methode within() hinzu, die eine maximale Anzahl Elemente in der Rückgabeliste bestimmt.
Schreibe eine Klasse LocationApplication mit einem main(). Füge einige Location-Objekte ein und teste die Bereichsabfrage.
Eine Klasse LocationRepository soll zwei statische Methoden enthalten: Locations loadLocations() und void saveLocations(Locations locations). Die Methoden sollen Locations aus einer Text-Datei lesen und schreiben können. Nutze dazu beliebige Geokoordinaten. Das Dateiformat kann frei bestimmt werden.
Passe die Methode within() an, so dass die Liste sortiert ist nach dem Abstand zum Anfrageort. Schreibe dazu einen DistanceComparator und nutze die Collections.sort()-Methode.
Modelliere mit NetBeans eine grafische Oberfläche, mit zwei Reitern (JTabbedPane). In dem ersten Reiter soll man drei Textboxen haben für Ort, Longitude, Latitude und einen „Hinzufügen“ Button. Damit sollen neue Orte dem Locations hinzugefügt werden. Auf dem zweiten Reiter soll der Anwender Abfragen vornehmen können. Eine Eingabezeile für ein Ort (oder Longitude, Latitude) und Radius soll zu max. 10 Ergebnissen führen.
Installiere Google Earth. Bei einer Bereichsabfrage erzeugte eine KML-Datei mit allen Ergebnissen. Diese Datei soll beim Start von Google Eath als Startparameter mitgegeben werden. Externe Programme startet man mit dem ProcessBuilder. Die Insel gibt ein Beispiel für diese Klasse. Überlegen, wie am einfachsten und effektivsten XML geschrieben werden kann.
public class LongLatUtils
{
/**
* Calculates the great circle distance between two points on the Earth. Uses the Haversine Formula.
*
* @param latitude1 Latitude of first location in decimal degrees.
* @param longitude1 Longitude of first location in decimal degrees.
* @param latitude2 Latitude of second location in decimal degrees.
* @param longitude2 Longitude of second location in decimal degrees.
* @return Distance in meter.
*/
public static double distance( double latitude1, double longitude1, double latitude2, double longitude2 )
{
double latitudeSin = Math.sin( Math.toRadians(latitude2 - latitude1) / 2 );
double longitudeSin = Math.sin( Math.toRadians(longitude2 - longitude1) / 2 );
double a = latitudeSin * latitudeSin
+ Math.cos( Math.toRadians(latitude1)) * Math.cos(Math.toRadians(latitude2) ) * longitudeSin * longitudeSin;
double c = 2 * Math.atan2( Math.sqrt(a), Math.sqrt(1 - a) );
return 6378137 * c;
}
/**
* Converts latitude and longitude from degrees, minutes, and seconds in decimal degrees.
*
* @param degrees
* @param minutes
* @param seconds
* @return Latitude and longitude in decimal degrees.
*/
public static double convertDegreesMinutesSecondsToDecimalDegrees( int degrees, int minutes, int seconds )
{
return degrees + minutes/60. + seconds/3600.;
}
// public static void main(String[] args)
// {
// System.out.println( convertDegreesMinutesSecondsToDecimalDegrees(38, 53, 23 ));
// System.out.println( distance(38.898556, -77.037852, 38.897147, -77.043934));
// }
}
Das schreibt Joseph D. Darcy in seinem Blog http://blogs.sun.com/darcy/entry/project_coin_final_five (und bei Java.net http://weblogs.java.net/blog/forax/archive/2009/08/29/seven-small-languages-changes-will-be-jdk7).
Improved Type Inference for Generic Instance Creation (diamond)
An omnibus proposal for better integral literals (also binary literals and underscores in numbers)
Language support for Collections
Die Spezifikationen stehen im Einzelnen noch nicht fest.
Raus sind erst einmal
und auch alle anderen Dinge.
Das alles erscheint mir schon mehr merkwürdig in der Auswahl. Improved Exception Handling for Java war so ein heißer Kandidat und wird es nun doch nicht.
Deadline ist Ende Oktober.
Steve Ebersole schreibt auf seinem Blog http://in.relation.to/12153.lace dazu:
This is the first release towards supporting JPA 2. Most of the APIs are implemented. Some know limitations for this beta include:
- Some of the ‚metamodel‘ APIs are still unimplemented, specifically differentiating between declared attributes and attributes (same wording as java.lang.reflect). The getDeclaredXYZ methods simply return null in this release.
- ‚criteria‘ query building is fully implemented aside from defining subquery correlations, to the best of my knowledge and current state of the spec. However, compiling criteria queries is unimplemented scheduled for the next release.
Additionally, initial support for
fetch profileshas been added in this release. Currently only join-fetching is supported as a strategy in fetch profiles.The artifacts have all been published to the JBoss Maven repository. Additionally the release bundles have been uploaded to SourceForge.
This is also the first version bundling annotations, entitymanager and envers together with the other core modules. Moving forward all will be versioned and released together.
Das Video gibt es bei Sun unter http://java.sun.com/developer/media/deepdivejdk7.jsp. Es zeigt die 5 Top-Features, die in Java 7 erwartet werden. Das Interview erwähnt noch das Swing Application Framework, was aber gestorben ist.
Unter http://weblogs.java.net/blog/alexfromsun/archive/2009/08/saf_and_jdk7.html ist von Alexander Potochkin nun zu lesen:
After much discussion it’s become clear that the Swing Application Framework API as it is today hasn’t reached consensus and we feel still needs further design work done.
Since the SAF API was committed to milestone 5 of JDK7 and that time is already here, this date is now impossible, and we need to decommit SAF from any specific JDK 7 milestone
Die Ankündigung von SpringSource liest sich so:
Together, VMware and SpringSource plan to further innovate and develop integrated Platform as a Service (PaaS) solutions that can be hosted at customer datacenters or at cloud service providers. These solutions will allow customers to rapidly build new enterprise and web applications and run and manage these applications in the same dynamic, scalable and cost-efficient vSphere-based internal or external clouds that can also host and manage their existing applications, providing an evolutionary path to the future.
Aus dem Blog http://www.jroller.com/sjivan/entry/smartgwt_1_2_released:
SmartGWT 1.2 has been released. I have added several new samples to the Showcase including a real world mini-application. The other new samples can be found under the „New Samples“ side nav item.
This is a feature-complete production ready release. There are only around 20 enhancement requests and 20 low / medium priority issues in the SmartGWT tracker which I think is pretty telling for such a comprehensive library. I hope to get to them over the weeks to come.
Here are some of the key features of this release :
- GWT 1.7 is fully supported and integration with GWT widgets has been improved significantly. Along with standard GWT widgets, you can now easily add Google Maps or even a Google Visualization Chart to your SmartGWT application
- Hosted mode performance improvements
- Fully implemented the highly requested ResultSet API.
- ListGrid performance improvements
- Full Support for Safari 4.x
- Support for Grid editing with all cell editors active
- Auto-loading of dependent XML schema for loadWSDL() and loadXMLSchema()
- Extended WebService APIs to allow simplified input data and allow setting SOAP headers
- Numerous enhancements. See the detailed API Changes document. Around 35 additional enhancements and bug fixes that were logged in tracker
- Official Maven Repository
- Enhancements to RPC Tab in Developer Console (shows component that initiated request, if applicable)
Looking ahead there are several exciting new features that are going to be in the next release. Deep level of customization of pretty much any widget is going to be supported. For example you’ll be able to fully customize grid headers, provide your own widget implementation to use as a Tile in a TileGrid, or even customize pretty much any aspect of the Calendar component.
Gibt es nun auch zum Downloaden unter http://bits.netbeans.org/netbeans/6.8/m1/. Und die News gibt es hier unter http://wiki.netbeans.org/NewAndNoteworthyNB68. Interessant ist:
Ein großartiges Projekt ist http://www.xmlvm.org/. Es steht zwar erst am Anfang, aber der sieht sehr vielversprechend aus. Die Idee von XMLVM ist einfach: Man nehme den Bytecode, repräsentierte diesen als XML, transformiere den über XSLT in Objective C und kompilieren dann.

(Bilder von der Webseite)

Die Stack-Operationen vom Java-Bytecode werden über XSLT einfach in Objective C abgebildet, wobei die Stack-Operationen beibehalten werden. Die Mühe über einen internen AST oder so macht man sich nicht.
<xsl:template match=“jvm:irem“>
<xsl:text>
_op2.i = _stack[–_sp].i; // Pop operand 1
_op1.i = _stack[–_sp].i; // Pop operand 2
_stack[_sp++].i = _op1.i % _op2.i; // Push remainder
</xsl:text>
</xsl:template>
Das gibt zwar für den GCC ‘ne Menge zu optimieren, aber das ist der einfachste Weg der Transformation. Später sieht das dann so aus:
@interface org_xmlvm_test_HelloWorld : java_lang_Object
+ (void) main___java_lang_String_ARRAYTYPE :(NSMutableArray*)n1;
@end
@implementation org_xmlvm_test_HelloWorld;
+ (void) main___java_lang_String_ARRAYTYPE :(NSMutableArray*)n1
{
XMLVMElem _stack[2];
XMLVMElem _locals[1];
int _sp = 0;
XMLVMElem _op1, _op2, _op3;
int _i;
for (_i = 0; _i <1; _i++) _locals[_i].o = nil;
NSAutoreleasePool* _pool = [[NSAutoreleasePool alloc] init];
_locals[0].o = n1;
_op1.o = [java_lang_System _GET_STATIC_java_lang_System_out];
_stack[_sp++].o = _op1.o;
_stack[_sp++].o = @“Hello World“;
_sp -= 2;
[((java_io_PrintStream*) _stack[_sp].o) println___java_lang_String:_stack[_sp + 1].o];
[_pool release];
return;
}
@end
Weitere Beispiele gibt http://xmlvm.org/showcase/ und der Blog http://www.cokeandcode.com/aboidblog.
Insgesamt ein sehr spannendes Projekt, welches auch die Frage Android –> iPhone Entwicklung angeht, und .NET -> Java Cross-Compilation bietet. Mal sehen, wie sich das Entwickeln wird. MONO für iPhone ist auch bald bereit und dann wird iPhone Entwicklung wirklich einfach. (Bekommen wir dann noch mehr Schrott im Store?)
Vom 25.-30. Juli lief in in den USA die Sicherheitsmesse Black Hat. Dort hat Jesse Burns in einem Vortrag die Sicherheitsarchitektur von Android vorgestellt. Sein Paper dazu kann man hier (alternativ unter http://www.isecpartners.com/files/iSEC_Securing_Android_Apps.pdf) runterladen.
Weiterhin lesenswert ist
Das geht nicht wirklich und wenn, dann nur mit großen Umwegen etwa über die Java Debugging API, mit der man sich an die JVM hängen kann. Auch ein Blick auf den Quellcode von jconsole und jmap/jhat helfen hier, weil die Tools genau das machen und Zahlen geben.
Der Objektgraf verändert sich ständig und so könnte man auch die Objekte stark referenzieren und den GC am Löschen hindern. Das würde zu einer großen Anzahl von Problemen führen. (Schwache Referenzen könnte das Problem abmildern, aber der GC muss hier Zusatzarbeit machen und die Laufzeit würde sich (messbar) verschlechtern.) Die Objekte sind ja immer eine Momentaufnahme. Da kämen ja Millionen von Objekten raus, wenn man etwa nach „Gib mir alle Strings“ fragt. Laufend ändert sich diese Menge.
Wenn der Nutzer diese Instanzen wirklich braucht, kann er sie an einer Objekt-Registry anmelden.
Zur Abstraktion von Zugriffen auf konkreten Datastores (oft eine relationale Datenbank) haben sich DAOs (http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html) etabliert. Im Domain Driven Design (DDD) gibt es etwas, das so aussieht wie ein DAO, und zu großer Diskussion in der Community führt.
Lassen sich hier schon Unterschiede herausstellen?
Verfolge den “Streit” über den Unterschied zwischen Repos/DAO in den Blogs
Fragen:
Optional. Wie sieht Paginierung aus? http://tech.groups.yahoo.com/group/domaindrivendesign/message/5795
Um in der Google Cloud Daten zu speichern bietet Google drei API an: JPA, JDO und eine Low-Level-API. Infos dazu gibt liefert http://code.google.com/intl/de/appengine/docs/java/datastore/. JPA und JDO basieren im Kern auf der Low-Level API, die auf die http://en.wikipedia.org/wiki/BigTable zurückgreift.
Für JPA und JDO gibt es selbst von Google viele Beispiele, aber die Low-Level-API ist nicht so gut dokumentiert und selbst das Beispielprogramm in der JavaDoc enthält Fehler. Zeit daher, ein sehr einfaches Beispiel mit einer 1:n Relationen anzugehen.
Im Mittelpunkt der API steht der DatastoreService, der ein bisschen an den EntityManager von JPA erinnert. Er bietet Methoden für die CRUD-Operationen. Mein Beispiel geht schon ein bisschen “pseudo-ORM” an die Aufgabe ran, einer Person Nachrichten zuordnen zu können:
Die Personen-Klasse:
package com.tutego.server.entity;
import java.util.ArrayList;
import java.util.List;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.Query;
public class Person
{
private final static String ENTITY_NAME = „Person“;
Entity personEntity;
public enum Gender
{
MALE, FEMALE
}
public Person()
{
personEntity = new Entity( ENTITY_NAME );
}
private Person( Key key )
{
try
{
personEntity = DatastoreServiceFactory.getDatastoreService().get( key );
}
catch ( EntityNotFoundException e )
{
}
}
private Person( Entity entity )
{
personEntity = entity;
}
public static Person get( Key key )
{
return new Person( key );
}
public void setUsername( String username )
{
personEntity.setProperty( „username“, username );
}
public String getUsername()
{
return personEntity.getProperty( „username“ ).toString();
}
public void setGender( Gender gender )
{
personEntity.setProperty( „gender“, gender.toString() );
}
public Gender getGender()
{
return Gender.valueOf( personEntity.getProperty( „gender“ ).toString() );
}
public Key put()
{
return DatastoreServiceFactory.getDatastoreService().put( personEntity );
}
public static void deleteAll()
{
Query deleteAllQuery = new Query( ENTITY_NAME );
for ( Entity entity : DatastoreServiceFactory.getDatastoreService().prepare( deleteAllQuery ).asIterable() )
DatastoreServiceFactory.getDatastoreService().delete( entity.getKey() );
}
private static List<Person> executeQuery( Query query )
{
List<Person> result = new ArrayList<Person>();
for ( Entity entity : DatastoreServiceFactory.getDatastoreService().prepare( query ).asIterable() )
result.add( new Person( entity ) );
return result;
}
public static List<Person> findAllPersons()
{
Query query = new Query( ENTITY_NAME );
return executeQuery( query );
}
public static List<Person> findPersonByGender( Gender gender )
{
Query query = new Query( ENTITY_NAME );
query.addFilter( „gender“, Query.FilterOperator.EQUAL, gender.toString() );
return executeQuery( query );
}
@Override
public String toString()
{
return String.format( „Person[%s,%s]“, getUsername(), getGender() );
}
}
Die Nachrichten-Klasse:
package com.tutego.server.entity;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.Query;
public class Message
{
private final static String ENTITY_NAME = „Message“;
private Entity messageEntity;
public Message()
{
messageEntity = new Entity( ENTITY_NAME );
}
private Message( Key key )
{
try
{
messageEntity = DatastoreServiceFactory.getDatastoreService().get( key );
}
catch ( EntityNotFoundException e )
{
}
}
private Message( Entity entity )
{
messageEntity = entity;
}
public static Message get( Key key )
{
return new Message( key );
}
public void setText( String text )
{
messageEntity.setProperty( „text“, text );
}
public String getText()
{
return messageEntity.getProperty( „text“ ).toString();
}
public void setCreationTime( Date d )
{
messageEntity.setProperty( „creationtime“, „“ + d.getTime() );
}
public Date getCreationTime()
{
return new Date( Long.parseLong( messageEntity.getProperty( „creationtime“ ).toString() ) );
}
public void setReceiver( Person p )
{
messageEntity.setProperty( „person_fk“, p.personEntity.getKey() );
}
public Key put()
{
return DatastoreServiceFactory.getDatastoreService().put( messageEntity );
}
private static List<Message> executeQuery( Query query )
{
List<Message> result = new ArrayList<Message>();
for ( Entity entity : DatastoreServiceFactory.getDatastoreService().prepare( query ).asIterable() )
result.add( new Message( entity ) );
return result;
}
public static List<Message> findMessagesForPerson( Person p )
{
Query query = new Query( ENTITY_NAME );
query.addFilter( „person_fk“, Query.FilterOperator.EQUAL, p.personEntity.getKey() );
return executeQuery( query );
}
@Override
public String toString()
{
return String.format( „Message[%s,%s]“, getCreationTime(), getText() );
}
}
Getestet werden soll das ganze in einer einfachen Server-Funktion:
StringWriter sw = new StringWriter();
PrintWriter out = new PrintWriter( sw );
// Insert new entity
Person p1 = new Person();
p1.setUsername( „chris“ );
p1.setGender( Person.Gender.MALE );
Key key1 = p1.put();
out.println( „* Key für erste Person “ + p1 );
out.println( KeyFactory.keyToString( key1 ) );
Person p2 = new Person();
p2.setUsername( „pallas“ );
p2.setGender( Person.Gender.FEMALE );
p2.put();
Person p3 = new Person();
p3.setUsername( „tina“ );
p3.setGender( Person.Gender.FEMALE );
p3.put();
// Search for entity with a given key
Person p = Person.get( key1 );
out.println( „* Suche mit Schlüssel “ + key1 );
out.println( p.getUsername() );
// Query
List<Person> findAll = Person.findAllPersons();
out.println( „* Alle Personen“ );
out.println( findAll.toString() );
// Query
List<Person> females = Person.findPersonByGender( Gender.FEMALE );
out.println( „* Alle Frauen:“ );
out.println( females.toString() );
Message msg1 = new Message();
msg1.setText( „Hallo Maus“ );
msg1.setCreationTime( new Date(1) );
msg1.setReceiver( p );
msg1.put();
Message msg2 = new Message();
msg2.setText( „Hallo Ratte“ );
msg2.setCreationTime( new Date(2) );
msg2.setReceiver( p );
msg2.put();
out.println( „* Alle Nachrichten für “ + p );
out.println( Message.findMessagesForPerson( p ) );
out.println( „\n“ );
// Clean up
Person.deleteAll();
out.flush();
return sw.toString().replace( „\n“, „<br/>“ );
Als Ergebnis kommt HTML zurück, was der Client zum Testen anschauen kann.
Die Listen http://java-source.net/open-source/web-frameworks und http://de.wikipedia.org/wiki/Liste_von_Webframeworks geben eine fast unendliche Aufzählung von Web-Frameworks an. Selbst bin ich ein Freund (je nach Anwendungsfall) von GWT, JSF 2.0 und Stripes.
Stripes is a presentation framework for building web applications using the latest Java technologies. The main driver behind Stripes is that web application development in Java is just too much work! It seems like every existing framework requires gobs of configuration. Struts is pretty feature-light and has some serious architectural issues (see Stripes vs. Struts for details). Others, like WebWork 2 and Spring-MVC are much better, but still require a lot of configuration, and seem to require you to learn a whole new language just to get started.
Stripes fällt die Kategorie der Action-orientierten Frameworks, wie Struts oder Spring MVC. Ein Front-Controller nimmt den Request entgegen und delegiert auf eine ActionBean-Klasse, die den Seitenfluss auf eine andere Zielseite steuert.
Aufgaben:
Trivia: Frederic Daoud ist der Autor vom Standard-Stripes Buch “Stripes: …and Java Web Development Is Fun Again”. Frederic und seine Frau Nadia haben ein zweites Kind bekommen und es Ruby genannt.

Zum Layout von GWT-Komponenten ist es unerlässlich zu verstehen, was GWT für ein DOM erzeugt. Zum einen sind da Werkzeuge wie FireBug unerlässlich und zum Anderen kann man sich vorher schon bei http://javabyexample.wisdomplug.com/component/content/article/75.html informieren, was GWT für eine Struktur erzeugen wird.
Schnell entstehen bei GWT-Anwendungen eine Unzahl geschachtelter Tabellen. Sie sind für die Performance der Darstellung nicht unerheblich, denn wenn man das Fenster zum Beispiel in der Größe ändert, so müssen die ganzen Größeninformationen neu berechnet werden.
Um das HTML schlank zu halten, lässt sich auf alternative Container zurückgreifen. Wer zum Beispiel horizontal oder vertikal anordnen will, greift sofort zum HorizontalPanel bzw. VerticalPanel. Doch zur Umsetzung setzt eben GWT eine Tabelle ein. Wenn man nur zum Beispiel eine Zeile wie “blal@googlemail.com | My favorites | Profile | Sign out” aufbauen möchte, ist das HorizontalPanel unnötig und schwergewichtig. Es bietet sich an, eine neue Panel-Klasse zu nutzen, etwa wie sie etwa http://blog.sudhirj.com/2009/05/vertical-and-horizontal-flow-panels-in.html vorstellt. Etwas komprimiert:
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Widget;
public class HorizontalFlowPanel extends FlowPanel
{
@Override
public void add( Widget w )
{
w.getElement().getStyle().setProperty( „display“, „inline“ );
super.add( w );
}
}
Diese Implementierung führt nur zu einem <div>-Block statt einer <table>.