19. februar 2003 - 22:06Der er
17 kommentarer og 1 løsning
Keylistener på en JTable.
Jeg prøver at lave en keylistener til den enkelte celle i en JTable. Problemet er at jeg ikke kan få tabellen til at stoppe med at fylde flere tegn ind i sig når max værdien nås. Min keylistener ser sådan ud:
protected class CellHandler extends KeyAdapter { int fieldSize, code; String sign = ""; JTable table; public CellHandler(int size, JTable table) { this.fieldSize = size; this.table = table; }
Jeg har ikke den store erfaring med JTable så jeg ved ikke om det er den forkerte måde at gøre det på. Måske skal der addes en keylistener pr celle istedet for en fælles til tabellen. Jeg har lavet min egen TableModel ved at arve fra AbstractTableModel. Håber der er nogen har lidt erfaring at dele ud af.
Det er ikke optimalt at bruge en KeyListener. Bedre er det at anvende en DocumentListener på cellen og lade cellen være repræsenteret af et JTextField.
return new String(toString); } } //ATableModel.java: import javax.swing.table.AbstractTableModel; import javax.swing.*;
import java.util.Vector;
public class ATableModel extends AbstractTableModel { private String[] columns = { "Navn", "Adresse", "Telefonnummer" }; private Vector data;
public ATableModel() { data = new Vector(); }
public int getColumnCount() { return columns.length; }
public int getRowCount() { return data.size(); }
public String getColumnName(int column) { return columns[column]; }
public Object getValueAt(int row, int column) { TableElement element = (TableElement)data.elementAt(row); String value = ""; switch( column ) { case 0: { value = element.getNavn(); } break; case 1: { value = element.getAdresse(); } break; case 2: { value = element.getTelefonNummer(); } break; } return value; }
public Class getColumnClass(int column) { return getValueAt(0, column).getClass(); }
public boolean isCellEditable(int row, int column) { switch( column ) { case 0: { return false; } case 1: { return true; } case 2: { return false; } } return false; }
public void setValueAt(Object value, int row, int column) { switch( column ) { case 0: { ((TableElement)data.elementAt(row)).setNavn((String)value); } break; case 1: { ((TableElement)data.elementAt(row)).setAdresse((String)value); } break; case 2: { ((TableElement)data.elementAt(row)).setTelefonNummer((String)value); } break; } fireTableCellUpdated(row, column); }
public void addTableElement(TableElement element) { data.add(element); fireTableRowsInserted(data.size(), data.size()); }
int result = JOptionPane.showOptionDialog(this, messages, "Indtast", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null, options, options[0] ); if( result == 0) tableModel.addTableElement(new TableElement(navn.getText(), adresse.getText(), telefon.getText())); } private void removeElement() { tableModel.removeTableElement(table.getSelectedRow()); } private class PopupListener extends MouseAdapter { public void mousePressed(MouseEvent e) { maybeShowPopup(e); }
public void mouseReleased(MouseEvent e) { maybeShowPopup(e); }
public void mouseClicked(MouseEvent e) { maybeShowPopup(e); }
public void maybeShowPopup(MouseEvent e) { if (e.isPopupTrigger()) {
JTable table = (JTable)e.getComponent(); Point point = new Point(e.getX(), e.getY()); table.setRowSelectionInterval(table.rowAtPoint( point ),table.rowAtPoint( point )); table.setColumnSelectionInterval(table.columnAtPoint( point ),table.columnAtPoint( point )); String columnName = table.getColumnName(table.getSelectedColumn()); popup.show(e.getComponent(), point.x, point.y); } } } private class FixedSizeDocument extends PlainDocument {
private int limit;
public FixedSizeDocument(int limit) { this.limit = limit; }
public void insertString (int offs, String str, AttributeSet a) throws BadLocationException { if (getLength() + str.length() <= limit) super.insertString(offs, str, a); } } }
class TestTableTest {
public static void main(String[] args) { new TableTest().show(); } }
Når man skriver i cellen er der en lille kant fra JTextField. jeg synes det ser bedst ud hvis den ikke er der da der er kant "nok" pga tabellen. derfor kan man skrive field.setBorder(null); lige efter man opretter field i koden. derved forsvinder kanten. viht du ved det sikekrt men måske andre kan få glæde af det ;-)
jeg har lige et opfølgende spørgsmål til dig viht. jeg har bemærket den sidste værdi man indtaster i en celle før man afvikler kommadoen getValueAt(row,column) ikke er opdateret med den sidst indtastede værdi. jeg har ikke lige selv kunnet gennemskue den. Vædien fås fint nok med getSelected..() men i en løkke er det ikke optimalt at skulle tage hensyn til en manglende opdatering af værdi. håber du har svaret. på forhånd tak.
i dit eksempel indtaster du selvfølgelig ikke direkte i boksen men ved at indsætte før du kalder metoden addElement i din button-handler vil du kunne se mit problem. For at se det skal du først tilføje en række, dernæst ændre i feks adressen og dernæst klikek på tilføj. Hvis du har en ide til hvordan det løses så skriv lige et par linier.
Jeg ved ikke om jeg forstår dit spørgsmål rigtig.. men hvis jeg først indsætter vha addElement() værdierne: "Navn", "Adresse" og "Telefonnummer". Derefter går jeg ind og ændrer adressen til "jesper". Jeg trykker så på tilføj og din løkke skriver følgende: 0 0 Navn 0 1 jesper 0 2 Telefonnummer
Det er da den nyeste indtastede værdi? Jeg har sikkert misforstået dit spørgsmål, men uddyb gerne hvis jeg ikke er med.
Problemet opstår når man ændrer indholdet i cellen og derefter klikker på tilføj inden man har trykket på enter mens markøren stadig er aktiv i cellen. Håber du kan se hvad jeg mener ved at skrive din actionlistener over. jeg tror ikke at det bare er mig...
Jamen tabellens indhold bliver ikke opdateret før du har trykket enter og kaldt setValueAt(...); Ellers skal du kalde setValueAt(..) hver gang brugeren indtaster noget i feltet, det kan du jo gøre med den DocumentListener der er på JTextField'et.
Sådan her: TableColumn textFieldColumn = table.getColumnModel().getColumn(1); JTextField field = new JTextField(new FixedSizeDocument(10), "", 20); final Document document = field.getDocument(); document.addDocumentListener(new DocumentListener() { public void changedUpdate(DocumentEvent e ) { getInput(document); }
public void insertUpdate( DocumentEvent e ){ getInput(document); }
public void removeUpdate( DocumentEvent e ){ getInput(document); }
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.