# CellEditor der nur Eingaben int 1-9  und "null" er



## VIDEN (27. Okt 2006)

So, jetzt zum CellEditor.

Ich will das man in die Zellen meines JTables NUR Zahlen von 1-9 eintragen kann (Sudoku Spielfeld). Es soll sofort verhindert werden, dass mehr wie eine Stelle eingetragen wird und andere Zeichen. 
Deshalb habe ich diese Klasse hier von SUN benutzt:
http://java.sun.com/docs/books/tutorial/uiswing/components/examples/IntegerEditor.java
und folgendes in den JTable geschrieben:

```
grid.setDefaultEditor(Integer.class, new IntegerEditor(1, 9));
```
Sobald ich nun eine andere Zahl eingebe kommt ein Error und ich muss die Zahl korrigieren.
Es ist aber trotsdem möglich andere Zahlen einzugeben, nur kommt eben dann der Error.
Gibt es auch einen Möglichkeit das die andere Zahlen erst garnicht eingegeben werden können?
d.h. nur eine Zahl und die darf nur 1-9 sein?

Das zweite Problem ist, ausser den 1-9 würde ich gerne noch "null" akzeptieren.
zB Man will eine Zahl in ein Feld schreiben, merkt aber dann, dass das nicht geht. Also will man ohne Eingabe wieder aus dem Editmode gehen.
Ich habe leider keine Möglichkeit gefunden das "null" mit in die validValues aufzunehmen.


Grüsse David


----------



## André Uhres (28. Okt 2006)

Alternative: JTable nicht editierbar machen und KeyListener dran machen. 
Bei keyPressed:

```
char c = evt.getKeyChar();
        if(Character.isDigit(c)){
            sudokuTable.setValueAt(c == '0' ? null : c,
                    sudokuTable.getSelectedRow(),sudokuTable.getSelectedColumn());
        }
```

Kleines Beispiel:

```
package table;
/*
 * SudokuTableDemo.java
 */
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
public class SudokuTableDemo extends JFrame {
    private JTable sudokuTable;
    public SudokuTableDemo() {
        super("Sudoku");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(174,171);
        setLocationRelativeTo(null);
        sudokuTable = new JTable(){
            public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
                Component c = super.prepareRenderer(renderer, row, column);
                if (!(isRowSelected(row) && isColumnSelected(column))) {
                    c.setBackground(Color.lightGray);
                    ((JLabel)c).setHorizontalAlignment(JLabel.CENTER);
                    if((row>=0 && row <=2) && (column>=3 && column<=5)) c.setBackground(Color.white);
                    if((row>=3 && row <=5) && (column>=0 && column<=2)) c.setBackground(Color.white);
                    if((row>=3 && row <=5) && (column>=6 && column<=8)) c.setBackground(Color.white);
                    if((row>=6 && row <=8) && (column>=3 && column<=5)) c.setBackground(Color.white);
                }
                return c;
            }
        };
        sudokuTable.setModel(new DefaultTableModel(9,9) {
            Class[] types = new Class [] {
                Integer.class, Integer.class, Integer.class, Integer.class, 
                Integer.class, Integer.class, Integer.class, Integer.class, Integer.class
            };
            public Class getColumnClass(int columnIndex) {
                return types [columnIndex];
            }
            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return false;
            }
        });
        sudokuTable.setCellSelectionEnabled(true);
        sudokuTable.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent evt) {
                sudokuKeyPressed(evt);
            }
        });
        sudokuTable.changeSelection(0,0,false,false);
        getContentPane().add(sudokuTable, BorderLayout.CENTER);
    }
    private void sudokuKeyPressed(KeyEvent evt) {
        char c = evt.getKeyChar();
        if(Character.isDigit(c)){
            sudokuTable.setValueAt(c == '0' ? null : c,
                    sudokuTable.getSelectedRow(),sudokuTable.getSelectedColumn());
        }
    }
    public static void main(String args[]) {new SudokuTableDemo().setVisible(true);}
}
```


----------



## VIDEN (13. Nov 2006)

Danke für die Antwort, ich hatte die vorletzte Woche frei und musste letze Woche auf die Berufsakademie und kann mich deswegen erst jetzt wieder mit dem Thema beschäftigen.

Wenn ich sudokuKeyPressed(KeyEvent evt) benutze kann ich aber jedes Feld ändern oder nicht?
Ich will nähmlich, dass die gegebenen Zahlen und die vom Solver gelösten Felder nicht Editierbar sind.

Und was machst du genau in dieser Zeile?:


```
sudokuTable.setValueAt(c == '0' ? null : c, 
                    sudokuTable.getSelectedRow(),sudokuTable.getSelectedColumn());
```

ich kenne den Operator "?" nicht und was bedeutet das "null : c" danach?


Grüsse David


----------



## André Uhres (13. Nov 2006)

VIDEN hat gesagt.:
			
		

> ..Wenn ich sudokuKeyPressed(KeyEvent evt) benutze kann ich aber jedes Feld ändern oder nicht?
> Ich will nähmlich, dass die gegebenen Zahlen und die vom Solver gelösten Felder nicht Editierbar sind.




```
private void sudokuKeyPressed(KeyEvent evt) {
        int row = sudokuTable.getSelectedRow();
        int column = sudokuTable.getSelectedColumn();
        char c = evt.getKeyChar();
        if(Character.isDigit(c) && !isCellSolved(row, column)){//<----------------------
            sudokuTable.setValueAt(c == '0' ? null : c, row, column);
        }
    }
    private boolean isCellSolved(int row, int column) {//<-----------------------------
        //hier bestimmst du was nicht mehr editierbar ist:
        if( row == 1 && column == 1) {
            return true;
        }
        return false;
    }
```



			
				VIDEN hat gesagt.:
			
		

> ..ich kenne den Operator "?" nicht ..


http://www.java-forum.org/de/viewtopic.php?p=183263#183263


----------



## VIDEN (20. Nov 2006)

hey,

Habe es versucht umzusetzten aber ich habe ein kleines Problem:

"sudokuKeyPressed" übergibt dem JTable eine "char" Variable die in das Feld geschrieben werden soll.
Das "setValueAt" von meinem Table Model braucht aber eine int Variable, damit es noch kurze Berechnungen durchführen kann. Ich habe geschaut aber es scheint keine schöne saubere char to int Lösung zu geben -.-


```
public void setValueAt(Object value, int row, int col) {
            if(value==null)
                return;
            if(data[row][col].num==0&&(Integer)value!=0&&value!=null)
                currentBoard.userMatrix.incNumSolvedCells();
            if(data[row][col].num!=0&&((Integer)value==0||value==null))
                currentBoard.userMatrix.decNumSolvedCells();
            data[row][col].num=(Integer) value;
            data[row][col].setColor("black");
            fireTableCellUpdated(row, col);
        }
```

Wenn ich hier jetzt die char Variable übergebe kommt es immer zu Fehlern.

Grüsse David

EDIT:

okay ich habe es jetzt hinbekommen aber es sieht finde ich nicht all zu sauber aus...
Ach ja und ich habe "MyTableModel" in mein "Board" Integriert, was das die ganzen Zellen des Sudokus sowieso schon verwalted:


```
public void setValueAt(Object value, int row, int col) {
        if(value==null)
            return;
        String strValue=value.toString();
        int nValue=Integer.parseInt(strValue);

        userMatrix.setCellValue(row, col, nValue);
        userMatrix.matrix[row][col].setColor("black");
        fireTableCellUpdated(row, col);
    }
```

Grüsse David


----------



## VIDEN (23. Nov 2006)

Noch eine Frage, wie ändere ich die Grösse des JTables?
Im NetBeans Graphical Editor gibt es zwar 2 Felder für Size Horizotal und Size Vertical, aber wenn ich diese verändere, wird die Tabelle nur um einen weissen Rand der grösse erweitert. die Tabelle selber bleibt gleich. Daher gehe ich davon aus, das ich das irgendwo im meinem Renderer oder TableModel oder was weis ich wo ändern muss nur weis ich eben nicht wo.
Das Problem ist nämlich, dass meine Tabelle minimal breiter wie hoch ist.

Grüsse David


----------



## André Uhres (23. Nov 2006)

Hast du veilleicht "sudokuTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF)" gesetzt?
Sonst poste mal deinen Code.


----------



## VIDEN (24. Nov 2006)

Hmm ne das habe ich nirgends gefunden.

Das hier müsste der generierte Code sein, der die Grösse bestimmt:

sudokuTable ist mein JTable,
gridPanel ist das JPanel in dem es drinne ist. ausser dem JTable ist nichts im gridPanel.


```
sudokuTable.setModel(currentBoard);
        sudokuTable.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent evt) {
                sudokuKeyPressed(evt);
            }
        });
        Renderer cellRenderer= new Renderer();
        sudokuTable.setDefaultRenderer(Integer.class, cellRenderer);
        sudokuTable.setCellSelectionEnabled(true);

        org.jdesktop.layout.GroupLayout gridPanelLayout = new org.jdesktop.layout.GroupLayout(gridPanel);
        gridPanel.setLayout(gridPanelLayout);
        gridPanelLayout.setHorizontalGroup(
            gridPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(gridPanelLayout.createSequentialGroup()
                .addContainerGap()
                .add(sudokuTable, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 180, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        gridPanelLayout.setVerticalGroup(
            gridPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(gridPanelLayout.createSequentialGroup()
                .addContainerGap()
                .add(sudokuTable, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 145, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
```


Wenn ich es so eingestellt habe: JTable auf 180x180 und JPanel auf default sieht es so aus:





Ist der JTable auf 180x145 (wie im Code) und der JPanel auf default sieht es so aus:





Das ist meine erste GUI die ich mache, daher kenne ich mich kaum aus, aber macht es überhaupt Sinn, den JTable in einen JPanel zu machen, wenn er eh das einzige Objekt in dem JPanel ist?

Ich hoffe du kannst helfen 

Grüsse David

PS: Bei bedarf kann ich auch den ganzen Code zur verfügung stellen


----------



## André Uhres (24. Nov 2006)

Versuch's mal so:
Design view | Inspector: 
Rechstklick auf JFrame --> Set Layout: BorderLayout 
Rechstklick auf gridPanel --> Set Layout: GridBagLayout


----------



## VIDEN (24. Nov 2006)

damit hat er mir das ganze Interface zerschossen -.- also hab ichs lieber mal wieder Rückgaängig gemacht ;-)

falls es helfen sollte, ich habe hier mal mein ganzes NetBeansProject gepackt:

http://www.file-upload.net/download_24.11.06_hhigo.zip.html

alternativer link:

http://www.uploadtemple.com/view.php/1164372738.zip

(sry kann nicht auf meinen eigenen FTP laden, da die Ports hier bei der Arbeit gesperrt sind)

Grüsse David


----------



## André Uhres (24. Nov 2006)

Probier das mal:
http://member.file-upload.net/uhrand/Sudoku.rar

EDIT: Du kannst aber auch deinen Code beibehalten und die Zeilenhöhe regeln
mit "sudokuTable.setRowHeight(20);"


----------



## VIDEN (27. Nov 2006)

vielen Dank! Hat so wunderbar funktioniert.
Jetzt kann ich endlich meine erste stable Beta releasen. 

Grüsse David


----------

