# JButton ausblenden



## buzzlightyear (19. Sep 2012)

Hi,

habe ein Probem mit meiner GUI. Auf meinem Panel liegt ein JButton (Start). Sobald dieser gedrückt wird soll der Start-Button verschwinden und eine Funktion gestartet werden. Jetzt ist das Problem das wenn ich auf den Button klicke, die Funktion gestartet wird aber der Button erst verschwindet sobald die Funktion abgelaufen ist. Den Button lass ich bisher mit


```
.setVisible(false);
```

ausblende.

Muss ich da irgendwie schon mit einem Timer o.a. arbeiten? Oder kann ich das Problem auch anders lösen?


----------



## jgh (19. Sep 2012)

Hast du in der actionPerf. -Methode diese Reihenfolge auch, also zuerst button..setVisible(false) und dann die andere Aktion?
Falls ja, evtl. noch ein validate() auf das Panel...


----------



## buzzlightyear (19. Sep 2012)

Also der Abschnitt sieht so aus (Ich poste den einmal rein da es eh nicht so viel ist)


```
else if (e.getSource().equals(mw.getStart())) {
// mw = MainWin (meine Fensterklasse)
// getStart returned einfach nur JButton (den Start Button)

			mw.getStart().setVisible(false);
			// Hier hab ich auch mw.validate() und mw.repaint getestet, leider ohne erfolg
                        // mw.getStart().validate() bzw. repaint() hat auch so keinen erfolg.


			iv.playNewIntervall();
			
		}
```

EDIT: Habs auch mit mw.getUp().validate() bzw. repaint() versucht hat aber leider auch nciht geklappt.
getUp liefert mir mein JPanel zurück auf dem der Button liegt.


----------



## jgh (19. Sep 2012)

keine Ahnung warum...aber folgendes Testprogramm macht genau das, da hilft es imho nur dein Problemm auf ein KSKB runterzubrechen und dann kann ich zumindest versuchen dir zu helfen...


```
public static void main(String[] args) {
		final JFrame f1 = new JFrame();
		f1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		f1.setSize(500, 500);
		final JButton b = new JButton("Test");
		b.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				b.setVisible(false);
//				f1.validate();
				try {
					Desktop.getDesktop().mail();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
		});
		f1.add(b);
		f1.setLocationRelativeTo(null);
		f1.setVisible(true);
	}
```


----------



## buzzlightyear (19. Sep 2012)

Hab mal alles raus geholt was unwichtig ist für das Beispiel (heisst es gibt jetzt eigentlich nur noch den frame und den Button. Hab die Klassen Struktur aber mal so abgebildet wie ich es imer mache. Hoffe das ist minimalistisch genug:

Main.java:


```
public class Main {
	public static void main (String[] args) {
		MainWinCon mwc = new MainWinCon();
	}
}

[/Java]

MainWindow.java
[code=Java]
import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class MainWindow extends JFrame {

	private MainWinCon mwc;
	
	// Inhalte des Fensters etc
	// Buttons
	JButton bStart;
	
	// Panels
	JPanel pUp, pDown;
	
	public MainWindow(MainWinCon mwc) {
		this.mwc = mwc;
		createWindow();
	}
	
	public void createWindow () {
		setSize(700, 400);
		setLayout(null);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		pUp = new JPanel();
		pUp.setLayout(null);
		pUp.setBackground(Color.WHITE);
		
		pDown = new JPanel(new GridLayout(2,4));
		pDown.setBackground(Color.WHITE);
		
		
		pUp.setBounds(0, 0, 700, 293);
        pDown.setBounds(0, 294, 700, 70);

        this.add(pUp);
        this.add(pDown);

        bStart = new JButton("Start");
        bStart.setBounds(290, 260, 120, 25);
        bStart.setVisible(true);
        bStart.addActionListener(mwc);
        pUp.add(bStart);
		
		setVisible(true);
		
	}
	
	public JPanel getUp() {
		return this.pUp;
	}
	
	public JButton getStart() {
		return this.bStart;
	}
	
}
```

MainWinCon.java

```
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Receiver;
import javax.sound.midi.ShortMessage;
import javax.sound.midi.Synthesizer;

public class MainWinCon implements ActionListener {
	
	
	private MainWindow mw;
	private Synthesizer synth;
	private Receiver rcvr;
	
	
	public MainWinCon() {
		mw = new MainWindow(this);
		
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		
		if (e.getSource().equals(mw.getStart())) {
			
			// Button Ausblenden
			mw.getStart().setVisible(false);
			
			mw.invalidate();
			
			// Ton spielen (bzw normalerweise Funktionsaufruf um ein Intervall zu spielen
			try {
				synth = MidiSystem.getSynthesizer();
			} catch (MidiUnavailableException e2) {
				e2.printStackTrace();
			}
			
			try {
				synth.open();
			} catch (MidiUnavailableException e2) {
				e2.printStackTrace();
			}
			
			try {
				rcvr = synth.getReceiver();
			} catch (MidiUnavailableException e1) {
				e1.printStackTrace();
			}
			ShortMessage msg = new ShortMessage();
			try {
				msg.setMessage(ShortMessage.NOTE_ON, 0, 40, 100);
			} catch (InvalidMidiDataException ex) {
				ex.printStackTrace();
			}
			rcvr.send(msg, -1);
			
			try {
				Thread.sleep(1500);
			} catch (InterruptedException ex) {
				ex.printStackTrace();
			}
			
			try {
				msg.setMessage(ShortMessage.NOTE_OFF, 0, 40, 100);
			} catch (InvalidMidiDataException ex) {
				ex.printStackTrace();
			}
			
			rcvr.send(msg, -1);
			synth.close();
			
		}
		else {
			System.out.println("Ein Fehler ist aufgetreten");
		}
	}
}
```

Das ist jetzt so das kleinste was möglich ist um es mit der Funktion zu testen. Der Button bleibt solange auf dem Panel bis der Ton zuende gespielt wurde und verschwindet erst dann. Obwohl ich die Reihenfolge beachtet habe (erst Button ausblenden, dann den Ton spielen) und selbst mit .validate() funktioniert es nicht. Wenn ich den Ton nicht abspielen lasse, verschwindet auch direkt der Button. Aber der Ton MUSS dort abgespielt werden da es ja schließlich der Start Button ist. Weiss echt nicht weiter.


----------



## SlaterB (19. Sep 2012)

wieso sparst du dir die jetzigen Informationen vorher? 
falls du sie erst durch das Verkürzen des Programms gewonnen hast, dann war das ja erfolgreich,

mit diesen Informationen
> Wenn ich den Ton nicht abspielen lasse, verschwindet auch direkt der Button. 
usw. ist der Code fast nicht mehr erforderlich,

es gilt: die GUI, der AWT Event-Thread, kann erst dann wieder handeln, z.B. neuzeichnen, wenn der Listener zu Ende bearbeitet ist,
langläufige Aktionen gehörten in einen nebenläufigen Thread, dann dürfte es gehen,

Thread bekannt oder selber herauszufinden? ich spare mir zunächst weiteres


----------



## jgh (19. Sep 2012)

ok das wusste ich nicht, dass der Listener erst abgearbeitet wird, hier mal qnd ein Thread reingewurschtelt UND unter KSKB versteht man das folgende Prog, fürs nächste Mal 


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

import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Receiver;
import javax.sound.midi.ShortMessage;
import javax.sound.midi.Synthesizer;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class KlassenName {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		MainWinCon mwc = new MainWinCon();
	}
}

class MainWindow extends JFrame {

	private MainWinCon mwc;

	// Inhalte des Fensters etc
	// Buttons
	JButton bStart;

	// Panels
	JPanel pUp, pDown;

	public MainWindow(MainWinCon mwc) {
		this.mwc = mwc;
		createWindow();
	}

	public void createWindow() {
		setSize(700, 400);
		setLayout(null);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		pUp = new JPanel();
		pUp.setLayout(null);
		pUp.setBackground(Color.WHITE);

		pDown = new JPanel(new GridLayout(2, 4));
		pDown.setBackground(Color.WHITE);

		pUp.setBounds(0, 0, 700, 293);
		pDown.setBounds(0, 294, 700, 70);

		this.add(pUp);
		this.add(pDown);

		bStart = new JButton("Start");
		bStart.setBounds(290, 260, 120, 25);
		bStart.setVisible(true);
		bStart.addActionListener(mwc);
		pUp.add(bStart);

		setVisible(true);

	}

	public JPanel getUp() {
		return this.pUp;
	}

	public JButton getStart() {
		return this.bStart;
	}

}

class MainWinCon implements ActionListener {

	private MainWindow mw;
	private Synthesizer synth;
	private Receiver rcvr;

	public MainWinCon() {
		mw = new MainWindow(this);

	}

	@Override
	public void actionPerformed(ActionEvent e) {

		if (e.getSource().equals(mw.getStart())) {

			// Button Ausblenden
			mw.getStart().setVisible(false);
			

			// Ton spielen (bzw normalerweise Funktionsaufruf um ein Intervall
			// zu spielen
			new Thread(new Runnable() {

				@Override
				public void run() {
					try {
						synth = MidiSystem.getSynthesizer();
					} catch (MidiUnavailableException e2) {
						e2.printStackTrace();
					}

					try {
						synth.open();
					} catch (MidiUnavailableException e2) {
						e2.printStackTrace();
					}

					try {
						rcvr = synth.getReceiver();
					} catch (MidiUnavailableException e1) {
						e1.printStackTrace();
					}
					ShortMessage msg = new ShortMessage();
					try {
						msg.setMessage(ShortMessage.NOTE_ON, 0, 40, 100);
					} catch (InvalidMidiDataException ex) {
						ex.printStackTrace();
					}
					rcvr.send(msg, -1);

					try {
						Thread.sleep(1500);
					} catch (InterruptedException ex) {
						ex.printStackTrace();
					}

					try {
						msg.setMessage(ShortMessage.NOTE_OFF, 0, 40, 100);
					} catch (InvalidMidiDataException ex) {
						ex.printStackTrace();
					}

					rcvr.send(msg, -1);
					synth.close();

				}
			}).start();
		} else {
			System.out.println("Ein Fehler ist aufgetreten");
		}
	}
}
```


----------



## buzzlightyear (19. Sep 2012)

Danke funktioniert!

Werde jetzt nur noch versuchen den Thread direkt in die Intervall-Klasse zu implementieren. Damit man sich im späterem Verlauf keine Gedanken mehr darüber machen muss wenn man zB die Methode playIntervall aufrufen will.



> es gilt: die GUI, der AWT Event-Thread, kann erst dann wieder handeln, z.B. neuzeichnen, wenn der Listener zu Ende bearbeitet ist..



Das wusste ich leider nicht. Werds mir aber gut merken für die Zukunft ^^


----------



## buzzlightyear (19. Sep 2012)

SlaterB hat gesagt.:


> mit diesen Informationen
> > Wenn ich den Ton nicht abspielen lasse, verschwindet auch direkt der Button.
> usw. ist der Code fast nicht mehr erforderlich,



Hatte ich aber doch im ersten Post erwähnt:



> Jetzt ist das Problem das wenn ich auf den Button klicke, die Funktion gestartet wird aber der Button *erst *verschwindet sobald die Funktion abgelaufen ist. Den Button lass ich bisher mit


----------



## SlaterB (19. Sep 2012)

buzzlightyear hat gesagt.:


> Hatte ich aber doch im ersten Post erwähnt:



gut, das wirft dann ein gewisses Licht auf jgh, nicht erkannt 
und eins auf mich, nicht nachgelesen


----------



## jgh (19. Sep 2012)

ich habe doch geschrieben, dass es mir nicht bewusst war...


----------



## SlaterB (19. Sep 2012)

und ich dass ich nicht alles nachlese 

super, wieder letztes Wort (edit: Mist, nicht mehr)


----------



## buzzlightyear (19. Sep 2012)

Ich muss unbedingt aufmerksamer Lesen 

EDIT: :lol: Das mit dem letzten Wort erst nach meinem Post gelesen xD Naja vllt. fällt dir ja noch was ein was du schreiben kannst xD

Ansonsten nochmal Danke an alle die an der Lösung beteiligt waren :toll:


----------

