# Listener erkennt Deselektierung von JCheckbox nicht



## Julyanne (19. Aug 2008)

Hallo!
Ich habe mal versucht, einen kleinen Texteditor mit einer Textarea zu erstellen .. (ich weiß,dass es dafür bessere Möglichkeiten gibt ^^)

Hänge allerdings jetzt schon seit einer Weile an einem Problem fest:
Ich habe für bold und italic eine JCheckbox  eingerichtet und beide mit einem ItemListener verbunden, der so programmiert ist, dass die Schriftform der Selektierung entsprechend geändert wird (da ja auch beides ausgewählt sein kann).
Solange ich die Checkboxen aktiviere, läuft auch alles problemlos. Das Problem liegt im Deaktivieren - es passiert nichts! Ich habe probehalber mal an jede stelle des Quelltextes festgelegt, dass er einen Text in einem Label ausgeben soll, um genau zu überprüfen, was nicht funktioniert - dabei ist mir klargeworden, dass der Listener die Deaktivierung gar nicht wahrnimmt! [also genauer: "Eine Checkbox wurde deaktiviert!" erscheint niemals auf dem Label!]
Mir ist allerdings ziemlich unklar, warum ..
Ich kopier euch mal den Quelltextausschnitt rein (das ganze Programm wäre mit 250 Zeilen ja doch etwas viel ..)
das Abfragen der aktuellen Schrift ist natürlich dazu da, damit auch die aktuelle Schriftart und -größe beibehalten werden.

Vielen Dank schonmal für eure Hilfe!!
Julyanne




```
public class BoxListener implements ItemListener{
		public void itemStateChanged(ItemEvent e) {
			if(e.getStateChange() == ItemEvent.SELECTED){ //soll bei Selektierung einer Checkbox durchlaufen (funktioniert auch tadellos)
				label.setText(label.getText() + "Eine Checkbox wurde aktiviert!");
				if(e.getSource() == bold){
					label.setText(label.getText() + "bold wurde aktiviert!");
					Font s = textfeld.getFont();
					int groesse = s.getSize();
					String schriftart = s.getFontName();
					int stil = s.getStyle();
					if(stil == Font.ITALIC){ //hier wird überprüft, ob der aktuelle Stil italic ist - wenn ja, wird bold+italic aktiviert
						textfeld.setFont(new Font(schriftart, stil+Font.BOLD, groesse));
					}
					else{
						textfeld.setFont(new Font(schriftart, Font.BOLD, groesse));
					}
				}
				if(e.getSource() == italic){
					label.setText(label.getText() + "italic wurde aktiviert!");
					Font sch = textfeld.getFont();
	    			int groesse = sch.getSize();
	    			String schriftart = sch.getFontName();
	    			int stil = sch.getStyle();
	    			if(stil == Font.BOLD) {
	    				textfeld.setFont(new Font(schriftart, stil+Font.ITALIC, groesse));
	    			}
	    			else{
	    				textfeld.setFont(new Font(schriftart, Font.ITALIC, groesse));
	    			}
				}
			
				if(e.getStateChange() == ItemEvent.DESELECTED){ //sollte bei Deselektierung eintreten ...
					label.setText(label.getText() + "Eine Checkbox wurde deaktiviert!");
					if(e.getSource() == bold){
						label.setText(label.getText() + "bold wurde deaktiviert!");
						Font sc = textfeld.getFont();
						int groesse = sc.getSize();
						String schriftart = sc.getFontName();
						if(italic.isSelected() == true){
							label.setText(label.getText() + "italic wurde deaktiviert!");
							textfeld.setFont(new Font(schriftart, Font.ITALIC, groesse));
						}
						else {
							textfeld.setFont(new Font(schriftart, Font.PLAIN, groesse));
						}
					}
				}
			}
		}		
	}
```


----------



## SlaterB (19. Aug 2008)

probier das hier mal

```
class BoxListener
    implements ItemListener
{
    public void itemStateChanged(ItemEvent e)
    {
        if (e.getStateChange() == ItemEvent.SELECTED)
        { // soll bei Selektierung einer Checkbox durchlaufen (funktioniert auch
            // tadellos)
            System.out.println("bin drin");

            if (e.getStateChange() == ItemEvent.DESELECTED)
            { // sollte bei Deselektierung eintreten ...
                System.out.println("ganz schön unsinnig an dieser Stelle");
            }
        }
        else
        {
            System.out.println("folgendes Ereignis wurde ignoriert: " + e.getStateChange());
        }
    }
}
```


----------



## Julyanne (19. Aug 2008)

Danke für die schnelle Hilfe:
beim aktivieren kommt "bin drin", auch zweimal, wenn ich beide boxen aktiviere.
Aber sobald ich irgendetwas deaktiviere kommt "ereignis wurde ignoriert: 2" ..
kann man mit der 2 da was anfangen? ^^


----------



## SlaterB (19. Aug 2008)

wenn du noch ItemEvent.DESELECTED per System.out.println ausgeben würdest,
dann könntest du diese Zahlen vergleichen,
aber eigentlich sollte das auch eher ein Hinweis auf den Quelltext an sich sein:

die Abfrage 
if (e.getStateChange() == ItemEvent.DESELECTED) 
            { // sollte bei Deselektierung eintreten ... 
            } 

steht doch INNERHALB der Abfrage 
 if (e.getStateChange() == ItemEvent.SELECTED) 
        { // soll bei Selektierung einer Checkbox durchlaufen 
 }

erkennst du nun das Dilemma?


```
i = 5;
if (i < 4) {
  // wird nicht durchlaufen

   if (i >= 4) {
     // das dann auch nicht
   }
}
```


----------



## Julyanne (19. Aug 2008)

Aaaah danke! Da is das etwas verrutscht ^^
Leider ist das Problem damit nicht vollständig gelöst:
Zwar wird jetzt im Label ausgegeben, dass eine Checkbox (und auch welche) deaktiviert wurde.
Die Änderung tritt allerdings weiterhin nicht ein ...
ALLERDINGS: Sie tritt ein, sobald ich die Schriftart (mittels einer JComboBox) verändere!?
und zwar, egal, welche Änderung.
Also zusammengefasst:
Mit dem aktivieren läuft alles genauso, wie es soll.
Das Deaktivieren funktioniert jetzt auch - bis auf den Unterschied, dass die Änderung erst sichtbar ist, wenn die Schriftart verändert wird ...

Wie kann das passieren??


----------



## SlaterB (19. Aug 2008)

> bis auf den Unterschied, dass die Änderung erst sichtbar ist, wenn die Schriftart verändert wird ... 

was ist denn 'die Änderung'? da werden doch hauptsächlich nur neue Fonts gesetzt?


----------



## Julyanne (19. Aug 2008)

Ja richtig, die Schriftart wird neu definiert .. sonst soll auch nix weiter passieren.


----------



## SlaterB (19. Aug 2008)

du sagst, dass nur die Schriftartenänderung geht, alles anderen nicht
+
es soll nur Schriftartenänderung passieren,

das passt nicht zusammen, oder funktioniert italic & Co nicht?
in jedem Fall ist es wohl Zeit für ein komplettes Beispielprogramm zum Ausprobieren


----------



## Julyanne (19. Aug 2008)

ah sry, hab mich da vertippt:
der schriftSTIL also plain/bold/italic wird nicht geändert, erst, wenn eine andere schriftart mittels einer jcombobox eingestellt wird.
zum verständnis am besten mal n screenshot vom programm


----------



## SlaterB (19. Aug 2008)

falls du noch eine Frage hast kann ich zumindest ohne Code nix sagen


----------



## Julyanne (19. Aug 2008)

Na, das Problem besteht weiterhin, dass beim Deaktivieren einer Box die Änderung des Schriftstils erst nach Änderung der Schriftart erfolgt ..
soll ich den kompletten Code mal reinstellen?


----------



## Julyanne (20. Aug 2008)

```
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;

import javax.swing.*;
import javax.swing.undo.UndoManager;

public class Editor extends JFrame {
	//Variablendeklarierung
	private Container c; //Frame-Container
	private JMenuBar menuBar; //Menüleiste
	private JMenu datei, bearbeiten; //Menüs
	private JMenuItem[] menuItem; //Menüeinträge
	private JToolBar toolBar;  //Toolbar
	private JTextArea textfeld; //Eingabefeld
	private JScrollPane scrollPane; //Laufleiste
	private MenuListener ml;
	private ComboBoxListener cl;
	private UndoableListener ul;
	private BoxListener bl;
	private UndoManager undomanager;
	private JComboBox combo;
	private JCheckBox bold, italic;
	private JLabel label;
	
            //Konstruktor
	public Editor() {
		super("NEditor");
		c = getContentPane();
		textfeld = new JTextArea();
		Font schrift = new Font("SansSerif",Font.PLAIN, 16);
		textfeld.setFont(schrift);
		textfeld.setLineWrap(true);
		textfeld.setWrapStyleWord(true);
		scrollPane = new JScrollPane(textfeld);
		c.add(scrollPane);
		ml = new MenuListener();
		ul = new UndoableListener();
		erzeugeMenu();
		setJMenuBar(menuBar);
		undomanager = new UndoManager();
		textfeld.getDocument().addUndoableEditListener( undomanager );
		cl = new ComboBoxListener();
		bl = new BoxListener();
		erzeugeToolBar();
		c.add(toolBar, BorderLayout.NORTH);	
		label = new JLabel();
		c.add(label, BorderLayout.SOUTH);
		
	}
	//erzeugt Menu
	public void erzeugeMenu(){
		menuBar = new JMenuBar();
		menuItem = new JMenuItem[20]; 
		datei = new JMenu("Datei");
		datei.setMnemonic(KeyEvent.VK_D);
		bearbeiten = new JMenu("Bearbeiten");
		bearbeiten.setMnemonic(KeyEvent.VK_B);
		macheItems();
		menuBar.add(datei);			
		menuBar.add(bearbeiten);
	}
		

	public void macheItems(){
		//erstes MenuItem Datei
		menuItem[0] = new JMenuItem("Neu");
		menuItem[0].setMnemonic(KeyEvent.VK_N);
		menuItem[0].addActionListener(ml);
		menuItem[0].setActionCommand("neu");
		
		//zweites MenuItem Datei
		menuItem[1] = new JMenuItem("Öffnen");
		menuItem[1].setMnemonic(KeyEvent.VK_O);
		menuItem[1].addActionListener(ml);
		menuItem[1].setActionCommand("open");
		
		//drittes MenuItem Datei
		menuItem[2] = new JMenuItem("Speichern");
		menuItem[2].setMnemonic(KeyEvent.VK_S);
		menuItem[2].addActionListener(ml);
		menuItem[2].setActionCommand("save");
		
		//viertes MenuItem Datei
		menuItem[3] = new JMenuItem("Beenden");
		menuItem[3].setMnemonic(KeyEvent.VK_B);
		menuItem[3].addActionListener(ml);
		menuItem[3].setActionCommand("exit");
		
		//füge Items in Datei ein
		for(int i=0; i <4; i++){
			datei.add(menuItem[i]);
		}
		
		//erstes MenuItem Bearbeiten
		menuItem[4] = new JMenuItem("Rückgängig");
		menuItem[4].setMnemonic(KeyEvent.VK_R);
		menuItem[4].addActionListener(ul);
		menuItem[4].setActionCommand("undo");
		
		//zweites MenuItem Bearbeiten
		menuItem[5] = new JMenuItem("Ausschneiden");
		menuItem[5].setMnemonic(KeyEvent.VK_A);
		menuItem[5].addActionListener(ml);
		menuItem[5].setActionCommand("cut");
		
		//drittes MenuItem Bearbeiten
		menuItem[6] = new JMenuItem("Kopieren");
		menuItem[6].setMnemonic(KeyEvent.VK_K);
		menuItem[6].addActionListener(ml);
		menuItem[6].setActionCommand("copy");
		
		//viertes MenuItem Bearbeiten
		menuItem[7] = new JMenuItem("Einfügen");
		menuItem[7].setMnemonic(KeyEvent.VK_E);
		menuItem[7].addActionListener(ml);
		menuItem[7].setActionCommand("paste");
		
		//füge Items in Bearbeiten ein
		for(int i=4; i<8; i++){
			bearbeiten.add(menuItem[i]);
		}
		
	}
	//erzeugen der Toolbar für Veränderung von Schriftart und -stil
	public void erzeugeToolBar(){
		toolBar = new JToolBar("Format");
		String[] schriften = {"", "Mit Serifen", "Ohne Serifen", "Monospaced"};
		combo = new JComboBox(schriften);
		combo.addActionListener(cl);
		toolBar.add(combo);
		bold = new JCheckBox("Bold");
		bold.addItemListener(bl);
		italic = new JCheckBox("Italian");
		italic.addItemListener(bl);
		toolBar.add(bold);
		toolBar.add(italic);		
	}
	
	public class MenuListener implements ActionListener{
		public void actionPerformed(ActionEvent e) {
			if (e.getActionCommand() == "neu"){
				textfeld.setText("");
			}
			if (e.getActionCommand() == "open") {
				//hier wird eine Datei geöffnet!
			}
			if (e.getActionCommand() == "save") {
				//hier wird eine Datei gespeichert!
			}
			if (e.getActionCommand() == "exit"){
				System.exit(1);
			}
			if (e.getActionCommand() == "cut"){
				textfeld.cut();
			}
			if (e.getActionCommand() == "copy"){
				textfeld.copy();
			}
			if (e.getActionCommand() == "paste"){
				textfeld.paste();
			}
		}
	}
	
	//undo-Listener fürs rückgängig machen
	public class UndoableListener implements ActionListener{
		public void actionPerformed( ActionEvent e )
        {
            undomanager.undo();

          textfeld.requestFocus();
        }
	}
	
            //Listener für ComboBox --> Schriftart
	public class ComboBoxListener implements ActionListener{
		public void actionPerformed(ActionEvent e){
			int index = combo.getSelectedIndex();
			if (index == 1){
				Font schriftaktuell = textfeld.getFont();
				int stil = schriftaktuell.getStyle();
				int groesse = schriftaktuell.getSize();
				textfeld.setFont(new Font("Serif", stil, groesse));
			}
			if (index == 2){
				Font schriftaktuell = textfeld.getFont();
				int stil = schriftaktuell.getStyle();
				int groesse = schriftaktuell.getSize();
				textfeld.setFont(new Font("SansSerif", stil, groesse));
			}
			if (index == 3){
				Font schriftaktuell = textfeld.getFont();
				int stil = schriftaktuell.getStyle();
				int groesse = schriftaktuell.getSize();
				textfeld.setFont(new Font("Monospaced", stil, groesse));
			}
		}
	}
	
	//Checkboxlistener - Problem besteht weiterhin ..
	public class BoxListener implements ItemListener{
		public void itemStateChanged(ItemEvent e) {
			if(e.getStateChange() == ItemEvent.SELECTED){
				label.setText(label.getText() + "Eine Checkbox wurde aktiviert!");
				if(e.getSource() == bold){ 
					label.setText(label.getText() + "bold wurde aktiviert!");
					Font s = textfeld.getFont();
					int groesse = s.getSize();
					String schriftart = s.getFontName();
					int stil = s.getStyle();
					if(stil == Font.ITALIC){
						textfeld.setFont(new Font(schriftart, stil+Font.BOLD, groesse));
					}
					else{
						textfeld.setFont(new Font(schriftart, Font.BOLD, groesse));
					}
				}
				if(e.getSource() == italic){
					label.setText(label.getText() + "italic wurde aktiviert!");
					Font sch = textfeld.getFont();
	    			int groesse = sch.getSize();
	    			String schriftart = sch.getFontName();
	    			int stil = sch.getStyle();
	    			if(stil == Font.BOLD) {
	    				textfeld.setFont(new Font(schriftart, stil+Font.ITALIC, groesse));
	    			}
	    			else{
	    				textfeld.setFont(new Font(schriftart, Font.ITALIC, groesse));
	    			}
				}
			}
			
			if(e.getStateChange() == ItemEvent.DESELECTED){
				label.setText(label.getText() + "Eine Checkbox wurde deaktiviert!");
				if(e.getSource() == bold){
					label.setText(label.getText() + "bold wurde deaktiviert!");
					Font sc = textfeld.getFont();
					int groesse = sc.getSize();
					String schriftart = sc.getFontName();
					if(italic.isSelected() == true){
						label.setText(label.getText() + "italic wurde deaktiviert!");							textfeld.setFont(new Font(schriftart, Font.ITALIC, groesse));
					}	
					else {
						textfeld.setFont(new Font(schriftart, Font.PLAIN, groesse));
					}
				}
			}
		}		
	}
	//kleine main zum Ausprobieren ..
	public static void main(String[] args){
		Editor editor = new Editor();
		editor.setSize(500,300);
		editor.setVisible(true);
		editor.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}

}
```


----------



## SlaterB (20. Aug 2008)

eine harte Nuss, aber ich habs nun:

du übernimmst die vorherige Schriftart, die ist aber nicht "MonoSpaced" oder so sondern z.B.
"java.awt.Font[family=Monospaced,name=MonoSpaced,style=plain,size=12]"

kannst den String schriftart mit System.out.println ausgeben, um dich zu überzeugen oder in dein recht volles label schreiben,

der in diesem Schriftnamen angegebene Style scheint Vorrang zu haben,
seltsames System..

also als Lösung:
entweder den einfacht Fontname extrahieren (der Text hinter "family=")
oder den richtigen Fontname irgendwo extern merken, dürfte ja z.B. die ganze Zeit immer aus der ComboBox verfügbar sein,
bis auf dem Anfang des Programmes, wenn nichts selektiert ist,

sicherer wäre also das Extrahieren, könntest auch anfangs die ComboBox auf diesen Wert setzen


----------



## Julyanne (20. Aug 2008)

Oh mein Gott, danke!!! ich habs endlich ^^
wie soll man auch auf sowas kommen ...
danke danke danke ^^

 :lol:  :lol:  :lol:  :lol:  :lol:  :lol:  :lol:


----------

