Meine JTable wird mit 0 Spalten/Zeilen initialisiert. Bei Knopfdruck werden dann sowohl neue Spalte als auch Zeile zugefügt oder wieder entfernt. Nun möchte ich aber (weil ich das alles im TableModel mache) nicht dabei noch dauernd meiner JTable sagen dass die neu erstellte Spalte eine bestimmte Breite haben soll. Gibt es eine Möglichkeit einzustellen, dass jede neu erzeugte Spalte eine gewisse Breite hat?
Leider finde ich nur tausende Threads wie ich die Spaltenbreite nachträglich ändere, aber genau das will ich ja nicht.
Grüße, TheAceOfSpades
Das sollte eigentlich nur eine/zwei zusätzliche Zeile/n Code bedeuten. Wie fügst Du eine neue Spalte hinzu? Nutzt Du ein DefaultTableModel und dessen Methoden oder ein eigenes?
/**
* Cover method, using a default width of 75, a <code>null</code>
* renderer and a <code>null</code> editor.
* @see #TableColumn(int, int, TableCellRenderer, TableCellEditor)
*/
public TableColumn(int modelIndex) {
this(modelIndex, 75, null, null);
}
ist wohl kein Kraut gewachsen,
da helfen nur diverse Eigenimplementationen
z.B. unschönerweise im Model die JTable ergänzen und doch noch selber nachträglich JTable ändern,
immerhin auf möglichst allgemeine Weise, nicht für einzelne Tabellen immer Code nötig,
maximal darauf zu achen ‘TableModelWithSpecialDefaultColumnWidth’ zu verwenden und da natürlich auch die DefaultWidth anzugeben
oder an anderen Stellen im Prozess, JTable überschreiben, einen Listener adden,
ich gehe davon aus dass du selber schon Ideen hast, bleibe zunächst bei nüchterner Absage (meiner Vermutung nach)
public class RatingTableModel extends DefaultTableModel{
...
public void addCrit(String crit){
crits.add(crit);
setColumnIdentifiers(crits);
addRow(new Vector());
int cols = getColumnCount() - 1;
super.setValueAt(1, cols, cols);
}
...
}
Im TableModel kann ich da ja aber recht wenig machen, das beinhaltet doch nur die Daten oder? Wenn, dann müsste ich doch dann das ColumnModel meiner JTable erweitern, oder?
der gepostete Code sorgt für sich doch kaum für eine neue Column, oder?
falls die JTable als Attribut vorhanden ist (was freilich ‘1-2 Codezeilen’ für sich schon strapazieren würde)
kann an fraglicher Stelle nach dem Event evtl. auf die JTable und anderes zugegriffen werden
ColumnModel ist ein anderer Angriffspunkt, richtig
Das ist richtig. Aber das DefaultTableModel bietet die Methode addColumn mit der man bequem neue Spalten ergänzen kann. Würdest Du ein eigenes TableModel verwenden müsstest Du Dich selbst um diese Erweiterung kümmern und würdest ggf. explizit eine neue TableColumn erzeugen, der man dann auch eine feste Breite zuweisen könnte. Daher die Frage.
Verwendest Du da absichtlich addRow, dachte es geht darum neue Spalten einzufügen?
Was spricht dagegen sich im Worst Case die TableColumn über das ColumnModel zu holen und daran z.B. Min und MaxWidth zu setzen?
Dann hat aber immer nur die letzte Spalte die PreferredWidth, der Rest wird bei zufügen wieder „zurückskaliert“. Nun könnte ich das natürlich mit einer Schleife lösen, aber das empfinde ich jetzt erstmal als unsauber, vor allem weil in der Tabelle später mehrere 100 Spalten drinstehen können und ich es als unnötig sehe jedes Mal wenn er eine Spalte hinzufügt alle mit neuer Breite versehen zu müssen. Gehen würde es ja schon, von Performance muss man an der Stelle glaube ich nicht anfangen. Aber ich frage hier ja nach weil ich das ja so eigentlich nicht haben will
bei den 100 Colums wirst du aber wohl nicht direkt die Wahl haben,
das setColumnIdentifiers() führt letztlich zu fireTableStructureChanged();
deswegen wird die neue Column erkannt, dabei aber kompletter Neuaufbau,
100x Size-Setzen ist das hinsichtlich Performance noch das geringste Problem:
egal ob du die Default-Size magst oder nicht werden alle Columns neu erzeugt
daran reparieren kannst du genauso, bietet sich im Verbund mit dem anderen Problem umso mehr an,
wieviele andere Wege, ergo Events, es im DefaultTableModel bzw. AbstractTableModel gibt, weiß ich nicht genau,
vielleicht auf dessen Unterstützung verzichten,
selber Daten und Columns verwalten, dann auch von Array oder Vector befreit,
beim Hinzufügen einer Spalte auf humanere Weise das ColumnModel der JTable erreichen (welches vielleicht deine Klasse ist)
dort nur eine Column hinzufügen und dann auch die richtige Size setzen
Column-Änderungen also selber managen, für neue Zeilen/ Datenänderungen durchaus fireTableDataChanged() von AbstractTableModel oder genaueres,
evtl. auch von DefaultTableModel erben oder kopieren:
public void setValueAt(Object aValue, int row, int column) {
Vector rowVector = (Vector)dataVector.elementAt(row);
rowVector.setElementAt(aValue, column);
fireTableCellUpdated(row, column);
}
oder wenn das alles zuviel ist, da kann man auch manches falsch machen und dann selber Performance kaputtoptimieren statt zu verbessern,
dann mit den 100 neuen Columns leben
Also von dem Buchstabenwald in der Mitte habe ich vielleicht die Hälfte verstanden, aber ich versuch mal drauf zu antworten in der Hoffnung dass ich es richtig interpretiere:
Das mit der Performance lasse ich einfach mal so stehen, darum geht es erstmal nicht.
Zuerst hatte in der addCrit() Methode ein einfaches addColumn(crit) stehen. Aber genauso wie ich addCrit() habe, habe ich auch removeCrit():
public void removeCrit(String crit){
Vector dataVec = getDataVector();
for(int c=0; c<crits.size(); c++){
if(crits.get(c).equals(crit)){
//Kriterium aus Überschriften entfernen
crits.remove(c);
//Tabelleninhalt aktualisieren
for(int v = 0; v < dataVec.size(); v++)
((Vector) dataVec.get(v)).remove(c);
dataVec.remove(c);
//removeRow(c);
break;
}
}
setDataVector(dataVec, crits);
setColumnIdentifiers(crits);
}
Hierbei muss ich eine Spalte sowie eine Zeile löschen. Leider habe ich keine andere Möglichkeit gefunden, aus dem Model einfach eine Spalte zu entfernen. Wenn ich sie aber so entferne, dann muss ich sie mit setColumnIdentifierts(crits) wieder hinzufügen, mit addColumn(crit) habe ich die Spalte dann zweimal.
Aber mir leuchtet ein dass auf dem aktuellen Weg sowieso alle Spalten neu eingesetzt werden…
Wie SlaterB schon erwähnt hat haben solchen Aktionen beim DefaultTableModel eine sehr tiefgreifende Wirkung. Aus eigener Erfahrung ist es empfehlens Wert sein eigenes TableModel abgeleitet vom Interface oder AbstractTableModel zu definieren.
Alternativ könnte man versuchen über das ColumnModel per addColumn(TableColumn) die neue Spalte hinzuzufügen, das wirkt nicht so extrem. Es kann aber durchaus berechtigt sein, dass das DefaultTableModel einen kompletten Neuaufbau auslöst.
Wenn man kein eigenes TableModel implementieren will, ist es denke ich das einfachste bei jedem Hinzufügen/Entfernen per Schleife die Spaltenbreiten zu setzen.
@TheAceOfSpades
addColumn() (edit: im DefaultTableModel) führt auch zu fireTableStructureChanged(), in der Hinsicht nichts zu gewinnen,
addColumn() fügt nebenbei auch im Datenvector für alle Zeilen einen Eintrag ein,
das muss man bedenken, bei dir aber wohl kein angesprochenes Problem
zum angegebenen Code ist noch zu sagen dass zwei gleiche Spalten hintereinander nicht gefunden werden würden,
steht c etwa bei 3, wird die Spalte in Index 3 entfernt, rückt die nächste Spalte auf Position 3 auf,
in der nächsten Runde wäre eigentlich wieder Index 3 zu prüfen, c wird aber auf 4 erhöht,
allgemein gefährliches Schleifenkonstrukt,
falls hier aber jede Spalte eh nur einmal vorhanden sein, dann kein akutes Problem,
edit: ach ja, ein break auch dabei, macht es klar
eine Frage ist aktuell nicht offen, oder?
abschweifen (auch wenn von anderen verursacht ) immer gefährlich,
ruhig zum Thema erinnern, unschön über viele Postings zurückschauen zu müssen ob noch irgendwas offen ist
Also generell würde ich gerne bei DefaultTableModel bleiben. Nicht zuletzt deshalb, weil ich ja andernfalls die eingegeben Daten manuell verwalten müsste (Wie SlaterB ja glaube ich schon gesagt hat), und das ganze würde mir dann wahrscheinlich zu unübersichtlich.
Das Schleifenkonstrukt funktioniert so, die Liste mit möglichen Spaltennamen gebe ich vor ;).
Die Frage an sich war eigentlich, ob es eine Möglichkeit gibt, dass jede neu erzeugte Spalte eine vorher festgelegte Breite hat. Also quasi so etwas wie setRowHeight(), nur eben für Spalten. Die Hoffnung verliere ich aber so langsam