Zuerst möchte ich folgendes sagen, das Benis Tutorials wahrscheinleich leichter zu handhaben und zu verstehen sind!
Außerdem haben seine Tutorials eine schöne "Hilfe" dabei, was meines nicht hat, aber trotzdem will ich mein JTable der Welt nicht vorenthalten!
Es wird mitHilfe einer inneren Klasse (Struktur) die Daten abgespeichert und in eine ArrayList geschrieben (nachher ein Objekt)! Diese wird dann sequentiell ausgelesen und mit getValueAt hineingeschrieben!
Als erstes ist der Aufruf (die imports habe ich dort weggelassen!)
Wie man das Table dann anzeigen lässt (ScrollPane, oder direkt auf ein Panel ist euch überlassen!!!)
Nun kommt die TabModel Klasse, die für euch die Daten in ein JTable schreibt!
Es sind 2 Funktionen zum Laden drinnen! Einmal von einer Datenbank und einmal aus einer Datei, falls ihr die Daten per Hand in die Struktur schreiben wollt, könnt ihr das auch tun, aber für das brauch ich woll kein Beispiel geben!
Nun der SortDecorator der euch die Tabelle auch schön brav nach ABC sortiert und die Pfeile reinmacht (die Pfeile wurden von Benis Beispiel genommen - Danke!)
Hatte früher hier den BubbleSort welcher bei ca. 100000 Zeilen sehr sehr lange gebraucht hat, aber der QuickSort ist huiiii
Also, hoffe es klappt (habs net ausprobiert, da ich viele Funktionen rausgenommen habe, die nur ich brauche)!
Außerdem haben seine Tutorials eine schöne "Hilfe" dabei, was meines nicht hat, aber trotzdem will ich mein JTable der Welt nicht vorenthalten!
Es wird mitHilfe einer inneren Klasse (Struktur) die Daten abgespeichert und in eine ArrayList geschrieben (nachher ein Objekt)! Diese wird dann sequentiell ausgelesen und mit getValueAt hineingeschrieben!
Als erstes ist der Aufruf (die imports habe ich dort weggelassen!)
Code:
//Aufruf in der anderen Klasse
public void showTable()
{
TabModel m_tabmod = new TabModel();
//hier dann Laden, oder sonst wo laden
m_tabmod.loadFromAFile(new File("/home/test");
//oder Datenbank
m_tabmod.loadFromADataBase();
JTable m_tab = new JTable(m_tabmod);
JTableHeader hdr = (JTableHeader) m_tab.getTableHeader();
hdr.addMouseListener(new MouseAdapter()
{
public void mousePressed(MouseEvent e)
{
if (e.getButton() == MouseEvent.BUTTON1)
{
final SortDecorator decorator = new SortDecorator(m_tabmod.getModel().
getModel());
TableColumnModel tcm = m_tab.getColumnModel();
int vc = tcm.getColumnIndexAtX(column.getX());
int mc = m_tab.convertColumnIndexToModel(vc);
//sortiert nach angeklickter Spalte
if(e.getModifiers() == 18) //strg + mausklick!
decorator.sort(mc,true);
else
decorator.sort(mc,false);// mausklick + irgendwas (oder nur mausklick)
//setzt das neue Model
m_tabmod.setModel(decorator);
m_tab.getTableHeader().setDefaultRenderer(decorator); //setzt die Pfeile
}
}
}
}
Wie man das Table dann anzeigen lässt (ScrollPane, oder direkt auf ein Panel ist euch überlassen!!!)
Nun kommt die TabModel Klasse, die für euch die Daten in ein JTable schreibt!
Code:
import java.io.*;
import java.util.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
/*
Es sind nicht alle Funktionen ausprogrammiert (so wie setValueAt(..) usw!
Es sind nur diese Funktionen ausprogrammiert, die man auch braucht fürs auslesen/anzeigen
und für das sortieren!
(das Statement braucht außerdem noch eine Verbindung! - man könntes mitübergeben bei der loadfunktion!)
*/
public class TabModel
extends AbstractTableModel
{
String[] columnNames =
{
"", "", "", "", "", "", ""}; //ßberschriften der Tabelle
private Object data[];
private Statement stm = null;
private ResultSet rs = null;
private ArrayList ar = null;
private boolean bErg = true;
/**************************************************************************
* Konstruktor für TabModel, indem die Spaltenbezeichnungen definiert werden
* und initDateTable wird aufgerufen
*************************************************************************/
public TabModel()
{
try
{
columnNames[0] = "1";
columnNames[1] = "2";
columnNames[2] = "3";
columnNames[3] = "4";
columnNames[4] = "5";
columnNames[5] = "6";
columnNames[6] = "7";
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
/***************************************************************************
* Spaltenanzahl
* @return Anzahl der Spalten
*************************************************************************/
public int getColumnCount()
{ //Anzahl der Spalten
return columnNames.length;
}
/***************************************************************************
* Zeilenanzahl
* @return Anzahl der Zeilen
*************************************************************************/
public int getRowCount()
{ //Anzahl der Zeilen
if (data == null)
return 0;
return (data.length);
}
/**************************************************************************
* Name einer Spalte
* @param iCol Position der Spalte
* @return Name der übergebenen Spalte
*************************************************************************/
public String getColumnName(int iCol)
{ //Name der Spalten
return columnNames[iCol];
}
/**************************************************************************
* Wert einer Spalte in einer bestimmten Zeile
* @param iRow Index der Zeile
* @param iCol Position der Spalte
* @return Wert an der Stelle row / col
*************************************************************************/
public Object getValueAt(int iRow, int iCol)
{ //Retouniert Wert an bestimmter Stelle
Object objRet = null;
if (iRow < data.length && data[iRow] != null) // gibt die Objekte zurück
{
Pay_d pl = (Pay_d) data[iRow];
switch (iCol)
{
case 0:
objRet = Short.toString(pl.Pay_id);
break;
case 1:
objRet = Short.toString(pl.Pay_sub);
break;
case 2:
objRet = pl.txt;
break;
case 3:
objRet = Short.toString(pl.for_currid);
break;
case 4:
objRet = Short.toString(pl.for_fakt);
break;
case 5:
objRet = Integer.toString(pl.bonuspnkt);
break;
case 6:
objRet = Integer.toString(pl.for_kurs);
break;
}
}
return objRet;
}
/*************************************************************************
* Hinweis: Je für Programm abänderbar
* @param row Index der Zeile
* @param col Position der Spalte
* @return false für not editable, true für editable
*************************************************************************/
public boolean isCellEditable(int row, int col)
{
return false;
}
/**************************************************************************
* Lädt die Daten von der Datenbank einmal in datatable und einmal in einen array
* und danach in data
*************************************************************************/
public void loadFromADatabase()
{
try
{
ar = new ArrayList();
//führt den SQL Befehl aus
rs = stm.executeQuery("SELECT * FROM PAY_D"); //man kann die Daten auch anders holen, und zwar File einlesen, usw
if (!rs.next()) // falls es kein nächstes gibt
bErg = false;
if (bErg) // default mäßig auf true, falls es kein Ergebnis gibt geht er nicht rein
{
do
{
bErg = true;
Pay_d pl = new Pay_d();
pl.Pay_id = rs.getShort(1);
pl.Pay_sub = rs.getShort(2);
pl.txt = rs.getString(3);
pl.for_currid = rs.getShort(4);
pl.bonuspnkt = rs.getInt(5);
pl.for_kurs = rs.getInt(6);
pl.for_fakt = rs.getShort(7);
ar.add(pl); //fügt die Klasse in den Array hinzu
}
while (rs.next()); //solange es einen nächsten gibt
}
rs.close();
stm.close();
data = ar.toArray(); // Array wird in ein Objekt geholt um es nachher für die Table auszugeben
fireTableDataChanged(); // lässt die Tabelle neu zeichnen
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
/*************************************************************************
* Beispiel lädt Daten aus einer Datei die mit ; getrennt sind
* @param fFile die Datei
************************************************************************/
public void loadFromAFile(File fFile)
{
int iAnzToken; // abfrage auf wieviel ; die linie hat
StringTokenizer token;
String line = "",buf[];
try{
//reader um aus der Datei zu lesen
BufferedReader br = new BufferedReader(
new InputStreamReader(
new FileInputStream(fFile)));
//Arrayliste neu initialisieren
ar = new ArrayList();
while ( (line = br.readLine()) != null)
{
token = new StringTokenizer(line, ";", false); //wird davon ausgegangen das es mit ; getrennt ist
iAnzToken = token.countTokens();
buf = new String[iAnzToken];
for(int x = 0; x != iAnzToken && token.hasMoreTokens(); x++)
buf[x] = token.nextToken();
Pay_d pl = new Pay_d();
pl.Pay_id = Short.parseShort(buf[0]);
pl.Pay_sub = Short.parseShort(buf[1]);
pl.txt = buf[2];
pl.for_currid = Short.parseShort(buf[3]);
pl.for_fakt = Short.parseShort(buf[4]);
pl.bonuspnkt = Integer.parseInt(buf[5]);
pl.for_kurs = Integer.parseInt(buf[6]);
ar.add(pl); //fügt die Klasse in den Array hinzu
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
/****************************************************************************
* Funktion liefert ein JTable zurück
* @return ein JTable objekt
***************************************************************************/
public JTable getModel()
{
return new JTable(this);
}
/****************************************************************************
* Setzt das Model neu!
* @param TableModel1 das tablemodel das gesetzt werden soll
***************************************************************************/
public void setModel(TableModel TableModel1)
{
ar = new ArrayList(); //alles neu schreiben
for (int x = 0; x != TableModel1.getRowCount(); x++)
{
//neues Objekt zum Einhängen
Pay_d pl = new Pay_d();
for (int y = 0; y != TableModel1.getColumnCount(); y++)
{
switch (y)
{
case 0:
pl.Pay_id = Short.parseShort(TableModel1.getValueAt(x, y).toString());
break;
case 1:
pl.Pay_sub = Short.parseShort(TableModel1.getValueAt(x, y).toString());
break;
case 2:
pl.txt = TableModel1.getValueAt(x, y).toString();
break;
case 3:
pl.for_currid = Short.parseShort(TableModel1.getValueAt(x, y).toString());
break;
case 4:
pl.for_fakt = Short.parseShort(TableModel1.getValueAt(x, y).toString());
break;
case 5:
pl.bonuspnkt = Integer.parseInt(TableModel1.getValueAt(x, y).toString());
break;
case 6:
pl.for_kurs = Integer.parseInt(TableModel1.getValueAt(x, y).toString());
break;
}
}
ar.add(lV);
}
data = ar.toArray(); // Array wird in ein Objekt gespeichert um es nachher für die Table auszugeben
}
/**************************************************************************
* Hilfsklasse, da die existierende Klasse nicht genommen werden kann,
* wegen eines Subsselects
*************************************************************************/
class Pay_d
{
short Pay_id; //Pay_id aus Datenbank Pay_d
short Pay_sub; //Pay_sub aus Datenbank Pay_d
String txt; // Bezeichnung aus Datenbank Pay_d
short for_currid; //Fremdwährungs Nummer aus Datenbank Pay_d
short for_fakt; // Faktor für Kommazeichen Kurse
int bonuspnkt; // Bonuspunkte aus Datenbank Pay_d
int for_kurs; // Kurs ohne Kommazeichen Kurse
}
}
Es sind 2 Funktionen zum Laden drinnen! Einmal von einer Datenbank und einmal aus einer Datei, falls ihr die Daten per Hand in die Struktur schreiben wollt, könnt ihr das auch tun, aber für das brauch ich woll kein Beispiel geben!
Nun der SortDecorator der euch die Tabelle auch schön brav nach ABC sortiert und die Pfeile reinmacht (die Pfeile wurden von Benis Beispiel genommen - Danke!)
Code:
import java.util.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
public class SortDecorator
extends DefaultTableCellRenderer
implements TableModel, TableModelListener
{
private TableModel realModel;
private int indexes[];
private static int iColumn = 0;
private static boolean bDescending = true;
private static ArrayList arSorter = null;
private static final double FACTOR = 0.95;
/****************************************************************************
* Konstruktor fürs Sortieren
* @param model model das übergeben wird
***************************************************************************/
public SortDecorator(TableModel model)
{
if (model == null)
throw new IllegalArgumentException("null models are not allowed");
this.realModel = model;
realModel.addTableModelListener(this);
allocate();
}
/****************************************************************************
* wenn sich was ändert
* @param tableModelEvent t
***************************************************************************/
public void tableChanged(TableModelEvent tableModelEvent)
{
allocate();
}
/****************************************************************************
* neue indexes werden allociert
***************************************************************************/
private void allocate()
{
indexes = new int[getRowCount()];
for (int i = 0; i < indexes.length; i++)
{
indexes[i] = i;
}
}
/****************************************************************************
* Funktion die nach der übergebenen Spalte sortiert
* @param column Spalte zum Sortieren
* @param bSorter ob mehrere Spalten sortiert werden sollen
***************************************************************************/
public void sort(int column,boolean bSorter)
{
GregorianCalendar zeit = new GregorianCalendar();
//wenn mehrere Spalten sortiert werden sollen!
if(bColumnAdd)
{
if(arSorter == null)
arSorter = new ArrayList();
if(!arSorter.contains(new Integer(column))) //wenn es noch nicht drinnen ist!
arSorter.add(new Integer(column));
}
else
arSorter = null;
bDescending = column != iColumn ? true : !bDescending;
//Zuweisung der Spalte
iColumn = column;
Date jetzt = new Date();
System.out.println(bDescending);
//ruft den Quicksort mit rowcount -1 auf
try
{
quicksort(0, realModel.getRowCount() - 1); //Achtung es wird von 0 weggezählt, daher -1
}
catch (Exception ex)
{
ex.printStackTrace();
}
GregorianCalendar zeit2 = new GregorianCalendar();
//Ausgabe wielange er fürs sortieren gebraucht hat in Millisekunden
System.out.println("Fürs SORTIEREN gebrauchte Millsekunden: " +
( (zeit2.getTimeInMillis() - zeit.getTimeInMillis())));
}
/***************************************************************************
* Führt den Quicksort durch
* @param lo niedrigstes
* @param hi höchstes
**************************************************************************/
private void quicksort(int lo, int hi)
{
int i = lo, j = hi;
//holt sich den mittleren String
String a = "";
if(arSorter == null) //wenn die ArrayList null ist, dann hole es normal
a = ( (String) realModel.getValueAt(indexes[ (lo + hi) / 2], iColumn)).
toLowerCase();
else
for(int y = 0; arSorter != null && y != arSorter.size(); y++) //ansonsten dazuzählen
{
int z = ((Integer)arSorter.get(y)).intValue();
a += ( ( String) realModel.getValueAt(indexes[( lo + hi) /2],z)).toLowerCase(); //anhängen!
}
toLowerCase();
// Aufteilung
while (i <= j)
{
if(bDescending)
while (get(indexes[i]).compareTo(a) < 0) //solange der mittlere String kleiner ist, wird erhöht
i++;
else
while (get(indexes[i]).compareTo(a) > 0) //solange der mittlere String größer ist, wird erhöht
i++;
if(bDescending)
while (get(indexes[j]).compareTo(a) > 0) //solange der mittlere String größer ist, wird erniedrigt
j--;
else
while (get(indexes[j]).compareTo(a) < 0) //solange der mittlere String kleiner ist, wird erniedrigt
j--;
//wenn i kleiner als j ist wird getauscht
if (i <= j)
{
swap(i, j);
i++;
j--;
}
}
// Rekursion
if (lo < j)
quicksort(lo, j);
if (i < hi)
quicksort(i, hi);
}
/***************************************************************************
* Funktion gibt einen String an der gewünschten Stelle zurück!
* Spalte wurde im sort vorgemerkt
* @param x welche Reihe
* @return den String
***************************************************************************/
private String get(int x)
{
String str = "";
try
{
if(arSorter == null) //normal den String holen
str = ( (String) realModel.getValueAt(x, iColumn)).toLowerCase();
else
{ //holt sich mehrere Strings
for(int y = 0; arSorter != null && y != arSorter.size(); y++)
{
int z = ((Integer)arSorter.get(y)).intValue();
str += ( ( String) realModel.getValueAt(x,z)).toLowerCase();
}
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
finally
{
return str;
}
}
/****************************************************************************
* Funktion die das austauschen 2er Objekte mittles index vornimmt
* @param i index 1
* @param j index 2
***************************************************************************/
public void swap(int i, int j)
{
int tmp = indexes[i];
indexes[i] = indexes[j];
indexes[j] = tmp;
}
/****************************************************************************
* Liefert die Zeilen zurück
* @return die Zeilen
***************************************************************************/
public int getRowCount()
{
return realModel.getRowCount();
}
/****************************************************************************
* Liefert die Spaltenanzahl zurück
* @return Spaltenanzahl
***************************************************************************/
public int getColumnCount()
{
return realModel.getColumnCount();
}
/****************************************************************************
* Liefert den Spaltennamen zurück
* @param int0 welche Spalte
* @return den Namen der Spalte
***************************************************************************/
public String getColumnName(int int0)
{
return realModel.getColumnName(int0);
}
/****************************************************************************
* Liefert die Spaltenklasse zurück
* @param int0 welche Spalte
* @return die Klasse der gewählten Spalte
***************************************************************************/
public Class getColumnClass(int int0)
{
return realModel.getColumnClass(int0);
}
/****************************************************************************
* Liefert zurück ob die Zelle editierbar ist oder nicht
* @param int0 x Koordinate
* @param int1 y Koordinate
* @return true oder false
***************************************************************************/
public boolean isCellEditable(int int0, int int1)
{
return realModel.isCellEditable(int0, int1);
}
/****************************************************************************
* Liefert einen Wert zu einer bestimmten x und y Koordinate zurück
* @param int0 x Koordinate
* @param int1 y Koordinate
* @return Objekt auf den Koordinaten
***************************************************************************/
public Object getValueAt(int int0, int int1)
{
return realModel.getValueAt(indexes[int0], int1);
}
/****************************************************************************
* Setzt ein Objekt an der gewissen stelle
* @param object welches objekt
* @param int1 x koordinate
* @param int2 y koordinate
***************************************************************************/
public void setValueAt(Object object, int int1, int int2)
{
realModel.setValueAt(object, indexes[int1], int2);
}
/****************************************************************************
* added einen neuen TableModelListener
* @param tableModelListener welchen Listener
***************************************************************************/
public void addTableModelListener(TableModelListener tableModelListener)
{
realModel.addTableModelListener(tableModelListener);
}
/****************************************************************************
* Removed den alten TableModellistener
* @param tableModelListener welcher listener
***************************************************************************/
public void removeTableModelListener(TableModelListener tableModelListener)
{
realModel.removeTableModelListener(tableModelListener);
}
/***************************************************************************
* Funktion gibt das Aussehen für den geklickt header zurück
* @param table die Table
* @param value das Objekt
* @param isSelected ob selektiert oder nicht
* @param hasFocus focus
* @param row reihe
* @param column spalte
* @return Komponente
**************************************************************************/
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column)
{
if (table != null) {
JTableHeader header = table.getTableHeader();
if (header != null) {
setForeground(header.getForeground());
setBackground(header.getBackground());
setFont(header.getFont());
}
}
setText((value == null) ? "" : value.toString());
if(arSorter == null)
if( table.convertColumnIndexToModel( column ) == this.iColumn ){
setBorder( BorderFactory.createRaisedBevelBorder() );
if( bDescending )
setIcon( createAscendingIcon() );
else
setIcon( createDescendingIcon() );
}
else{
setIcon( null );
setBorder( BorderFactory.createEmptyBorder() );
}
else
{
for (int x = 0; arSorter != null && x != arSorter.size(); x++)
{
int z = ( (Integer) arSorter.get(x)).intValue();
if (table.convertColumnIndexToModel(column) == z)
{
setBorder(BorderFactory.createRaisedBevelBorder());
Color color = getBackground();
//ist eigentlich die darker funktion, nur kann man sich seinen Factor selber setzen!
for(int i = x; i != arSorter.size(); i++)
{
color = new Color((int)Math.max((int)color.getRed() * FACTOR,0),
(int)Math.max((int)color.getGreen() * FACTOR,0),
(int)Math.max((int)color.getBlue()* FACTOR,0));
}
setBackground(color);
if (bDescending)
setIcon(createAscendingIcon());
else
setIcon(createDescendingIcon());
}
else if (!arSorter.contains(new Integer(column)))
{
setIcon(null);
setBorder(BorderFactory.createEmptyBorder());
}
}
return this;
}
/***************************************************************************
* Funktion zeichnet das Icon und gibt es danach zurück
* @return das Icon
**************************************************************************/
protected Icon createAscendingIcon(){
return new Icon(){
public int getIconHeight() {
return 3;
}
public int getIconWidth() {
return 5;
}
public void paintIcon(Component c, Graphics g, int x, int y) {
g.setColor( Color.BLACK );
g.drawLine( x, y, x+4, y );
g.drawLine( x+1, y+1, x+3, y+1 );
g.drawLine( x+2, y+2, x+2, y+2 );
}
};
}
/****************************************************************************
* Funktion zeichnet das Icon und gibt es zurück
* @return das Icon
***************************************************************************/
protected Icon createDescendingIcon()
{
return new Icon(){
public int getIconHeight() {
return 3;
}
public int getIconWidth() {
return 5;
}
public void paintIcon(Component c, Graphics g, int x, int y) {
g.setColor( Color.BLACK );
g.drawLine( x, y+2, x+4, y+2 );
g.drawLine( x+1, y+1, x+3, y+1 );
g.drawLine( x+2, y, x+2, y );
}
};
}
}
Hatte früher hier den BubbleSort welcher bei ca. 100000 Zeilen sehr sehr lange gebraucht hat, aber der QuickSort ist huiiii
Also, hoffe es klappt (habs net ausprobiert, da ich viele Funktionen rausgenommen habe, die nur ich brauche)!