# Matrix mit JCheckBox



## eren (30. Dez 2009)

Hi Leute,

hab folgendes Problem:

Ich habe für die Schule ein Programm schreiben müssen, welches Graphen auswertet. Die Algorithmen habe ich bereits geschrieben jetzt würde noch eine graphische Oberfläche fehlen. Bis jetzt habe ich folgendes gemacht:
Als Layout für das Fenster habe BorderLayout verwendet und habe als erstes einen JSlider, für die Größe des Graphen, in NORTH positioniert.
Weiters habe ich einen Button "auswerten" in SOUTH eingefügt, um die Auswertung starten zu können.
Als nächstes hätte ich gern noch, dass ich die Matrix mittels JCheckBox(es) darstelle nur weis ich nicht wie das geht.

Bitte um Hilfe.
Danke
Mfg


----------



## javimka (30. Dez 2009)

Meinst du sowas?

```
import java.awt.GridLayout;

import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class CheckBoxMatrix extends JPanel {

	public CheckBoxMatrix(int n, int m) {
		super(new GridLayout(n, m));
		for (int i=0;i<n*m;i++) {
			add(new JCheckBox());
		}
	}
	
	public static void main(String[] args) {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				JFrame frame = new JFrame("CheckBox Matrix");
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				frame.add(new CheckBoxMatrix(10,16));
				frame.pack();
				frame.setLocationRelativeTo(null);
				frame.setVisible(true);
			}
		});
	}
}
```
Ist ein JPanel, das nxm CheckBoxen beinhaltet.


----------



## eren (30. Dez 2009)

Hallo javimka,

ja genau sowas, nur gibt es da die Möglichkeit das die checkboxes näher zueinander stehen??? Bei mir sind da sehr große Abstände, das sieht ungefähr so aus:
n=3
m=3

[]             []               []


[]             []               []


[]             []               []

Was ich gerne hätte:
n=3
m=3

[] [] []
[] [] []
[] [] []

Und noch eine weitere Frage:
Kann man irgendwie die Diagonale sperren ??? Aber nur die von links oben nach rechts unten. Ich meine das nur die Checkboxes außerhalb der Diagonale anklickbar sind. 
Ungefähr so:

 []  [x] [x]
[x]  []  [x]
[x] [x]  []

Danke
Mfg


----------



## eren (30. Dez 2009)

Hallo javimka,

da wäre noch was:
Ich brauche die CheckBoxMatrix später noch für Berechnungen, dafür muss ich aber auch wissen wo jetzt überall ein Häcken gesetzt wurde um eine Matrix erstellen zu können, mit der ich dann weiterrechne. Geht das mit der Methode von dir ???
Bsp.:

 []  [] [x] []
 []  []  [] [x]
[x] []  []  []
 [] [x] []  []

0010
0001
1000
0100

Und noch etwas was mit erst jetzt auffällt:
Wenn ich jetzt angenommen eine 4*4 Matrix habe
   1  2  3  4
1 [] [] [] []
2 [] [] [] []
3 [] [] [] []
4 [] [] [] []

und ich jetzt bei [1,3] ein Häcken setze, sollte es auch automatisch bei [3,1] auch ein Häcken setzen.
Wie würde das dann funktionieren ? JCheckBox[][] ? Gibt es so was ???

Bitte um Hilfe ;(


----------



## javimka (30. Dez 2009)

Um jeweils zu jeder CheckBox das Gegenstück auf der anderen Seite der Diagonale zu selektieren, müssen die CheckBoxen wissen, an welcher Position sie stehen. Am einfachsten realisieren wir das, wenn wir eine neue Klasse (ich habe sie MatrixBox genannt) definieren, die von der JCheckBox erbt. Der Konstruktor dieser Klasse nimmt die Positionen r (Row) und c (Column) entgegen und speichert sie. (Zeilen 53-67)

Dann definieren wir ein Array [c]MatrixBox[][] boxes[/c], in welchem alle diese Boxen gespeichert werden. Ausserdem kriegt jede Box einen ActionListener, der dafür sorft, dass das Gegenstück selektiert wird, wenn eine CheckBox selektiert wird. Oder auch deselektiert. (Zeilen 19-25)

Um die Diagonale zu deaktivieren, überprüft jede Box, ob sie in der Diagonale liegt. Dies ist der Fall, wenn r==c ist. Dann wird setEnabled(false) aufgerufen. (Zeilen60-62)

Um den Minimalabstand zu den Nachbarn zu definieren, kannst du setBorder verwenden und der CheckBox ein EmptyBorder geben. Die Zahlen definieren die Abstände zu den Nachbarkomponenten (Zeile 65).
Es bleibt das Problem, dass sich das Panel auseinanderziehen lässt und dadurch die Boxen auseinander gehen. Um dieses Problem zu lösen, musst du einige Layouts kombinieren. Eine ganz einfache Idee wäre es, ein ZwischenPanel zu erstellen, das ein FlowLayout hat und in dem dann die Matrix hineingelegt wird. (Zeilen 43-45)
Wenn dir ein anderes Verhalten vorschwebt, was passieren soll, wenn sich die Komponente ausdehnt, müsstest du das etwas genauer definieren. Wenn du willst, dass die Matrix immer gleich gross in der Mitte ist, wären zwei Panels mit BoxLayout hilfreich. Ich verwende gerne BoxLayouts, weil sie die bevorzugten Grössen der Komponenten gut berücksichtigen.


```
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;

public class CheckBoxMatrix extends JPanel {

	private MatrixBox[][] boxes; // Alle Checkboxen
	
	public CheckBoxMatrix(int n, int m) {
		super(new GridLayout(n, m));
		
		ActionListener al = new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				// Selektiere auch das Gegenstück
				MatrixBox box = (MatrixBox) e.getSource();
				boxes[box.c][box.r].setSelected(box.isSelected());
			}
		};
		
		boxes = new MatrixBox[n][m];
		for (int i=0;i<n;i++) {
			for (int j=0;j<m;j++) {
				MatrixBox box = new MatrixBox(i, j);
				box.addActionListener(al);
				add(box);
				boxes[i][j] = box;
			}
		}
	}
	
	public static void main(String[] args) {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				JFrame frame = new JFrame("CheckBox Matrix");
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				JPanel pnl = new JPanel(new FlowLayout());
				pnl.add(new CheckBoxMatrix(10,6));
				frame.add(pnl);
				frame.pack();
				frame.setLocationRelativeTo(null);
				frame.setVisible(true);
			}
		});
	}
	
	private class MatrixBox extends JCheckBox {
		
		private int r,c;
		
		private MatrixBox(int r, int c) {
			this.r = r;
			this.c = c;
			if (r==c) { // Diagonale deaktivieren
				setEnabled(false);
			}
			
			// Minimalabstand zu den Nachbarn definieren
			setBorder(new EmptyBorder(2,2,2,2));
		}
	}
}
```


----------



## eren (31. Dez 2009)

Hi,

cool danke, jedoch hat das mit den Abständen leider nicht geklappt. Aber ich habe da was gefunden (setBounds) nur weis ich nicht wo genau ich das jetzt einbauen soll.

_setBounds

public void setBounds(int x,
                      int y,
                      int width,
                      int height)
Moves and resizes this component. The new location of the top-left corner is specified by x and y, and the new size is specified by width and height.
Parameters:
x - the new x-coordinate of this component
y - the new y-coordinate of this component
width - the new width of this component
height - the new height of this component_

das würde glaub ich dann so funktionieren: boxes_[j].setBounds(x, y, width, height)

Und noch was:
Also nachdem man die Checkboxes ausgewählt hat, würde ich gerne in ein genauso großes 2 Dimensionales Array die Werte einlesen. D.h., eine Matrix mit 0 und 1, wobei 0 kein Hackerl und 1 ein gesetztes Hackerl bedeutet. 
Kann es sein das ich das mit einer CheckBoxMatrix Instanz mache ?? Ich muss die Matrix durchlaufen und an jeder position mit isSelected() == true prüfen und an der jeweiligen Position dann einen 1er in der Matrix setzen.

Mfg_


----------



## javimka (31. Dez 2009)

setBounds() funktioniert aber nur, wenn du kein Layout verwendest, was du aber besser nicht tun solltest. Ansonsten ruft das Layout selber setBounds auf. Mach mir mal eine Zeichnung, die das ganze aussehen soll, wenn das Fenster vergrössert wird, dann kann ich dir schon sagen, welche(s) Layout(s) du verwenden kannst.
setBorder() funktioniert. Gib mal grosse und kleine Werte ein, dann wirst du sehen, dass sich die Abstände verändern.

Lass den ActionListener das Array verwalten. Entweder ein boolean[][] oder eine int[][], was dir besser passt. Du weisst ja die Koordinaten, der JCheckBox, die den ActionListener aufgeruden hat: box.r und box.c.
Mit denen kannst du auch in deinem Array die richtigen Werte setzen.


----------



## eren (31. Dez 2009)

Hallo,

im Anhang sind 2 Screenshots(Bild1, Bils2) von einem Freund von mir, so ungefähr hätte ich die Anordnung. Die blauen Felder sollen die Zeilennr. und Spaltennr. darstellen

Es befindet sich noch ein weiterer Screenshot(Bild3) von meiner GUI. Irgendwie verändert sich leider auch mit setBorder() auch nichts. Ich habe die 2 und 10 versucht, aber die Ansicht ändert sich nicht.
Und den Slider bekomme ich auch nicht kleiner. Ich habe es mit FlowLayout(FlowLayout.LEFT) in einem Panel versucht, nur das überlappen sich die Zahlen und es wird nicht erkennbar. Ich habe es auch versucht einfach nur mit add(slider) statt add(slider, BorderLayout.NORTH), aber dann verschwindet der Slider ganz.


----------



## javimka (31. Dez 2009)

Dann so:

```
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;

public class CheckBoxMatrix extends JPanel {

	private MatrixBox[][] boxes; // Alle Checkboxen
	
	public CheckBoxMatrix(int n, int m) {
		super(new FlowLayout(FlowLayout.LEFT));
		JPanel panelContent = new JPanel(new GridLayout(n+1,m+1));
		
		ActionListener al = new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				// Selektiere auch das Gegenstück
				MatrixBox box = (MatrixBox) e.getSource();
				boxes[box.c][box.r].setSelected(box.isSelected());
			}
		};
		
		panelContent.add(Box.createGlue());
		for (int j=0;j<m;j++) {
			panelContent.add(new JLabel(String.valueOf(j+1)));
		}
		
		boxes = new MatrixBox[n][m];
		for (int i=0;i<n;i++) {
			panelContent.add(new JLabel(String.valueOf(i+1)));
			for (int j=0;j<m;j++) {
				MatrixBox box = new MatrixBox(i, j);
				box.addActionListener(al);
				panelContent.add(box);
				boxes[i][j] = box;
			}
		}
		add(panelContent);
	}
	
	public static void main(String[] args) {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				JFrame frame = new JFrame("CheckBox Matrix");
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				frame.add(new CheckBoxMatrix(10,6),BorderLayout.CENTER);
				frame.add(new JButton("Neue Knotenauswahl"),BorderLayout.SOUTH);
				frame.add(new JButton("Matrix Erstellen"),BorderLayout.EAST);
				frame.pack();
				frame.setLocationRelativeTo(null);
				frame.setVisible(true);
			}
		});
	}
	
	private class MatrixBox extends JCheckBox {
		
		private int r,c;
		
		private MatrixBox(int r, int c) {
			this.r = r;
			this.c = c;
			if (r==c) { // Diagonale deaktivieren
				setEnabled(false);
			}
			
			// Minimalabstand zu den Nachbarn definieren
			setBorder(new EmptyBorder(2,2,2,2));
		}
	}
}
```
Mit setBorder auf Zeile 77 kannst du die Abstände einstellen.


----------



## eren (31. Dez 2009)

Ich weis, dass ich jedesmal mit einem neuen Problem zu dir komme, tut mir echt Leid. Mir wird es langsam aber sicher echt unangenehm 

Mein jetztiges Problem werde ich ebenfalls versuchen mit Grafiken zu erläutern:
In Bild1 siehst du eine 15*15 Matrix, mit ein paar Hackerl die gesetzt sind und im nächsten Bild2 eine 9*9 Matrix, jedoch ist es anscheinend so das er sich die 15*15 Matrix merkt und nur das Aussehen auf eine 9*9 Matrix heruntersetzt, denn man kann nach wie vor Checkboxes außerhalb der 9*9 Matrix anklicken.

Woran mag das liegen ??
Danke


----------



## javimka (31. Dez 2009)

Schon Recht, dazu sind wir ja da. Wie sieht denn der Code dazu aus?


----------



## eren (31. Dez 2009)

Das ist der Code für das Hauptfenster und ganz unten ab Zeile 93 habe ich einen ChangeListener für den Slider implementiert der auf Veränderungen horcht, und je nach momentanen Wert die Ansicht aktualisiert.


```
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;



public class Hauptfenster extends JFrame {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private JSlider slider;
	private JButton auswerten;
	private JPanel panelButton;
	private CheckBoxMatrix boxes;
	
	private VerarbeitungsFenster verarbeitungsfenster;
	
	private MyListener ml;
	private MyChangeListener cl;
	
	
	public Hauptfenster() {
		init();
		initComponents();
		addComponents();
		
		setVisible(true);
	}
	
	private void init() {
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setSize(550,550);
		setTitle("Eren Cindi / 6ABINS - Graphentheorie");
		setResizable(true);
		setLayout(new BorderLayout());
	}

	
	private void initComponents() {
		slider = new JSlider(3,15,9);
		slider.setBorder(BorderFactory.createTitledBorder("Größe des Graphen wählen !"));
		slider.setMajorTickSpacing(1);
		slider.setPaintTicks(true);
		slider.setPaintLabels(true);
		slider.setPaintTrack(true);
		
		boxes = new CheckBoxMatrix(slider.getValue(), slider.getValue());
		
		auswerten = new JButton("auswerten");

		panelButton = new JPanel();
		panelButton.setLayout(new FlowLayout(FlowLayout.RIGHT));
				
		ml = new MyListener();
		cl = new MyChangeListener();
	}
	
	private void addComponents() {
		slider.addChangeListener(cl);
		
		auswerten.addActionListener(ml);
		
		panelButton.add(auswerten);
		
		add(slider, BorderLayout.NORTH);
		add(boxes, BorderLayout.CENTER);
		add(panelButton, BorderLayout.SOUTH);
	}

	
	 class MyListener implements ActionListener {

		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
			if(e.getSource() == auswerten) {
				verarbeitungsfenster = new VerarbeitungsFenster();
			}
		}
	 }
	 
	 class MyChangeListener implements ChangeListener {

		public void stateChanged(ChangeEvent e) {
			// TODO Auto-generated method stub
			JSlider source = (JSlider) e.getSource();
			if(!source.getValueIsAdjusting()) {
				int value = source.getValue();
				boxes = new CheckBoxMatrix(value, value);
				add(boxes, BorderLayout.CENTER);
			}
		}
	 }
}
```


----------



## javimka (31. Dez 2009)

Du fügst zwar jeweils eine neue CheckBoxMatrix hinzu, aber du löschst sie nie. Das sollte eigentlich bereits helfen.
Schreib einfach [c]remove(boxes)[/c] bevor du eine neue Matrix auf boxes speicherst (Zeile 100).
Nach dem add() Befehel solltest du noch validate() aufrufen, damit die Komponenten neu geortned werden.


----------



## eren (31. Dez 2009)

:toll::toll::toll::toll:

echt super Danke für deine Zeit und Mühe, ist richtig perfekt geworden.
Lg Eren


----------



## eren (31. Dez 2009)

Hallo nochmals,

anscheinend wirst du mich nicht so leicht los 

Aber bezüglich deiner Aussage habe ich noch eine Frage:



> Lass den ActionListener das Array verwalten. Entweder ein boolean[][] oder eine int[][], was dir besser passt. Du weisst ja die Koordinaten, der JCheckBox, die den ActionListener aufgeruden hat: box.r und box.c.
> Mit denen kannst du auch in deinem Array die richtigen Werte setzen.



Also das Hauptfenster kennst du ja bereits. Da habe ich rechts unten eine Button "auswerten". Nach Betätigung dieses Button erscheint ein neues Fenster "Verarbeitungsfenster" wo ich die Auswertungen ausgeben möchte. Hier der momentane Code:


```
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class VerarbeitungsFenster extends JFrame {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	private JButton schließen;
	private MyListener mlv;
	private JPanel panelschließen;
	
	
	public VerarbeitungsFenster() {
		init();
		initComponents();
		addComponents();
	}
	
	private void init() {
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		setTitle("Verarbeitungsfenster");
		setSize(550, 550);
		setLayout(new BorderLayout());
		setVisible(true);
	}
	
	private void initComponents() {
		panelschließen = new JPanel();
		panelschließen.setLayout(new FlowLayout(FlowLayout.RIGHT));
		
		schließen = new JButton("schließen");
		
		mlv = new MyListener();
	}

	private void addComponents() {
		panelschließen.add(schließen);
		
		add(panelschließen, BorderLayout.SOUTH);
		
		schließen.addActionListener(mlv);
	}
	
	class MyListener implements ActionListener {

		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
			if(e.getSource() == schließen) {
				dispose();
			}
		}
		
	}
}
```

Nun zur eigentlichen Frage:


> Und noch was:
> Also nachdem man die Checkboxes ausgewählt hat, würde ich gerne in ein genauso großes 2 Dimensionales Array die Werte einlesen. D.h., eine Matrix mit 0 und 1, wobei 0 kein Hackerl und 1 ein gesetztes Hackerl bedeutet.
> Kann es sein das ich das mit einer CheckBoxMatrix Instanz mache ?? Ich muss die Matrix durchlaufen und an jeder position mit isSelected() == true prüfen und an der jeweiligen Position dann einen 1er in der Matrix setzen.



Wie mach ich das jetzt, denn der ActionListener für die CheckBoxMatrix ist im Hauptfenster.

Und noch etwas komisches ist mir aufgefallen, also nach betätigen des "auswerten"-Buttons erscheint das AuswertungsFenster. In diesem Fenster ist rechts unten ein "schließen"-Button, der aber nicht nach erscheinen des Fenster sichtbar ist, erst nach dem man an der Größe des Button spielt wird er sichtbar. Woran mag das liegen ????


----------



## javimka (31. Dez 2009)

Das Array, sagen wir mal, es sei ein boolean[][] müsstest du in der Klasse CheckBoxMatrix haben. Im Konstruktor von CheckBoxMatrix würdest du dann dieses Array dann instanzieren: [c]array = new boolean[n][m][/c].
Der ActionListener in CheckBoxMatrix wird jedesmal aufgerufen, wenn eine Checkbox selektiert oder deselektiert wird. Du musst einfach die richtige Position in Array auf true oder false setzen.

Wenn dann "auswerten" gedrückt wird, übergibst du der Klasse Verarbeitungsfenster dieses array als Parameter. Das Objekt der Klasse Verarbeitungsfenster kann dann damit anstellen, was es will.

setVisible(true) sollte erst aufgerufen werden, wenn das gesamte Fenster mit allen Komponenten erstellt worden ist. Lösche es aus der Methode init() und setze es im Konstruktor als letzten Befehl. Dann klappt das.

Du kannst gerne noch weiter fragen, aber ich kann dir leider erst nächstes Jahr wieder weiterhelfen 
Guten Rutsch allen


----------



## eren (31. Dez 2009)

Danke sehr.

Dir und auch dem ganzem Team vom Java-Forum eine guten Rutsch und ein schönes neues Jahr

Lg Eren


----------



## eren (1. Jan 2010)

Hallo schon lange nichts mehr voneinander gehört ;-)



> Das Array, sagen wir mal, es sei ein boolean[][] müsstest du in der Klasse CheckBoxMatrix haben. Im Konstruktor von CheckBoxMatrix würdest du dann dieses Array dann instanzieren: array = new boolean[n][m] .
> Der ActionListener in CheckBoxMatrix wird jedesmal aufgerufen, wenn eine Checkbox selektiert oder deselektiert wird. Du musst einfach die richtige Position in Array auf true oder false setzen.
> 
> Wenn dann "auswerten" gedrückt wird, übergibst du der Klasse Verarbeitungsfenster dieses array als Parameter. Das Objekt der Klasse Verarbeitungsfenster kann dann damit anstellen, was es will.



Ich habe das alles befolgt, nur habe ich statt einem boolean[][] ein int[][] genommen, jedoch gibt es da noch ein Problem irgendwie kann man keine int[][] ausgeben oder ?? Ich habe auch versucht das int[][] in ein JLabel einzufügen, aber das mag er nicht. Also gibt es da eine Möglichkeit Matrizen auszugeben ???

Danke
ps: nochmal ein schönes neues Jahr


----------



## javimka (1. Jan 2010)

Du musst mit zwei for-Schleifen durch das Array iterieren und die einzelnen Elemente ausgeben:

```
for (int i=0;i<n;i++) {
  for (int j=0;j<m;j++) {
    System.out.print(array[i][j]+" "+);
  }
  System.out.println(""); // neue Zeile
}
```


----------



## eren (1. Jan 2010)

Dadurch erreiche ich aber nur, dass die Werte im int[][] in der Console ausgegeben wird, aber nicht auf der GUI. Oder hätte ich noch etwas zusätzliches machen müssen ???


----------



## javimka (1. Jan 2010)

Willst du die Matrix denn schön als Teil der GUI ausgeben, so dass der Benutzer die Zahlen sieht, oder willst du das nur vorübergehen einprogrammieren, so dass du es siehst?

Wenn du es einfach haben willst, würde ich dir eine JTextArea empfehlen. Diese Komponente verfügt über die Methode append(String). Damit kannst du analog zur oben gezeigten for-Schleife, die Elemente in die Textarea einfügen. Wenn du noch setEditable(false) aufrufst, kann man der Benutzer den Text nicht selbst verändern.

Wenn du es ganz schön haben willst, könntest du eine LabelMatrix analog zur CheckBoxMatrix erstellen und statt JCheckBoxen einfach JLabels als Matrix Elemente verwenden.


----------



## eren (2. Jan 2010)

Ok eine "kurze" Erläuterung was ich alles gemacht habe:

In der Klasse MatrixBoxMatrix(beim ActionListener) habe ich, wie du gesagt hast, ein 2 Dimensionales Array(int[][]) angelegt und ein Abbild der CheckBoxMatrix abgebildet: (Zeile 43-61)


```
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
 
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
 
public class CheckBoxMatrix extends JPanel {
 
    /**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	
	private MatrixBox[][] boxes; // Alle Checkboxen
    
	private int[][] array;
	private int groesse;
	
	private Graph graph;
	
    public CheckBoxMatrix(int n, int m) {
        super(new FlowLayout(FlowLayout.LEFT));
        JPanel panelContent = new JPanel(new GridLayout(n+1,m+1));
        
        groesse = n;
        
        ActionListener al = new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                // Selektiere auch das Gegenstück
                MatrixBox box = (MatrixBox) e.getSource();
                boxes[box.c][box.r].setSelected(box.isSelected());
                
                array = new int[groesse][groesse];
        		for(int i=0;i<groesse;i++) {
        			for(int j=0;j<groesse;j++) {
        				if(boxes[i][j].isSelected() == true) {
        					array[i][j] = 1;
        				}
        				else {
        					array[i][j] = 0;
        				}
        			}
        		}
        		try {
					graph = new Graph(array.length, array);
				} catch (GraphException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
        		graph.printGraph(array);
        		setArray(array);
            }
        };
        
        panelContent.add(Box.createGlue());
        for (int j=0;j<m;j++) {
            panelContent.add(new JLabel(String.valueOf(j+1)));
        }
        
        boxes = new MatrixBox[n][m];
        for (int i=0;i<n;i++) {
            panelContent.add(new JLabel(String.valueOf(i+1)));
            for (int j=0;j<m;j++) {
                MatrixBox box = new MatrixBox(i, j);
                box.addActionListener(al);
                panelContent.add(box);
                boxes[i][j] = box;
            }
        }
        add(panelContent);
    }
    
    public void setArray(int[][] array) {
    	this.array = array;
    }
    
    public int[][] getArray() {
    	return array;
    }
    
//    public int[][] getArray() {
//    	array = new int[groesse][groesse];
//		for(int i=0;i<groesse;i++) {
//			for(int j=0;j<groesse;j++) {
//				if(boxes[i][j].isSelected() == true) {
//					array[i][j] = 1;
//					array[j][i] = 1;
//				}
//				else {
//					array[i][j] = 0;
//					array[j][i] = 0;
//				}
//			}
//		}
//		
//		return array;
//    }
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame frame = new JFrame("CheckBox Matrix");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new CheckBoxMatrix(10,6),BorderLayout.CENTER);
                frame.add(new JButton("Neue Knotenauswahl"),BorderLayout.SOUTH);
                frame.add(new JButton("Matrix Erstellen"),BorderLayout.EAST);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
    
    private class MatrixBox extends JCheckBox {
        
        /**
		 * 
		 */
		private static final long serialVersionUID = 1L;
		
		private int r,c;
        
        private MatrixBox(int r, int c) {
            this.r = r;
            this.c = c;
            if (r==c) { // Diagonale deaktivieren
                setEnabled(false);
            }
            
            // Minimalabstand zu den Nachbarn definieren
            setBorder(new EmptyBorder(2,2,2,2));
        }
    }
}
```

Wie du sicher bemerken wirst habe ich eine getArray() und eine setArray(int[][] array) Methode gemacht. Mit der setArray(int[][] array) übergebe ich dem Attribut die Werte der Matrix, und mit der getArray() hohle ich mir den Wert der Matrix in der Klasse Hauptfenster:


```
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;



public class Hauptfenster extends JFrame {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private JSlider slider;
	private JButton auswerten;
	private JButton beenden;
	private JPanel panelButton;
	private CheckBoxMatrix boxes;
	
	private int[][] array;
	
	private MyListener ml;
	private MyChangeListener cl;
	
	
	public Hauptfenster() {
		init();
		initComponents();
		addComponents();
		
		setVisible(true);
	}
	
	private void init() {
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setSize(550,550);
		setTitle("Eren Cindi / 6ABINS - Graphentheorie");
		setResizable(true);
		setLayout(new BorderLayout());
	}

	
	private void initComponents() {
		slider = new JSlider(3,15,9);
		slider.setBorder(BorderFactory.createTitledBorder("Größe des Graphen wählen !"));
		slider.setMajorTickSpacing(1);
		slider.setPaintTicks(true);
		slider.setPaintLabels(true);
		slider.setPaintTrack(true);
		
		boxes = new CheckBoxMatrix(slider.getValue(), slider.getValue());
		
		auswerten = new JButton("auswerten");
		beenden = new JButton("beenden");

		panelButton = new JPanel();
		panelButton.setLayout(new FlowLayout(FlowLayout.RIGHT));
				
		ml = new MyListener();
		cl = new MyChangeListener();
	}
	
	private void addComponents() {
		slider.addChangeListener(cl);
		
		auswerten.addActionListener(ml);
		beenden.addActionListener(ml);
		
		panelButton.add(auswerten);
		panelButton.add(beenden);
		
		add(slider, BorderLayout.NORTH);
		add(boxes, BorderLayout.CENTER);
		add(panelButton, BorderLayout.SOUTH);
	}

	
	 class MyListener implements ActionListener {

		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
			if(e.getSource() == auswerten) {
				new VerarbeitungsFenster(array);
			}
			if(e.getSource() == beenden) {
				System.exit(0);
			}
		}
	 }
	 
	 class MyChangeListener implements ChangeListener {

		public void stateChanged(ChangeEvent e) {
			// TODO Auto-generated method stub
			JSlider source = (JSlider) e.getSource();
			if(!source.getValueIsAdjusting()) {
				int value = source.getValue();
				remove(boxes);
				boxes = new CheckBoxMatrix(value, value);
				array = boxes.getArray();
				add(boxes, BorderLayout.CENTER);
				validate();
			}
		}
	 }
}
```

Beim ChangeListener des JSliders hohle ich mir das Array (Ziele 109) in ein Attribut der Klasse Hauptfenster und übergebe dieses Attribut als Parameter für den Konstruktor der Klasse Verarbeitungsfenster (Zeile 92). Aber irgendwie wird da ein Null übergeben und nicht das int[][] was ursprünglich Werte in sich hatte. Denn in der Klasse CheckBoxMatrix habe ich in der Zeile 60 eine Methode die die Werte vom Array auf der Konsole ausgibt. Und die Werte stimmen auch, aber funktioniert nicht.

Bezüglich der Ausgabe vom int[][] auf der GUI:
Ich habe mich ein bisschen falsch ausgedrückt, denn wie schon gesagt soll dieses int[][], was ein Abbild der CheckBoxMatrix ist, nur als Parameter für den Konstruktor einer anderen Klasse(Verarbeitungsfenster) übergeben werden. Das ist aber noch nicht alles, denn dann möchte ich  innerhalb des Verarbeitungsfensters dieses int[][]  wieder als Parameter für einen anderen Konstruktor(Klasse Graph) verwenden, welches mit diesem int[][] Berechnungen durchführt und dann aber wieder int[][] als Retourwert liefert und diese möchte ich auf der GUI ausgeben, wobei der Benutzer aber keine Veränderungen durchnehmen darf. Hier noch der Code vom Verarbeitgunsfenster:


```
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class VerarbeitungsFenster extends JFrame {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	private JButton schließen;
	private JPanel panelschließen;
	
	private int[][] matrix;
	private Graph graph;
	
	private MyListener mlv;

	
	public VerarbeitungsFenster(int[][] array) {
		matrix = array;
		try {
			graph = new Graph(matrix.length, matrix);
		} catch (GraphException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		graph.printGraph();
		init();
		initComponents();
		addComponents();
		
		setVisible(true);
	}
	
	private void init() {
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		setTitle("Auswertungen");
		setSize(550, 550);
		setLayout(new BorderLayout());
	}
	
	private void initComponents() {
		panelschließen = new JPanel();
		panelschließen.setLayout(new FlowLayout(FlowLayout.RIGHT));
		
		schließen = new JButton("schließen");
		
		try {
			graph = new Graph(matrix.length, matrix);
		} catch (GraphException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		mlv = new MyListener();
	}

	private void addComponents() {
		panelschließen.add(schließen);
		
		add(panelschließen, BorderLayout.SOUTH);
		
		schließen.addActionListener(mlv);
	}
	
	class MyListener implements ActionListener {

		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
			if(e.getSource() == schließen) {
				dispose();
			}
		}
		
	}
}
```

Was mache da eigentlich falsch???


----------



## javimka (2. Jan 2010)

Ich kann nicht so ganz nachvollziehen, wieso das array null sein könnte, ausser vielleicht, wenn du sofort auf auswerten klickst, bevor du eine einzige CheckBox aktiviert hast. Die Klasse CheckBoxMatrix erstellt im Konstruktor nämlich nicht sofort ein int[][] array, sondern erst im ActionListener. Das finde ich keine gute Idee. Jedesmal, wenn du eine CheckBox anklickst, wird das array komplett neu erstellt und auch noch ein neues Objekt der Klasse Graph erzeugt.
Du solltest das Array ein einziges Mal erstellen, im Konstruktor, und im actionListener nur jene Einträge ändern, die sich tatsächlich geändert haben. Welche Einträge das sind, weisst du ja (array[box.r][box.c]).
Die Methode setArray solltest du löschen, sonst kann ja jeder irgend ein Array da reinspeichern.
In Zeile 92 könntest du auch schreiben: [c]new VerarbeitungsFenster(boxes.getArray());[/c], dann musst du das Array nicht in Zeile 109 extrahieren.

Was ist bei der Klasse VerarbeitungsFenster das Problem? Wenn das int[][] dann wirklich kommt, sollte das eigentlich klappen.


----------



## eren (2. Jan 2010)

Jetzt aufeinmal klappt es, nur habe ich noch immer das Problem die Matrix als Teil der GUI auszugeben. Kannst du mir nicht ein SampleCode schreiben??


----------



## javimka (2. Jan 2010)

Wieso schreibst nicht du mal eien SampleCode und sagst mir, was nicht funktioniert 

Schau dir einfach mal an, wie du das in CheckBoxMatrix gemacht hast und verwende JLabels statt JCheckBoxen.


----------



## eren (2. Jan 2010)

ok ich werde es einmal probieren


----------



## eren (2. Jan 2010)

Hallo ich glaube, dass das richtig ist:


```
import java.awt.FlowLayout;
import java.awt.GridLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;


public class LabelMatrix extends JPanel {
	
	
		/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private int[][] array;
	private int groesse;

	
	public LabelMatrix(int[][] matrix) {
		super(new FlowLayout(FlowLayout.LEFT));
	    JPanel panelContent = new JPanel(new GridLayout(matrix.length,matrix.length));
	    
	    groesse = matrix.length;
	    array = matrix;
	        
	    for(int i=0;i<groesse;i++) {
	      	for(int j=0;j<groesse;j++) {
	       		if(array[i][j] == 1) {
	       			panelContent.add(new JLabel("1"));
	       		}
	       		else {
	       			panelContent.add(new JLabel("0"));
	       		}
	       	}
	    }
	    add(panelContent);
	}
}
```


----------



## javimka (2. Jan 2010)

ja, das sieht gut aus.
Die if-Abfrage in den Zeilen 28-32 könntest du noch etwas abkürzen:

```
panelContent.add(new JLabel(""+array[i][j]));
```


----------



## eren (2. Jan 2010)

Endlich ist der Zeitpunkt gekommen an dem ich mich bei dir für alles bedanken kann. DANKE
Das Programm ist so gut wie fertig. Nochmals Danke


----------



## javimka (2. Jan 2010)

schon Recht


----------

