# Programmierung von grafischen Oberflächen



## Alibistudent (20. Mrz 2011)

Hallo alle zusammen wir haben eine Aufgabe in Informatik aufbekommen. Ich hab mich versucht erstmal langsam anzutasten und habe versucht die Struktur meines Fensters zu erstellen. Doch ich habe noch Probleme die Elemente richtig zu verwenden. Die Funktionen der Komponenten möchte ich erst danach machen. Was kann ich ändern bzw. besser machen damit meine Aufgabe wie auf dem Bild ist. Ich hab als erstes 3 Label eingefügt doch irgendwie befinden sie sich nicht wo sie sein sollten! Danke im voraus:toll:

Die Aufgabe lautet:
_Im ersten Textfeld ist eine gültige Jahreszahl (laut Gregorianischem Kalender) einzugeben. Als Reaktion auf das Ereignis Button-Klick des Buttons "Anzeige" soll im zweiten Textfeld "ein" oder "kein" angezeigt werden. Dazu wird ein Hörerobjekt benötigt, das der Vorgabe der Schnittstelle ActionListener genügt. Innerhalb der Hörerklasse enthält die Methode actionPerformed (actionEvent e) den Maßnahme-Quellcode als Reaktion auf das Ereignis ButtonKlick. Für die Schaltjahrberechnung soll eine Methode boolean istSchaltjahr(int jahr)verwendet werden, die in der Hörerklasse zu implementieren ist. Mit dem Button "Löschen" sollen die Textfelder gelöscht werden. Dazu ist eine weitere Hörerklasse zu implementieren._


```
import javax.swing.*;

public class Schaltjahr{
	public static void main(String[] args){
	
		JFrame f = new JFrame("Schaltjahr");
		
		JLabel label1 = new JLabel("Das Jahr");
		JLabel label2 = new JLabel("ist");
		JLabel label3 = new JLabel("ein Schaltjahr");
		
		label1.setHorizontalTextPosition(JLabel.LEFT);
		label2.setHorizontalTextPosition(JLabel.CENTER);
		label3.setHorizontalTextPosition(JLabel.RIGHT);
		
		f.add(label1);
		f.add(label2);
		f.add(label3);
		
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		f.setSize(450, 300);
		f.setVisible( true );
		
	}
}
```


----------



## Ironzwerg (21. Mrz 2011)

Erstmal zu dem Problem mit den 3 Labels.
Du fügst jedes Label dem JFrame hinzu.
Das Problem dabei ist, du überschreibst Label1 und Label2 mit Label3, da man einem JFrame nur eine Komponente geben kann.
Daher musst du ein JPanel nehmen und die 3 Label dem Panel hinzufügen.
Dann fügst du das JPanel dem JFrame hinzu.


```
public class Schaltjahr{
    public static void main(String[] args){
    
        JFrame f = new JFrame("Schaltjahr");
        
        JPanel panel = new JPanel();
        
        JLabel label1 = new JLabel("Das Jahr");
        JLabel label2 = new JLabel("ist");
        JLabel label3 = new JLabel("Schaltjahr");
                
        panel.add ( label1 );
        panel.add ( label2 );
        panel.add ( label3 );
        
        f.add ( panel );
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(450, 300);
        f.setVisible( true );
        
    }
}
```


----------



## Ironzwerg (21. Mrz 2011)

So, nun habe ich Zeit etwas genauer zu schreiben.
Um das Bild ungefähr hinzubekommen, würde ich drei Panels erstellen.

Das Hauptpanel, dass dem JFrame hinzugefügt wird
Das Panel für die Textfelder und die Labels
das Panel für die Button.


```
JPanel bigPanel = new JPanel ( new BorderLayout ( 0, 20 ) );
        
JPanel panel = new JPanel ( new FlowLayout ( FlowLayout.CENTER, 20, 50 ) );
        
JPanel btnPanel = new JPanel ( new GridLayout ( 0, 2, 10, 0 ) );

// Erzeugung der einzelnen Elemente

bigPanel.add ( panel, BorderLayout.NORTH );
bigPanel.add ( btnPanel, BorderLayout.CENTER );

f.add ( bigPanel );
```

Durch die entsprechenden LayoutManager werden die einzelnen Elemente angeordnet.
Die Werte sind für die Abstände zwischen den einzelnen Komponenten und den Grenzen der LayoutManager.

Wenn du nun noch den Labels und den Textfeldern die Größe 
	
	
	
	





```
Dimension size = new Dimension ( 95, 50 );
```
 mitgibst, sollte es passen


----------



## Alibistudent (21. Mrz 2011)

Bin jetzt soweit gekommen das ich alle Elemente hinzugefügt hab. Ich habs das Prinzip verstanden. Kannte die Panels noch nicht aber jetzt wird mir langsam alles klar. Ich hab das mit der Dimension nicht verstanden also ich versteh schon was es bewirkt aber ich weiß nicht ob ich die einzelnen Elemente vergrößern muss oder reicht es wenn ich mein Panel vergrößere? Kannst du mir für ein Element zeigen wie man die Dimension ändern muss.

```
import javax.swing.*;
import java.awt.*;

public class Schaltjahr{
	public static void main(String[] args){
	
		//Fenster erstellen
		JFrame f = new JFrame("Schaltjahr");
		
		//Ein JPanel ist ein genereller Container, der selbst keine besonderen grafischen Eigenarten aufweist. Er wird meist benutzt, um bestimmte Komponenten zusammenzufassen.
		JPanel bigPanel = new JPanel(new BorderLayout(0, 20));//Das Hauptpanel, dass dem JFrame hinzugefügt wird
		JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 50));//Das Panel für die Textfelder und die Labels
		JPanel btnPanel = new JPanel(new GridLayout(0, 2, 10, 0));//das Panel für die Button.
		
		//Labels und Textfelder
		JLabel label1 = new JLabel("Das Jahr");
		JLabel label2 = new JLabel("ist");
		JLabel label3 = new JLabel("ein Schaltjahr");
		JTextField eingabefeld = new JTextField(4);
		JTextField ausgabefeld = new JTextField(4);
		panel.add(label1);
		panel.add(eingabefeld);
        panel.add(label2);
		panel.add(ausgabefeld);
        panel.add(label3);
		
		//Buttons
		JButton button1 = new JButton("Anzeige");
		JButton button2 = new JButton("Löschen");
		btnPanel.add(button1);
		btnPanel.add(button2);
		
		//Panels dem Hauptpanel hinzufügen
		bigPanel.add(panel, BorderLayout.NORTH);
		bigPanel.add(btnPanel, BorderLayout.CENTER);
		
		//Hauptpanel dem Fenster hinzufügen
		f.add(bigPanel);
		
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		f.setSize(450, 300);
		f.setVisible(true);
		
	}
}
```


----------



## Ironzwerg (21. Mrz 2011)

Die Elemente vergrößern und die Panels vergrößern sind zwei verschiedene Dinge.
Wenn du die Panels vergrößerst, richtest du die Container an dem Frame aus.
Wenn du die Elemente vergrößerst, richtest du die Elemente am Container aus.

Ich habe das mit der Dimension nur gemacht, damit die Elemente weiter auseinander sind, gemäß des Bildes.
So wie du es jetzt, ist es natürlich auch super, nur nicht so gestreckt.
Ich habe das nur gestreckt, mehr nicht.
Ein andere Auswirkung hat das nicht.

Probiers einfach mal aus, wenn du die vier Elemente in der Breite vergrößerst.


----------



## Alibistudent (22. Mrz 2011)

Hab das mit der Dimension erstmal sein lassen hab das Fenster bisschen verkleinert und die Buttons auch sodass es etwas besser aussieht Ich wollte jetzt weitergehen, weil ich ja den Aufbau schon hab, und die Funktionen des Anzeigebuttons festelegen aber ich komm mit dem ActionListener nicht ganz klar. Hier hab ich schonmal was geschrieben tut aber noch nicht ganz was es tun soll:bahnhof: kannst du mir da weiterhelfen?


```
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Schaltjahr{
	public static void main(String[] args){
	
		//Fenster erstellen
		JFrame f = new JFrame("Schaltjahr");
		
		//Ein JPanel ist ein genereller Container, der selbst keine besonderen grafischen Eigenarten aufweist. Er wird meist benutzt, um bestimmte Komponenten zusammenzufassen.
		JPanel bigPanel = new JPanel(new BorderLayout(0, 20));//Das Hauptpanel, dass dem JFrame hinzugefügt wird
		JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 50));//Das Panel für die Textfelder und die Labels
		JPanel btnPanel = new JPanel(new GridLayout(0, 2, 10, 0));//das Panel für die Button.
		
		//Labels und Textfelder
		JLabel label1 = new JLabel("Das Jahr");
		JLabel label2 = new JLabel("ist");
		JLabel label3 = new JLabel("ein Schaltjahr");
		JTextField eingabefeld = new JTextField(4);
		JTextField ausgabefeld = new JTextField(4);
		panel.add(label1);
		panel.add(eingabefeld);
        panel.add(label2);
		panel.add(ausgabefeld);
        panel.add(label3);
		
		//Buttons
		JButton button1 = new JButton("Anzeige");
		JButton button2 = new JButton("Löschen");
		btnPanel.add(button1);
		btnPanel.add(button2);
		ActionListener al = new ActionListener() {
			public void actionPerformed( ActionEvent e ) {
				int jahr = Integer.parseInt(eingabefeld.getText());
				if((jahr%4)==0){
					ausgabefeld.setText("ein");
				}
				else{
					ausgabefeld.setText("kein");
				}
			}
		};
		button1.addActionListener(al);
		
		//Panels dem Hauptpanel hinzufügen
		bigPanel.add(panel, BorderLayout.NORTH);
		bigPanel.add(btnPanel, BorderLayout.SOUTH);
		
		//Hauptpanel dem Fenster hinzufügen
		f.add(bigPanel);
		
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		f.setSize(300, 200);
		f.setVisible(true);
		
	}
}
```


----------



## Ironzwerg (22. Mrz 2011)

Welche IDE benutzt du?
Bei mir sagt eclipse, dass die Eingabefelder als final deklariert werden müssen, sprich 
	
	
	
	





```
final JTextField eingabefeld = new JTextField(4);
```
Sobald diese als final deklariert sind, funktioniert es bei mir.

Die Schaltjahrberechnung ist etwas kurz, denn du prüfst nur, ob die eingegebene Zahl durch 4 teilbar ist.
Ein Schaltjahr ist alle 4 Jahre, jedoch alle 100 Jahre nicht, dann aber alle 400 Jahre.
Die Abfrage sieht also so aus 
	
	
	
	





```
jahr % 4 == 0  && (jahr % 100 != 0 || jahr % 400 == 0)
```


----------



## Alibistudent (22. Mrz 2011)

toll:toll: mit final funktioniert alles und ich hab jetzt auch den Löschenbutton installiert:applaus: jetzt stellt sich mir nur die Frage warum es durch "final" möglich ist:noe: kannst du mir das vllt erklären?:rtfm:

```
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Schaltjahr{
	public static void main(String[] args){
	
		//Fenster erstellen
		JFrame f = new JFrame("Schaltjahr");
		
		//Ein JPanel ist ein genereller Container, der selbst keine besonderen grafischen Eigenarten aufweist. Er wird meist benutzt, um bestimmte Komponenten zusammenzufassen.
		JPanel bigPanel = new JPanel(new BorderLayout(0, 20));//Das Hauptpanel, dass dem JFrame hinzugefügt wird
		JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 50));//Das Panel für die Textfelder und die Labels
		JPanel btnPanel = new JPanel(new GridLayout(0, 2, 10, 0));//das Panel für die Button.
		
		//Labels und Textfelder
		JLabel label1 = new JLabel("Das Jahr");
		JLabel label2 = new JLabel("ist");
		JLabel label3 = new JLabel("Schaltjahr");
		final JTextField eingabefeld = new JTextField(4);
		final JTextField ausgabefeld = new JTextField(4);
		panel.add(label1);
		panel.add(eingabefeld);
        panel.add(label2);
		panel.add(ausgabefeld);
        panel.add(label3);
		
		//Buttons
		JButton button1 = new JButton("Anzeige");
		JButton button2 = new JButton("Löschen");
		btnPanel.add(button1);
		btnPanel.add(button2);
		ActionListener al1 = new ActionListener() {
			public void actionPerformed( ActionEvent e ) {
				int jahr = Integer.parseInt(eingabefeld.getText());
				if(jahr % 4 == 0 && (jahr % 100 != 0 || jahr % 400 == 0)){
					ausgabefeld.setText("ein");
				}
				else{
					ausgabefeld.setText("kein");
				}
			}
		};
		ActionListener al2 = new ActionListener() {
			public void actionPerformed( ActionEvent e ) {
			
				eingabefeld.setText("");
				ausgabefeld.setText("");
				
			}
		};
		button1.addActionListener(al1);
		button2.addActionListener(al2);
		
		//Panels dem Hauptpanel hinzufügen
		bigPanel.add(panel, BorderLayout.NORTH);
		bigPanel.add(btnPanel, BorderLayout.SOUTH);
		
		//Hauptpanel dem Fenster hinzufügen
		f.add(bigPanel);
		
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		f.setSize(400, 200);
		f.setVisible(true);
		
	}
}
```


----------



## Ironzwerg (23. Mrz 2011)

Das Problem liegt erstmal darin, dass die Textfelder als lokale Variablen deklariert sind, sprich es sind keine Klassenvariablen, denn dann würde das Problem auch nicht auftreten.

Wenn ich was falsches sage, soll mich bitte jemand verbessern, aber ich versuchs mal mit der Erklärung.
Die Fehlermeldung besagt, dass es nicht möglich ist auf eine nicht als final deklarierte Varaible in einer anderen Methode zuzugreifen.

Ich vermute mal, dass es ein Sicherheitsmechanismus ist und die Veränderbarkeit der Variablen sichert.
D.h. die Variable kannst du ja nicht mehr ändern, sobald diese als final deklariert ist.
Kannst du gerne mal versuchen.
Setze einfach mal 
	
	
	
	





```
eingabefeld = new JTextfield ( 6 );
```
Das wird eclipse meckern.

Wenn du die Variable als Klassenvariable deklarierst, kannst du das Textfeld setzen wie du willst, denn wenn du ein Objekt deiner Klasse erzeugen würdest, wäre die Variable dadurch gesichert, denn eine gesetzte Klassenvariable bleibt immer beim Objekt.


```
public class Schaltjahr {
    
    private static JTextField eingabefeld;
    private static JTextField ausgabefeld;
    
    public static void main(String[] args) {
       

        eingabefeld = new JTextField(4);
        ausgabefeld = new JTextField(4);

        ...
    }
}
```

So tritt der Fehler auch nicht auf.
In deinem Programm würde ich aber das mit dem final vorziehen, da du nicht vor hast ein Objekt deiner Klasse zu erzeugen.

Ich hoffe du hast das in etwa verstanden, was ich meine.

@alle
Zerhackt mich nicht, wenn diese Erklärung unverständlich oder sehr kompliziert ist.
Ich habe es versucht


----------

