This page (revision-22) was last changed on 03-Jan-2011 16:54 by ThomasBayen 

This page was created on 01-Sep-2008 13:19 by ThomasBayen

Only authorized users are allowed to rename pages.

Only authorized users are allowed to delete pages.

Page revision history

Version Date Modified Size Author Changes ... Change note
22 03-Jan-2011 16:54 14 KB ThomasBayen to previous Linkliste zu Wizards in Swing
21 03-Jan-2011 15:26 14 KB ThomasBayen to previous | to last Linkliste zu Wizards in Swing

Page References

Incoming links Outgoing links

Version management

Difference between version and

= Swing-Tips =

Bei der Arbeit mit Swing stößt man fast ständig an Besonderheiten und Eingenschaften, deren genaue Funktion man sich erst erarbeiten muss. Um solche Dinge für die Nachwelt und für mich zu erhalten, habe ich diese Seite begonnen, um sie hier zu erklären.

== JTable wie ein Spreadsheet benutzen ==

Der eigentliche Sinn einer editierbaren JTable ist meiner Meinung nach, dem Benutzer halbwegs das Gefühl zu geben, das er beim editieren eines Spreadsheets (also in MS Excel oder ~OpenOffice.org Calc) hat. Leider ist das "Feeling" etwas anders, was meiner Meinung nach unnötig die Benutzer verstört. Ich möchte jeden Unterschied, der mich stört, hierbei einzeln behandeln.

=== sofortiges löschen beim editieren ===

Wenn man eine Textzelle (z.B. mit der Maus) aktiviert hat und dann eine alphanumerische Taste drückt, wird diese Taste an das Ende des bestehenden Textes angefügt. Das gleiche passiert beim Drücken von F2. In OOo Calc ist es so, daß beim einfachen Drücken der bestehende Wert immer überschrieben wird und man F2 drücken muss, um den Wert editieren zu können.

Dieses Problem ist aufgrund der Struktur der JTable-Klasse gar nicht so trivial, wie ich dachte. Deshalb dokumentiere ich hier einen Teil des Weges, den ich zu meiner Lösung genommen habe, um ggf. später beim nachbessern nicht alles neu suchen zu müssen:

Zuerstmal steht im [Swingwiki|http://www.swingwiki.org/best:edit_cells_like_excel], daß die eine Lösung hätten. Diese Lösung basiert darauf, daß ein ~DefaultCellEditor gesetzt wird, der sich beim Aufruf automatisch komplett selektiert. Das hilft zwar, wenn ich eine alphanumerische Taste drücke, selektiert aber bei F2 ebenfalls den gesamten Text und verhindert somit, das man einen vorhandenen Zelleninhalt editieren kann.

In einem [Sun-Forum|http://forums.sun.com/thread.jspa?forumID=57&threadID=752727] steht ein Quelltext, von dem ich überhaupt nicht verstehe, was der soll. Ich habe ihn nicht ausprobiert, nach der Beschreibung sollte er aber mit meinem Problem zu tun haben.

In einem [Artikel|http://www.informit.com/articles/article.aspx?p=24130&seqNum=11] mit einem relativ einfachen Niveau fand ich den Hinweis, wie Funktionstasten und alphanumerische Tasten überhaupt behandelt werden und wo der Unterschied liegt: Scheinbar wird in ~BasicTableUI entschieden, ob es sich um eine einzufügende Taste oder eine Sondertaste (z.B. Pfeiltaste oder F2) handelt. F2 wird dann in ~BasicTableUI.actionPerformed als Action START_EDITING behandelt, normale Tasten in ~JTable.processKeyBinding().

Parallel fand ich in einem [Forumsthread zum Thema|http://forums.java.net/jive/thread.jspa?threadID=42682&tstart=0] einen Beitrag von "oswald", der versucht hatte, ~processKeyBinding() zu überladen, aber mit dieser Idee nicht vorwärtsgekommen war. Nachdem ich das durchdacht hatte, merkte ich, daß dieser Gedanke der beste war, den ich gesehen hatte. Ich beschäftigte mit intensiver mit dieser Methode, fand das Problem, das oswald hatte, einen Workaround hierfür und habe folgende Lösung implementiert:
{{{
public class SpreadsheetJTable extends JTable {

protected boolean processKeyBinding(KeyStroke ks, KeyEvent e,
int condition, boolean pressed) {
/*
* Der Inhalt dieses if-Blocks ist aus der super-Methode entnommen. Ich
* erzeuge hier die Editor-Komponente genauso wie im Original. Dann
* selektiere ich allerdings den ganzen Text wie in
* Spreadsheet-Applikationen üblich.
*/
if (condition == WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
&& isFocusOwner()
&& !Boolean.FALSE
.equals((Boolean) getClientProperty("JTable.autoStartsEdit"))) {
// We do not have a binding for the event.
Component editorComponent = getEditorComponent();
if (editorComponent == null) {
// Only attempt to install the editor on a KEY_PRESSED,
if (e == null || e.getID() != KeyEvent.KEY_PRESSED) {
return false;
}
// Don't start when just a modifier is pressed
int code = e.getKeyCode();
if (code == KeyEvent.VK_SHIFT || code == KeyEvent.VK_CONTROL
|| code == KeyEvent.VK_ALT) {
return false;

}
// Try to install the editor
int leadRow = getSelectionModel().getLeadSelectionIndex();
int leadColumn = getColumnModel().getSelectionModel()
.getLeadSelectionIndex();
if (leadRow != -1 && leadColumn != -1 && !isEditing()) {
if (!editCellAt(leadRow, leadColumn, e)) {
return false;
}
}
editorComponent = getEditorComponent();
if (editorComponent == null) {
return false;
}
// -TB-
// select everything (like Spreadsheet Apps do)
if (editorComponent instanceof JTextField) {
((JTextField) editorComponent).selectAll();
}
}
}
boolean retValue = super.processKeyBinding(ks, e, condition, pressed);
return retValue;
}

}

}}}

Das Ergebnis ist jetzt, das man einerseits mit einer normalen Taste den Zellinhalt überschreibt, aber andererseits mit F2 auch den vorhandenen Inhalt editieren kann! -- ThomasBayen


=== Navigation durch TAB-Taste ===

Beim Drücken von TAB sollte in die jeweils nächste Zelle gewechselt werden. Nachdem ich eine Weile durch den Sourcecode von ~BasicTableUI gestreift bin und gemerkt habe, daß es nicht so viel bringt, in den dortigen Actions herumzuhacken, habe ich mich zurückgelehnt, etwas gegoogelt und bin dann im ganz normalen [Java-Tutorial|file:///home/tbayen/Daten/Dokumentationen_dontbackup/JavaTutorial-Nov06/uiswing/misc/keybinding.html]
<< (Im Web: [JavaTutorial|http://java.sun.com/docs/books/tutorial/uiswing/misc/keybinding.html]) fündig geworden. Dort ist sehr gut erklärt, was es mit ~InputMap und ~ActionMap auf sich hat.