Update von Swing Look and Feel Synthetica V2.9 – tolle Screenshots
2 Kommentar(e). Veröffentlicht von Christian Ullenboom am Sonntag, November 22, 2009.Die Version 2.9 verbesser der Aussehen insbesondere bei den neuen Java 6 Updates. Infos gibt http://weblogs.java.net/blog/wzberger/archive/2009/11/22/synthetica-blackeye-highlights.



![]()
![]()



Labels: Open Source, Swing
Der vorgegebene Konstruktor (engl. default constructor) und Begriffsverwirrungen
5 Kommentar(e). Veröffentlicht von Christian Ullenboom am Samstag, November 21, 2009.Wenn wir in unserer Klasse überhaupt keinen Konstruktor angeben, legt der Compiler automatisch einen an. Dieser Konstruktor nennt Sun default constructor, was wir als vorgegebener Konstruktor (selten auch Vorgabekonstruktor) eindeutschen wollen.
Schreiben wir nur
class Player
{
}
macht der Compiler daraus immer automatisch:
class Player
{
Player() { }
}
Der vorgegebene Konstruktor hat immer die gleiche Sichtbarkeit wie die Klasse. Ist also die Klasse public/private/protected, wird auch der automatisch eingeführte Konstruktor public/private/protected sein. Ist die Klasse paketsichtbar, ist es auch der Konstruktor.
Vorgegebener und expliziter Standard-Konstruktor
Ob ein parameterloser Konstruktor vom Compiler oder Entwickler angelegt wurde ist ein Implementierungsdetail, der für Nutzer der Klasse irrelevant ist. Daher ist es im Grunde egal, ob wir einen Standard-Konstruktor selbst anlegen oder wir uns einen vorgegebenen Konstruktor vom Compiler generieren lassen: im Bytecode lässt sich das nicht mehr unterscheiden. Selbst die JavaDoc API-Dokumentation, von einer public class C1 {} und public class C2 { public C2(){} } wäre strukturell gleich.
Bytecode der Klassen C1 und C2 im Vergleich
In der Begriffswelt der Insel heißt ein parameterloser Konstruktor immer Standard-Konstruktor, was natürlich den Unterschied verschwimmen lässt, ob der Standard-Konstruktor von Hand angelegt wurde oder als vorgegebener Konstruktor vom Compiler eingeführt wurde. Um das noch klarer zu unterscheiden, können wir es mit vorgegebener (Standard-)Konstruktor und expliziter Standard-Konstruktor weiter präzisieren.
Auch wenn der Compiler einen vorgegeben Konstruktor anlegt, ist es oft sinnvoll, einen eigenen Standard-Konstruktor anzugeben, auch wenn der Rumpf leer ist. Ein Grund ist, ihn zu mit JavaDoc zu dokumentieren, eine anderer, die Sichtbarkeit explizit zu wählen, etwa wenn die Kasse public ist, aber der Konstruktor nur die Paketsichtbarkeit haben soll.
| Begrifflichkeit I In der Java-Language Specification gibt es bei den Konstruktoren nur die Trennungen in no-arg-constructor (parameterloser Konstruktor) und default constructor (vorgegebener Konstruktor), aber den Begriff „standard constructor“ gibt es nicht. Viele Autoren übersetzen die englische Bezeichnung „default constructor“ (unserem vorgegebenen Konstruktor) einfach nur mit „Standard-Konstruktor“. |
| Begrifflichkeit II Einige Autoren nennen nur den vom Entwickler explizit geschriebenen parameterlosen Konstruktor „Standard-Konstruktor“ und trennen dies sprachlich vom Compiler generierten Konstruktor, den sie weiterhin „Default-Konstruktor“ nennen. Beide werden dann zusammengefasst einfach parameterlose Konstruktoren genannt. Wenn also etwa die Frage gestellt wird, ob die Deklaration class C { } einen Standard-Konstruktor enthält, ist die Begrifflichkeit des Autors zu prüfen. Wenn der Autor nur den ausprogrammierten parameterlosen Konstruktor „Standard-Konstruktor“ genannt hat, so hätte die Klasse C nach dessen Definition keinen „Standard-Konstruktor“. Nach der Insel-Definition hätte die Klasse zwar einen vorgegebenen (Standard-)Konstruktor, aber keinen expliziten Standard-Konstruktor. |
Labels: Insel
Frustrierend: Java 7 doch später
0 Kommentar(e). Veröffentlicht von Christian Ullenboom am Donnerstag, November 19, 2009.Heute auf der Devoxx Konferenz gab es die Info, dass wegen der neuen Spracheigenschaften sich Java 7 von Februar auf etwa September verschieben wird. Immerhin wird es dann wohl Closures geben und das Projekt Coin wird vermutlich noch mehr aufnehmen, etwa die Aufzählung von mehreren Exceptions im catch-Block.
Labels: Java 7
Überraschung: Wohl doch Closures in Java 7
1 Kommentar(e). Veröffentlicht von Christian Ullenboom am Donnerstag, November 19, 2009.GWT 2.0 RC1 ist raus, Updates beim Google Eclipse Plugin
1 Kommentar(e). Veröffentlicht von Christian Ullenboom am Mittwoch, November 18, 2009.Infos dazu hier: http://code.google.com/p/google-web-toolkit/wiki/GWT_2_0_RC.
Major New Features in the GWT SDK
- In-Browser Development Mode
- Prior to 2.0, GWT hosted mode provided a special-purpose "hosted browser" to debug your GWT code. In 2.0, the web page being debugged is viewed within a regular-old browser. Development mode is supported through the use of a native-code plugin called the "Google Web Toolkit Developer Plugin" for many popular browsers. In other words, you can use development mode directly from Safari, Firefox, IE, and Chrome.
- Developer-guided Code Splitting
- Code splitting using GWT.runAsync(), along with compile reports (also known as The Story of Your Compile) allows you to chunk your GWT code into multiple fragments for faster startup. Imagine having to download a whole movie before being able to watch it. Well, that's what you have to do with most Ajax apps these days -- download the whole thing before using it. With code splitting, you can arrange to load just the minimum script needed to get the application running and the user interacting, while the rest of the app is downloaded as needed.
- Declarative User Interfaces with UiBinder
- GWT's UiBinder now allows you to create user interfaces mostly declaratively. Previously, widgets had to be created and assembled programmatically, requiring lots of code. Now, you can use XML to declare your UI, making the code more readable, easier to maintain, and faster to develop. The Mail sample has been updated to show a practical example of using UiBinder.
- Bundling of Resources via ClientBundle
- GWT introduced ImageBundle in 1.4 to provide automatic spriting of images. ClientBundle generalizes this technique, bringing the power of combining and optimizing resources into one download to things like text files, CSS, and XML. This means fewer network round trips, which in turn can decrease application latency -- especially on mobile applications.
- Simplified Unit Testing with HtmlUnit
- Using HtmlUnit for running test cases based on GWTTestCase: Prior to 2.0, GWTTestCase relied on SWT and native code versions of actual browsers to run unit tests. As a result, running unit tests required starting an actual browser. As of 2.0, GWTTestCase no longer uses SWT or native code. Instead, it uses HtmlUnit as the built-in browser. Because HtmlUnit is written entirely in the Java language, there is no longer any native code involved in typical test-driven development. Debugging GWT Tests in development mode can be done entirely in a Java debugger.
Major New Features in the Google Plugin for Eclipse
- Development Mode Launch View
- Integrates your Development Mode logs right into Eclipse, which means one less window to shuffle around
- UiBinder Support
- The UiBinder template editor provides auto-completion and formatting for editing ui.xml files (and embedded CSS blocks)
Validation of UiBinder templates and backing Java classes
New UiBinder wizard to quickly get started- ClientBundle Support
- "New ClientBundle" wizard to bundle CSS and other resources together to minimize HTTP round-trips
As-you-type validation ensures that your app's static resources are always in the right place- RPC Refactoring
- Automatically updates sync/async pairs of RPC interfaces and their methods
- JNSI Reference Auto-completion
- Auto-completion takes the pain out of referencing Java members from JSNI methods
Labels: GWT, Open Source
Fork und Join aus Java 7
3 Kommentar(e). Veröffentlicht von Christian Ullenboom am Dienstag, November 17, 2009.- Threads: Werden vom Betriebssystem verwaltet und laufen entweder pseudo-parallel auf einem Prozessor/Core oder echt parallel. Threads können sich mit anderen Threads koordinieren. Zu viele Threads, die sich im Weg stehen und aufeinander Warten führen zu keiner verbesserten Ausführungszeit gegenüber einer sequentiellen Lösung.
- Tasks: Werden von Threads bzw. einem Thread-Pool ausgeführt. Sie sind Arbeitseinheiten, die nicht auf andere Tasks warten
Die Tasks sind kleine Arbeitspakete und werden in eine Task-Queue gelegt und dann von Threads abgearbeitet. Hat das System zwei Prozessoren und hat der Thread-Pool die Größe 2, so ist es wahrscheinlich, dass 2 Tasks parallel abgearbeitet werden. Gibt es 4 Prozessoren, können 4 Tasks vielleicht parallel laufen. Tasks lassen sich also grundsätzlich auf einer beliebigen Anzahl Threads und somit Prozessoren/Cores bringen, wobei im Gegensatz die Effektivität von Threads immer mit der physikalischen Anzahl von Prozessoren/Cores assoziiert ist.
Das Fork/Join-Framework löst die Probleme effektiv. Wie der Name schon andeutet, geht es bei Fork um das Erstellen eines neuen Tasks und bei Join um das Zusammenführen der Ergebnisse. Die Fork/Join-Bibliothek bietet dazu die Klasse ForkJoinPool und zwei zentrale Methoden: fork() und join(). Zur Abarbeitung der Tasks stellt das Framework die Threads zu Verfügung, deren Anzahl wir zwar selbst bestimmen können, aber die Anzahl Prozessoren/Cores eine gute Standardgröße ist.[1] Die Methode fork() erzeugt einen neuen Task, der an den Anfang (!) einer Queue gestellt wird. Dabei haben alle Threads eine Queue für ihre Arbeitsaufträge und sollte einmal eine Queue leer gelaufen sein, so nimmt sich der Thread einfach einen Task vom Ende (!) einer anderen nicht-leeren Queue. (Das nennt sich work-stealing und ist in der Realwelt ziemlich selten anzutreffen.) Dass neue Tasks an den Anfang gestellt werden ist einfach zu erklären: Die Tasks werden ja immer kleiner und somit stehen die kleinen, schnell lösbaren Aufgaben vorne. Erst später folgen die größeren Aufgaben, die auf die Ergebnisse der kleinen Aufgaben zurückgreifen, die dann logischerweise schon berechnet wurden.
Zur Theorie ein Beispiel: Es geht darum, mit Fork/Join ein Programm zu haben, welches parallel das Maximum eines Arrays sucht. Der Start ist:
int[] array = { 0, 9, 10, 111, 1, 12, 13, 14, 17 };
System.out.println( MaxElementInArrayFinder.findMax( array ) );
Die eigene Klasse MaxElementInArrayFinder bietet die Methode findMax(), die auf den ForkJoinPool zurückgreift, um mit invoke() den Haupt-Task abzusetzen.
class MaxElementInArrayFinder
{
private static final ForkJoinPool fjPool = new ForkJoinPool();
...
public static int findMax( int[] array )
{
return fjPool.invoke( new MaxElemTask( array, 0, array.length -1 ) );
}
}
Die Klasse MaxElemTask repräsentiert unser Arbeitspakt. Die Tasks referenzieren jeweils das Array, und die Anfangs-/Endeposition, ab der sie nach dem Maximum suchen sollen.
private static class MaxElemTask extends RecursiveTask<Integer>
{
private final int[] array;
private final int start, end;
MaxElemTask( int[] array, int start, int end )
{
assert array != null && start >= 0 && start <= end;
this.array = array;
this.start = start;
this.end = end;
}
@Override protected Integer compute()
{
…
}
}
Unsere Klasse erweitert die Basisklasse RecursiveTask<Integer> und deutet durch den generischen Typ schon an, das das Ergebnis des Tasks eine Ganzzahl sein wird, nämlich das Feldmaximum aus dem gewünschten Bereich. Der Konstruktor sichert die Werte und compute() führt die eigentliche Arbeit aus: Es löst entweder das Problem direkt, wenn es klein genug ist, oder spannt Unter-Tasks auf und wartet anschließend auf deren Ergebnisse.
@Override protected Integer compute()
{
assert array != null && array.length > 0;
System.out.printf( "max( start=%d, end=%d )%n", start, end );
if ( end - start < 4 )
{
int max = array[start];
for ( int i = start + 1; i <= end; i++ )
if ( array[i] > max )
max = array[i];
return max;
}
int middle = (start + end) / 2;
MaxElemTask leftTask = new MaxElemTask( array, start, middle );
leftTask.fork();
MaxElemTask rightTask = new MaxElemTask( array, middle + 1, end );
int rightMax = rightTask.compute();
int leftMax = leftTask.join();
return Math.max( rightMax, leftMax );
}
[1] Das die Maximalanzahl von Threads beim ForkJoinPool zurzeit 32767 ist, dürfte für normale Nutzer keine Einschränkung sein.
Algorithmendesign teile und herrsche
1 Kommentar(e). Veröffentlicht von Christian Ullenboom am Dienstag, November 17, 2009.Eine effektive Problemlösungsstrategie ist es, zunächst das Problem in Teilprobleme zu legen, dann die Teilprobleme zu lösen und anschließend zur Gesamtlösung zu kommen. Wer morgens im Bett liegt und Hunger verspürt, wird erst dann satt sein, wenn gewisse Teilprobleme gelöst sind. Diese Problemlösungsstrategie wird teile und herrsche (engl. divide and conquer, D&C[1]) genannt. Zunächst wird die Aufgabe ist kleine Häppchen zerlegt und anschließend abgearbeitet.
Teile und herrsche ist nicht nur eine Lösung, wie wir eine große Pizza „verarbeiten“, sondern auch in der Informatik eine beliebte algorithmische Methode: Das Hauptproblem wird in Teilprobleme zerlegt, die Teilprobleme dann gelöst und zur großen Lösung zusammengefügt. Zwei populäre Beispiele sind Sortierungen und die Multiplikation von großen Zahlen.
Sortieren über das Merge-Sort Verfahren
Der von John von Neumann vorgestellte Algorithmus basiert auf der Idee, die zu sortierende Liste ein zwei Teillisten zu zerlegen, diese dann wiederum in zwei Teile zu zerlegen, diese wiederum, usw., bis die Listen so klein sind, dass sie vielleicht nur noch aus zwei Zahlen bestehen, die trivial in eine Reihenfolge zu bringen sind. Ist eine Teilfolge dann sortiert, muss sie mit sortieren Nachbarfolge zusammenfügt (engl. merge) werden. Während also das Zerlegen und Sortieren von oben nach unten erfolgt, läuft das Zusammenlegen der sortierten Teillisten zur neuen größeren sortieren Teillisten von unten nach oben, bis schließlich die Gesamtliste sortierten ist. Der Algorithmus lässt sich sehr gut rekursiv implementieren. Auch das bekannte Quicksort arbeitet ähnlich. (Hier geht es allerdings darum, ein sogenanntes Pivot-Element zu wählen, dann die Liste in zwei Teillisten aufzuspalten, wobei in die erste Liste (erst einmal unsortiert) die Elemente kleiner dem Pivot-Element verschoben werden und in die andere Liste die Elemente größer dem Pivot-Element. Die Auswahl eines neuen Pivot-Elemens und das Kopieren in den richtigen Bereich wird rekursiv für die Unterbereiche wiederholt, was natürlich zu einer Sortierung führt. In der Regel kommt Quicksort mit weniger Speicher aus und ist in der Praxis schneller, da Merge-Sort in der einfachen Implementierung immer neue Teillisten aufbauen muss und Quicksort die Vertauschoperationen auf der originalen Datenstruktur (in-place genannt) ausführen kann.
Multiplikation von großen Ganzzahlen
In Java ist das Multiplizieren von Ganzahlen einfach. Sind die Zahlen klein genug, erledigt der *-Operator die Aufgabe, sind sie größer hilft die Klasse BigInteger und die Methode multiply(). Das sind natürlich hübsche Abstraktionen, aber im Java Bytecode gibt für die Multiplikation von int und long lediglich imul und lmul[2], und alles andere, etwa die Multiplikation von großen Zahlen für RSA-Schlüssel.
Das Produkt von großen Zahlen lässt sich einfach auf das Produkt von kleinern Zahlen mit ein paar Additionen abbilden. Statt Zahlen mit hunderten von Stellen zu nehmen, ein einfacheres Beispiel, was das Prinzip zeigt. Nehmen wir dazu die Zahl A = 1234, die mit B = 5678 multipliziert werden soll. Dann ist AB = (12 · 10^2 + 34) · (56 · 10^2 + 78) = 12 · 56 · 10^4 + (12 · 78 + 34 · 56) · 10^2 + 34 · 78. Waren bei 1234 und 5678 die Zahlen noch vierstellig, sind sie bei der Umschreibung nur noch zweistellig. Zählen wir die Anzahl Multiplikationen – und lassen wir die einfachen Multiplikation mit 10^4 bzw. 10^2 beiseite – so kommen wir auf vier, denn wir müssen 12 · 56, 12 · 78, 34 · 56 und 34 · 78 ausführen. Bei einem rekursiven D&C-Algorithmus ist also das Problem zur Multiplikation von 1234 · 5678 auf die vier Multiplikationen und Additionen abgeschwächt worden. Das können wir dann auch weiter aufspalten bis wir bei einstelligen Zahlen sind. Stehen wir also vor der Aufgabe beliebig große Zahlen mit n Stellen zur multiplizieren, können wir das Abbilden auf eine Multiplikation von Zahlen der Größe n/2 und ein paar Additionen. Kommen wir noch zu einer kleinen Optimierung. Wenn Zahlen sehr groß werden und dann multipliziert werden müssen (etwa zu Schlüsselgenerierung) ist es wichtig, jede überflüssige Operation wegzulassen, da arithmetische Operationen dann bei großen Zahlen und dem häufiger Durchführung doch ihre Zeit kosten. Interessanterweise kann durch geschickte Umstellung kann die Anzahl Multiplikationen von 4 auf 3 gesenkt werden. Zwei der Multiplikationen stammen aus 12 · 56 · 10^4 + (12 · 78 + 34 · 56) · 10^2 + 34 · 78 stammen aus dem Teil 12 · 78 + 34 · 56. Hier können wir etwas umschreiben, denn 12 · 78 + 34 · 56 = (12 + 34) · (56 + 78) – 12 · 56 – 34 · 78. Obwohl das auf den ersten Blick schlimmer aussieht (drei Multiplikationen statt zwei), fällt bei zweiten Blick auf, dass wie die beiden Produkte 12 · 56 und 34 · 78 schon im ersten Schritt berechnet haben. Also ergibt sich letztendlich 12 · 56 · 10^4 + ((12 + 34) · (56 + 78) – 12 · 56 – 34 · 78) · 10^2 + 34 · 78 und das macht insgesamt drei Multiplikationen für den Preis von ein paar zusätzlichen Subtraktionen, die im allgemeinen billiger ist als die Multiplikation, die bei dem D&C-Ansatz ja recht aufwändig ist.
Die Arbeitsweise von D&C-Algorithmen im Pseudocode sieht wie folgt aus:
löse Problem:
ist Problem klein:
löse Problem direkt
andernfalls:
zerlege das Problem in Teilprobleme
löse die Teilprobleme
setzte Problemlösung aus den Teillösungen zusammen
Attraktiv sind D&C-Algorithmen dann, wenn die Teilprobleme unabhängig voneinander und parallel gelöst werden können.
Bei unserem Eingangsbeispiel mit dem Aufstehen und Essen gibt es eine Abhängigkeit, so dass zwei beide Teilprozesse zwar eine Teilaufgabe des Gesamtproblems lösen, aber ohne Aufstehen man nicht zum Kühlschrank kommt. Das Sortieren über Merge-Sort ist erfüllt dabei das Kriterium, dass wenn die Liste in zwei Unterlisten zerlegt wird, die beiden Unterlisten problemlos parallel sortiert werden können.
[1] Nicht D&G, „ein anspruchsvolles und zeitgemäßes Markenzeichen und Ausdruck einer sich wandelnden Welt“ …
[2] http://java.sun.com/docs/books/jvms/second_edition/html/Mnemonics.doc.html
Labels: Insel
Merkwürdige Geschäftsbedingungen für Android Market
0 Kommentar(e). Veröffentlicht von Christian Ullenboom am Samstag, November 14, 2009.Darüber berichtet Heise:
Ein Entwickler, der sein Produkt aus dem Market aus unterschiedlichen Gründen (z.B. aufgrund von Urheberrechtsverletzungen) zurückzieht, muss alle Einkünfte, die er innerhalb eines Jahres, bevor die Software entfernt wurde, an die Endverbraucher, die für das Produkt gezahlt haben, zurückerstatten.
Vielleicht ist das aber gar nicht so falsch. Wenn ich mit Nacktbildern von Angela M. richtig viel Kohle mache, dann aber wegen unsittlichen urheberrechtlich geschützten Privatfotos meine App zurückziehen muss, habe ich dann schon auf dem Rücken von Angela M. (oh, ja, welch’ Bild) viel verdient. Bin gespannt, wie sich das entwickelt.
switch auf Strings seit Java 7
2 Kommentar(e). Veröffentlicht von Christian Ullenboom am Samstag, November 14, 2009.Seit Java 7 sind switch-Anweisungen auf String-Objekten möglich.
String input = javax.swing.JOptionPane.showInputDialog( "Eingabe" );
switch ( input.toLowerCase() )
{
case "kekse":
System.out.println( "Ich mag Keeeekse" );
break;
case "kuchen":
System.out.println( "Ich mag Kuchen" );
break;
case "scholokade":
case "lakritze":
System.out.println( "Hm. lecker" );
break;
default:
System.out.printf( "Kann man %s essen?", input );
}
Obwohl Zeichenkettenvergleiche nun möglich sind, fallen Überprüfungen auf reguläre Ausdrücke leider heraus, die insbesondere Skriptsprachen anbieten.
Java 7 Milestone 5: Build b76 vorgestellt
0 Kommentar(e). Veröffentlicht von Christian Ullenboom am Samstag, November 14, 2009.Download gibt es unter http://download.java.net/jdk7/m5/, die Neuerungen bei http://download.java.net/jdk7/changes/jdk7-b76.html. Am Interessantesten dürfen sein:
- bb3. 6865582. jsr166y - jsr166 maintenance update
- 6865571. Add a lightweight task framework known as ForkJoin
- 6445158. Phaser - an improved CyclicBarrier
- 6865579. Add TransferQueue/LinkedTransferQueue
und
- 8fb9b4be3cb1. 6827009. Project Coin: Strings in Switch
Labels: Java 7
Release von JProfiler 6.0
0 Kommentar(e). Veröffentlicht von Christian Ullenboom am Freitag, November 13, 2009.Während man die Profiler TPTP und den NetBeans Profiler als Standards im Open-Source Umfeld bezeichnen kann, so ist das auf der kommerziellen Seite JProfiler und YourKit Java Profiler 8.0. Die ej-technologies GmbH stellt mit dem JProfiler nun ein Tool vor, das interessante Neuigkeiten bietet. Ein Trend ist die Zuwendung zu einem Tool welches Möglichkeiten bietet Thread-Locks zu visualisieren, was es klarer Hinweis ist, dass Entwickler um die parallele Programmierung nicht mehr rumkommen und Hilfe bei der Optimierung der (gedachten) Optimierung benötigen.

Neu ist auch die Darstellung, welche Locks wie oft angefragt werden:

Auch folgende Darstellung ist neu und von einem Klassiker inspiriert, der Dateigrößen erstmalig so darstellte. Nun ist das auf die Ausführungszeiten und Speicherverbrauch angewendet. Eine wunderbare Idee:


PS: Die deutschsprachige Frage-/Antwort-Plattform http://stackunderflow.de/ freut sich über neue Fragen und Antworten aus dem IT-Bereich. Java, Datenbanken, .NET, … alles ist erlaubt.
Kommen jetzt die Androids?
0 Kommentar(e). Veröffentlicht von Christian Ullenboom am Freitag, November 13, 2009.Vor nicht all zu Langer Zeit kam Google mit Android 2.0 um die Ecke und nun kommt es mir vor, dass alle möglichen Hersteller Android-Geräte ankündigen. Heise gibt nun auch ein Handy von LG an. Damit wächst die Liste der Android-Handys auf 13. Einige sind jedoch nur Ankündigungen doch ich bin überzeugt, es werden mehr. Es wäre Zeit, nun ein Android-Buch zu schreiben …
Labels: Android
Thema der Woche: Ladebalken über dem Textfeld
0 Kommentar(e). Veröffentlicht von Christian Ullenboom am Mittwoch, November 11, 2009.Mit JXLayer (https://jxlayer.dev.java.net/) lassen sich beliebige Swing-Komponenten mit anderen Swing-Komponenten (oder Zeichnungen) auf eine Ebene legen und somit interessante Effekte und Lösungen entwerfen.

- Schreibe eine kleine Swing-Anwendung mit einem Textfeld und einer Schaltfläche. Wird die Schaltfläche gedrückt soll ein Web-Server kontaktiert und die Daten von dort geladen und in das Textfeld gesetzt werden.
- Das Laden soll künstlich verzögert werden. Schreibe einen eigenen ThrottleReader, der den FilterReader erweitert und deine künstliche Verzögerung einführt.
- Beim Laden soll nun ein (indefinite) Fortschrittsbalken mit JXLayer über dem Textfeld erscheinen, der dann ausgeblendet wird, wenn der Text geladen wurde.
- Überlege, wie sich der Fortschnitt des Fortschrittsbalken bestmöglich an der Anzahl geladenen Zeichen festmachen lässt.
Labels: Die wöchentliche Dosis Java
Ersetze in einem String die alle diakritischen Zeichen (ä->a, ...)
0 Kommentar(e). Veröffentlicht von Christian Ullenboom am Mittwoch, November 04, 2009.s = Normalizer.normalize( s, Normalizer.Form.NFD );
s = s.replaceAll( "[\\p{InCombiningDiacriticalMarks}\\p{IsLm}\\p{IsSk}]+", "" );
System.out.println( s ); // Muller
Die Lösung geht zweistufig vor. Der Normalisier zerlegt zunächst den String und macht die eigentliche Arbeit. replaceAll() entfernt dann übriggebliebene Punke, Striche, Kreise, Häkchen.
Labels: Insel
Swing-Komponenten neu erstellen oder verändern und JLayer
0 Kommentar(e). Veröffentlicht von Christian Ullenboom am Mittwoch, November 04, 2009.Unproblematisch ist auch, wenn sich neue Komponenten aus anderen Swing Teilkomponenten zusammenzusetzen lassen und. Dann erweitert die neue Swing-Klasse erweitert einen Container wie JPanel, der einfach die anderen Elemente wie gewünscht platziert. Möglich ist dies zum Beispiel bei einer Statuszeile, da diese nichts großartiges macht, als einfach horizontal andere Komponenten anzuordnen und einen besonderen Rahmen zu setzen. Einen Dialog zur Auswahl eines Zeichensatzes bietet Swing bisher auch nicht an, der lässt sich aber als JDialog mit passenden Swing-Komponenten leicht nachbauen.
Mehr Arbeit ist nötig, wenn sich auf keine allgemeinen Swing-Komponenten zurückgreifen lässt. Die Swing-Bibliothek bietet etwa keine Ribbon-Komponente, keinen wirklich guten HTML-Renderer, oder ein Docking-Framework. Bei Anforderungen dieser Art lässt sich nicht so einfach auf Standardkomponenten zurückgreifen, sondern spezieller Programmcode zum Zeichnen nötig. Der wesentliche Unterschied ist also der, dass sich die Darstellung nicht vollständig an Standardkomponenten delegieren lässt sondern immer etwas einer Java-Code zum Zeichnen nötig ist.
Um es richtig gut zu machen, sind für eine eigene Swing-Komponente drei Dinge nötig: Die Komponentenklasse, eine Modellklasse und ein UI-Delegate. Die Komponentenklasse ist die Hauptklasse und eine JComponent, die der Entwickler auf die Gui setzt. Sie bietet die API zum Setzten der Zustände. Die Modell-Daten werden nicht selbst in der Komponentenklasse gespeichert, sondern idealweise über eine eigene Klasse modelliert. Die Tabelle nimmt zum Beispiel die Zellen aus einem Tabellemodell, eine Textkomponenten den Text aus einem Dokumentenmodell. Als letztes bleibt der UI-Delegate, der das wirkliche Zeichen und die Ereignisbehandlung übernimmt. Es kann sehr anspruchvoll sein ein gutes Aussehen und effektive Navigation zu erreichen und insbesondere wenn die Komponente in verschiedenen Look-and-Feels arbeiten soll, eine Menge Arbeit werden. Und das die eigene Swing-Komponente die UI-Eigenschaften wie Farben, Abstände und Antialiasing-Modus toleriert ist selbstverständlich.
Überlagerungen mit dem Swing-Komponenten-Dekorator JLayer
Können Swing-Komponten überlagert werden, können dadurch interessante Effekte erzieht werden. Ein paar Beispiele:
· Während ein Text in die Textbox geladen wird, erscheint ein JProgressBar.
· Bei aufwändigen Operationen wird das Haupt-Panel gesperrt und eine drehende Sanduhr erscheint.
· Ist die Eingabe in einem Textfeld falsch, erscheint ein kleines Symbol, welches über die invalide Eingabe informiert.
· Über einer leeren Tabelle liegt eine Beschriftung, die erklärt, dass Doppelklick eine neue Zeile einfügt.
Alle die Darstellungen lassen sich mit Hilfe der in Java 7 eingefügten Klassen JLayer einfach lösen (Nutzer vor Java 7 greifen auf SwingX zurück, denn von dort kommt die Klasse auch; sie heißt nur dort JXLayer. Als Alternative haben Autoren auch oft auf Glass-Pane zurückgegriffen.)
Haupteigenschaft von JLayer ist, sich um existierende Swing-Komponenten zu legen. Soll ein JLayer um ein Textfeld gelegt werden, heißt es:
JLayer
Die zu ummantelnde Komponente wird über den Konstruktor angegeben und nicht über add(), da JLayer kein Container ist. Der nächste Schritt ist die Angabe eines Objekts, dass das Zeichnen übernimmt.
layer.setUI( layerUI );
Die Angabe erfordert ein LayerUI-Objekt, welches eine paint()-Methode realisiert. Die Implementierung kann super.paint() aufrufen, um die ummantelte Komponente zu zeichnen, und dann eigenen Programmcode hinzufügen, um etwa einen Sanduhr darzustellen.
Das folgende Beispiel fasst die Schritte zusammen und realisiert ein Programm, welches bei Eingabe von „pu“ einen kleinen roten Kreis anzeigt.
JFrame f = new JFrame();
f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
f.setLayout( new BorderLayout(2, 2) );
f.add( new JSeparator(), BorderLayout.PAGE_START );
f.add( new JLabel( "Name:" ), BorderLayout.LINE_START );
final JTextField textField = new JTextField();
LayerUI
{
@Override
public void paint( Graphics g, JComponent component )
{
super.paint( g, component );
if ( textField.getText().equalsIgnoreCase( "pu" ) )
{
g.setColor( new Color( 255, 0, 0, 100 ) );
g.fillOval( 0, component.getHeight() - 10, 10, 10 );
}
}
};
JLayer
layer.setUI( layerUI );
f.add( layer );
f.add( new JSeparator(), BorderLayout.PAGE_END );
f.pack();
f.setVisible( true );
Die JLayer kann auch das Hauptpanel dekorieren und die Events auffangen. Das ist eine zweites Anwendungsfeld neben dem Änderung der Darstellung. Die JLayer-Komponente kann einfach Events auffangen und verarbeiten und so zum Beispiel global F1 für die Hilfe abfangen.
JSON-Serialisierung mit Jackson
0 Kommentar(e). Veröffentlicht von Christian Ullenboom am Mittwoch, November 04, 2009.var person = { "name" : "Michael Jackson", "age" : 50 };
Die Definition eines Objekts geschieht in der JSON (JavaScript Object Notation). Als Datentypen unterstützt JSON Zahlen, Wahreiswerte, Strings, Arrays, null und Objekte – wie unser Beispiel zeigt. Die Deklarationen können geschachtelt sein, um Unterobjekte aufzubauen.
Zum Zugriff auf die JSON-Daten kommt der Punkt zum Einsatz, sodass der Name nach der Auswertung durch person.name zugänglich ist.
Eine Personenbeschreibung wie diese kann auch in einem String stehen, die von JavaScript zur Laufzeit ausgewertet wird.
var json = 'person = { "name" : "Michael Jackson", "age" : 50 };';
eval( json );
Der Zugriff auf person.name liefert wie vorher den Namen, denn nach der Auswertung mit eval() wird JavaScript ein neues Objekt mit person im Kontext anlegen.
JSON ist besonders praktisch, wenn es darum geht, Daten zwischen einem Server und Browser mit JavaScript-Interpreter auszutauschen. Denn wenn der String json nicht von Hand mit einem String initialisiert wurde, sondern ein Server die Zeichenkette person = { … }; liefert, haben wir das, was heutzutage in modernen Ajax-Webanwendungen passiert. Die letzte Frage ist nun, wie elegant der Server Zeichenketten im Datenaustauschformat JSON erzeugt und so Objekte überträgt. Den String per Hand aufzubauen ist eine Lösung, aber es geht besser.
Die Open-Source Bibliothek Jackson (http://jackson.codehaus.org/) gehört zu den populärsten Lösungen, die JSON-Daten einliest und ausgibt und auf JavaBeans überträgt, sodass eine unkomplizierte Serialisierung in JSON möglich wird.
ObjectMapper mapper = new ObjectMapper();
MyClass myObject = mapper.readValue( input, MyClass.class );
mapper.writeValue( output, myObject );
Der ObjectMapper übernimmt das Lesen/Schreiben. In der zweiten Zeile wird aus der Eingabequelle input gelesen und ein Objekt vom Typ MyClass rekonstruiert. In der dritten Zeile wird es in die Ausgabe output geschrieben.
JSON ist nicht nur für die Objektübertragung zwischen Server und Browser gut, sondern ist eine elegante Alternative zu XML, wenn es etwa um lokale Konfigurationsdateien geht. JSON ist viel kürzer als XML und kann somit zum Beispiel für Konfigurationsdateien übersichtlicher sein.
Labels: Insel
Bean-Zustände kopieren
1 Kommentar(e). Veröffentlicht von Christian Ullenboom am Dienstag, November 03, 2009.Der Aufwand mit einer eigenen Implementierung ist allerdings nicht nötig, denn zwei populäre Implementierungen können helfen:
• Apache Commons BeanUtils (http://commons.apache.org/beanutils/). Die Klasse org.apache.commons.beanutils.BeanUtils bietet praktische statische Methoden wie copyProperty(Object bean, String name, Object value), copyProperties(Object dest, Object orig), Object cloneBean(Object bean) oder populate(Object bean, Map properties).
• Dozer (http://dozer.sourceforge.net/). Dozer bringt ausgefeilte Mapping-Möglichkeiten mit, die weit über BeansUtils hinausgehen. Das geht soweit, dass es ein Eclipse-Plugin zur Konfiguration der Abbildungen gibt.
Labels: Insel
Java-Ribbon Komponente Flamingo 4.2 ist raus
0 Kommentar(e). Veröffentlicht von Christian Ullenboom am Dienstag, November 03, 2009.- Support for placing small command buttons in ribbon galleries
- Option to specify the callback for populating the default content of ribbon application menu
- Command buttons support no icon / no text mode
- Emitting full bounding box coordinates in SVG transcoder
- Support for changing the expand listener of ribbon bands
- Better tracing of inconsistent ribbon resize policies
Mehr Infos gibt es unter https://flamingo.dev.java.net/.
Mit dem Substance LaF sieht das hervorragend aus.
Labels: Open Source, Swing
Process-Ströme in Dateien umlenken
0 Kommentar(e). Veröffentlicht von Christian Ullenboom am Dienstag, November 03, 2009.Neben diesem Pipe-Modus gibt es seit Java 7 eine Alternative, die Ströme direkt auf Dateien umzulenken. Dazu definiert die ProcessBuilder-Klasse diverse redirectXXX()-Methoden. (Sollte dann ein getXXXStream()-Aufruf gemacht werden, so kommen nicht-aktive Ströme zurück, denn das externe Programm kommuniziert ja dann direkt mit einer Datei und die Java-Pipe hängt nicht dazwischen.)
class java.lang.ProcessBuilder
§ ProcessBuilder redirectInput( File file )
ProcessBuilder redirectInput( ProcessBuilder.Redirect source )
Der Unterprozess wird die Eingaben aus der angegeben Quelle beziehen.
§ ProcessBuilder redirectOutput( File file )
§ ProcessBuilder redirectOutput( ProcessBuilder.Redirect destination )
Der Unterprozess wird Standardausgaben an das angegebene Ziel senden.
§ ProcessBuilder redirectError( File file )
§ ProcessBuilder redirectError( ProcessBuilder.Redirect destination )
Der Unterprozess wird Fehlerausgaben an das angegebene Ziel senden.
Die redirectXXX(File file)-Methoden bekommen als Ziel ein einfaches File-Objekt. Die redirectXXX()-Methoden sind aber überladen mit einem anderen Typ Redirect, der als innere statische Klasse in ProcessBuilder angelegt ist. Mit Redirect.PIPE und Redirect.INHERIT gibt es zwei Konstanten, und drei statischen Methoden Redirect.from(File), Redirect.to(File), Redirect.appendTo(File) die Redirect-Objekte für die Umleitung zur Datei liefern. Die mit File parametrisierten Methoden greifen auf die Redirect-Klasse zurück, so dass es bei redirectOutput(File file) intern auf ein redirectOutput(Redirect.to(file)) herausläuft.
NumberFormat, Währungen angeben und die Klasse Currency
0 Kommentar(e). Veröffentlicht von Christian Ullenboom am Dienstag, November 03, 2009.NumberFormat frmt1 = DecimalFormat.getCurrencyInstance( Locale.FRANCE );
System.out.println( frmt1.format( 12345.6789 ) ); // 12 345,68 €
so ist die Währung automatisch Euro (denn Frankreich nutzt den Euro); schreiben wir DecimalFormat.getCurrencyInstance(Locale.JAPAN) ist sie Yen und wir bekommen ¥12,346. (Es gibt standardmäßig keine Nachkommastellen beim Yen.) Locale-Objekten repräsentieren immer eine sprachliche Region.
DecimalFormat bzw. schon die Oberklasse NumberFormat ermöglicht die explizite Angabe der Währung. In der Java-Bibliothek wird sich durch die Klasse java.util.Currency repräsentiert. NumberFormat liefert mit getCurrency() die eingestellte Currency, die zur Formatierung verwendet wird und setCurrency() setzt sie neu. Das löst Szenarios, in denen etwa ein Euro-Zeichen die Währung darstellt, aber die Zahlenformatierung englisch ist, wie die folgenden Zeilen zeigen:
NumberFormat frmt = DecimalFormat.getCurrencyInstance( Locale.ENGLISH );
frmt.setCurrency( Currency.getInstance( "EUR" ) );
System.out.println( frmt.format( 12345.6789 ) ); // EUR12,345.68
Die Currency-Klasse bietet drei statische Methoden, die Currency-Objekte liefern. Da ist einmal getAvailableCurrencies(), was ein Set
Folgendes Programm geht über alle Währungen und gibt die zentralen Informationen aus:
for ( Currency currency : Currency.getAvailableCurrencies() )
{
System.out.printf( "%s, %s, %s (%s)%n",
currency.getCurrencyCode(),
currency.getSymbol(),
currency.getDisplayName(),
currency.getDisplayName(Locale.ENGLISH) );
}
Wir bekommen dann mehr als 200 Ausgaben, und die Ausgabe beginnt mit:
EGP, EGP, Ägyptisches Pfund (Egyptian Pound)
IQD, IQD, Irak Dinar (Iraqi Dinar)
GHS, GHS, Ghana Cedi (Ghana Cedi)
AFN, AFN, Afghani (Afghani)
MUR, MUR, Mauritius Rupie (Mauritius Rupee)
SGD, SGD, Singapur Dollar (Singapore Dollar)
…
Eclipse 3.6 M3 ist verfügbar
0 Kommentar(e). Veröffentlicht von Christian Ullenboom am Montag, November 02, 2009.Labels: Eclipse, Entwicklungsumgebung
Wrapperklassen-Vergleiche durchführen mit compare() und compareTo()
1 Kommentar(e). Veröffentlicht von Christian Ullenboom am Montag, November 02, 2009.· Sie implementieren eine Objektmethode compareTo(). Die Methode ist nicht zufällig da, denn Wrapper-Klassen implementieren die Schnittstelle Comparable. (Wir haben die Schnittstelle schon im Kapitel 6 kurz vorgestellt.)
· Wrapper-Klassen besitzen statische compare()-Methoden.
Die Rückgabe der Methoden ist ein int und es kodiert, ob ein Wert größer, kleiner oder gleich ist.
Beispiel Teste verschiedene Werte.
System.out.println( Integer.compare(1, 2) ); // -1
System.out.println( Integer.compare(1, 1) ); // 0
System.out.println( Integer.compare(2, 1) ); // 1
System.out.println( Double.compare(2.0, 2.1) ); // -1
System.out.println( Double.compare(Double.NaN, 0) );// 1
System.out.println( Boolean.compare(true, false) ); // 1
System.out.println( Boolean.compare(false, true) ); // -1
Ein true ist „größer“ als als false.
Die Tabelle fasst von den Wrapper-Klassen die Methoden zusammen.
Klasse Methode aus Comparable Statische Methode compare()
Byte int compareTo(Byte anotherByte) int compare(int x, int y)
Short int compareTo(Short anotherShort) int compare(short x, short y)
Float int compareTo(Float anotherFloat) int compare(float f1, float f2)
Double int compareTo(Double anotherDouble) int compare(double d1, double d2)
Integer int compareTo(Integer anotherInteger) int compare(int x, int y)
Long int compareTo(Long anotherLong) int compare(long x, long y)
Character int compareTo(Character anotherCharacter) int compare(char x, char y)
Boolean int compareTo(Boolean b) int compare(boolean x, boolean y)
Die Implementierung einer statischen Methode WrapperKlasse.compare() ist äquivalent zu WrapperKlasse.valueOf(x).compareTo(WrapperKlasse.valueOf(y)).
Die Klassen BigInteger, BigDecimal implementieren zwar Number und somit Comparable, aber eine statische compare()-Methode bieten sie nicht. Auch String implementiert Comparable, aber eine statische Methode fehlt. Der Grund ist, dass es eine statische Methode Objects.compare() gibt, zwei Objekte mit einem Comperator vergleicht.
Die Utility-Klasse java.lang.Objects
0 Kommentar(e). Veröffentlicht von Christian Ullenboom am Montag, November 02, 2009.null-Tests um equals()/hashCode()/toString()
class java.lang.Objects |
Liefert true wenn beide Argument entweder null sind, oder a.equls(b) ebenfalls true ergibt. Sonst false. Das Objects.equals(null, null) die Rückgabe true ergibt ist sinnvoll und so erspart die Methode einige händische Tests.
Liefert 0 wenn o gleich null ist, sonst o.hashCode().
Liefert den String "null" wen das Argument null ist sonst o.toString().
Null-Prüfungen mit eingebauter Ausnahmebehandlung
Beispiel Die Methde setName() soll keine name-Argument gleich null erlauben. public void setName( String name ) { this.name = Objects.nonNull( name ); } Alternativ ist eine Fehlermeldung möglich: public void setName( String name ) { this.name = Objects.nonNull( name, "name is not supposed to be null" ); } |
class java.lang.Objects |
equals()/hashCode() tief oder flach und mehrdimensionale Arrays
0 Kommentar(e). Veröffentlicht von Christian Ullenboom am Montag, November 02, 2009.Tiefe oder flache Vergleiche/Hash-Werte
if ( ((Player)that).name != null )
return false;
else if ( !name.equals( ((Player)that).name ) )
return false;
equals()/hashCode()-Berechnung bei (mehrdimensionalen) Arrays
Labels: Insel
