Button und aktion?

  • Themenstarter Themenstarter cosinus
  • Beginndatum Beginndatum
C

cosinus

Gast
Hallo,

Habe ein kleines Problem, beim untenstehenden Code wird ein Button und ein Quadrat erzeugt.

Beim Code such ich nach einer Möglichkeit, dass das Quadrat, erst erzeugt wird wenn man den Button klickt. Habe versucht [c]frame.getContentPane().add(BorderLayout.CENTER, Me);[/c] in die [c]public void actionPerformed(ActionEvent event)[/c] Methode zu schreiben aber es wird nicht gezeichnet?

Java:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Button1 implements ActionListener {
 
 JFrame frame;

 public static void main(String[] args) {
  Button1 gui = new Button1();
  gui.los();
 }

 public void los() {
  frame = new JFrame();
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  JButton button = new JButton("klick mich");
  Font bigFont = new Font("roman", Font.BOLD, 20);
  button.setFont(bigFont);
  button.addActionListener(this);

  MeinZeichenPanel Me = new MeinZeichenPanel();
 
  frame.getContentPane().add(BorderLayout.EAST, button);
  frame.getContentPane().add(BorderLayout.CENTER, Me);
  frame.setSize(200,200);
  frame.setVisible(true);
 }
 
 public void actionPerformed(ActionEvent event) {
  
  frame.repaint();
 }
}
class MeinZeichenPanel extends JPanel {
 public void paintComponent(Graphics g) {
  g.setColor(Color.blue);
  g.fillRect(300,300,500,500);
 }
}

Danke

P.
 
nach Änderung des Layouts sind stärkere Befehle als (nur) repaint() nötig,
validate() und/oder revalidate() aufs JFrame und/oder das ContentPane
 
Habe die Api angesehen von den Methoden die du empfehlst die von der Klasse Component sind, aber bin mir nicht sicher wie man das implementieren könnte, also was die Methode genau für eine funktion hat?

Hab den unteren code etwas abgeändert?

Java:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Button1 implements ActionListener {
 
 JFrame frame;
 boolean fill = false;

 public static void main(String[] args) {
  Button1 gui = new Button1();
  gui.los();
 }

 public void los() {
  frame = new JFrame();
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  JButton button = new JButton("klick mich");
  button.setActionCommand("Zeichnen");
  Font bigFont = new Font("roman", Font.BOLD, 10);
  button.setFont(bigFont);
  button.addActionListener(this);

  MeinZeichenPanel Me = new MeinZeichenPanel();
 
  frame.getContentPane().add(BorderLayout.EAST, button);
  
  frame.setSize(200,200);
  frame.setVisible(true);
 }
 
 public void actionPerformed(ActionEvent event) {
  
  if(event.getActionCommand().equals("Zeichnen")) {
   fill = true;
   frame.repaint();
  }
 }
}
class MeinZeichenPanel extends JPanel {
 public void paintComponent(Graphics g) {
  super.paint(g);
  Button1 bt = new Button1();
  if(bt.fill) {
   g.setColor(Color.blue);
   g.fillRect(300,300,500,500);
  }
 }
}

Danke
P.
 
du musst nichts implementieren, nur aufrufen:
frame.validate();
frame.repaint();

in PaintComponent ein neues Button1-Objekt zu erzeugen ist übrigens keine gute Idee, deren boolean-Variable wird den Default-Value haben,
ist ja nicht das Button1-Objekt, welches als ActionListener in der GUI beteiligt ist, sondern ein anderes
 
Habe das mit validate() abgeändert?

Java:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Button2 implements ActionListener {
 
 JFrame frame;
 
 public static void main(String[] args) {
  Button2 gui = new Button2();
  gui.los();
 }

 public void los() {
  frame = new JFrame();
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  JButton button = new JButton("klick mich");
  Font bigFont = new Font("roman", Font.BOLD, 10);
  button.setFont(bigFont);
  button.addActionListener(this);

  MeinZeichenPanel Me = new MeinZeichenPanel();
 
  frame.getContentPane().add(BorderLayout.EAST, button);
  frame.getContentPane().add(BorderLayout.WEST, Me);
  frame.setSize(200,200);
  frame.setVisible(true);
 }
 
 public void actionPerformed(ActionEvent event) {
   frame.validate();
   frame.repaint();
 }
}

class MeinZeichenPanel extends JPanel {
 public void paintComponent(Graphics g) {
   g.setColor(Color.blue);
   g.fillRect(300,300,500,500);
 }
}

Danke
P.
 
Warum nicht einfach das Panel nach erzeugen verstecken und in der actionPerformed Methode wieder hervorholen?

Also in deiner los Methode, nachdem du das Panel erzeugt hast, machst du
Java:
Me.setVisible(false)
und in der actionPerformed Methode, anstelle der validate und repaint Methoden machst du
Java:
Me.setVisible(true)
 
wenn schon sauber, dann doch wohl CardLayout, setVisible() erscheint mir eher suspekt

@cosinus
noch ne Frage offen?
das validate() im Listener erscheint mit unsinnig wenn du die Komponente nun doch schon am Anfang einfügst
 
Wäre eine Idee mit dem setVisible(), unten hab ich den Code?

Habe das mit der hinzugefügten addcontentPane() für die Objektvariablen [c]Me[/c] weggelassen, wie im zweiten Code unten?

CardLayout, ist auch aus dem LayoutManager, wrid das auch der contentPane() hinzugefügt, oder in actionPerformed erzeugt?

Java:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Button2 implements ActionListener {
 
 JFrame frame;
 
 public static void main(String[] args) {
  Button2 gui = new Button2();
  gui.los();
 }

 public void los() {
  frame = new JFrame();
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  JButton button = new JButton("klick mich");
  Font bigFont = new Font("roman", Font.BOLD, 10);
  button.setFont(bigFont);
  button.addActionListener(this);

  MeinZeichenPanel Me = new MeinZeichenPanel();
 
  frame.getContentPane().add(BorderLayout.EAST, button);
  frame.getContentPane().add(BorderLayout.WEST, Me);
  Me.setVisible(false);
  frame.setSize(200,200);
  frame.setVisible(true);
 }
 
 public void actionPerformed(ActionEvent event) {
  MeinZeichenPanel Me = new MeinZeichenPanel(); 
  Me.setVisible(true);
 }
}

class MeinZeichenPanel extends JPanel {
 public void paintComponent(Graphics g) {
   g.setColor(Color.blue);
   g.fillRect(300,300,500,500);
 }
}

mit validate()

Java:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Button2 implements ActionListener {
 
 JFrame frame;
 
 public static void main(String[] args) {
  Button2 gui = new Button2();
  gui.los();
 }

 public void los() {
  frame = new JFrame();
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  JButton button = new JButton("klick mich");
  Font bigFont = new Font("roman", Font.BOLD, 10);
  button.setFont(bigFont);
  button.addActionListener(this);

  
 
  frame.getContentPane().add(BorderLayout.EAST, button);
  
  frame.setSize(200,200);
  frame.setVisible(true);
 }
 
 public void actionPerformed(ActionEvent event) {
  frame.repaint();
  frame.validate();
 }
}

class MeinZeichenPanel extends JPanel {
 public void paintComponent(Graphics g) {
   g.setColor(Color.blue);
   g.fillRect(300,300,500,500);
 }
}

Danke
P.
 
im unteren Code wird nie ein MeinZeichenPanel-Objekt erstellt, muss man dazu wirklich was sagen?
im obigen werden zwei erstellt, auch das kann doch niemals in die richtige Richtung gehen

egal was immer an Lösungsvarianten kommen können, bedenke doch paar ganz logische Konstanten:
- es braucht genau ein Zeichen-Objekt, welches ENTWEDER am Anfang ODER später im Listener erzeugt und auch in die GUI eingefügt wird,
ohne diese Schritte kann doch offensichtlich nichts funktionieren
 
Im oberen code kam an beiden stellen wo ich [c]Me.setVisible()[/c] gesetzt habe eine Fehlermeldung, es können die "Me" objektvariablen nicht gefunden werden, desshalb hab ich die Objekte dort erzeugt?

Der untere Code hab ich nun so?

Java:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Button2 implements ActionListener {
 
 JFrame frame;
 
 public static void main(String[] args) {
  Button2 gui = new Button2();
  gui.los();
 }

 public void los() {
  frame = new JFrame();
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  JButton button = new JButton("klick mich");
  Font bigFont = new Font("roman", Font.BOLD, 10);
  button.setFont(bigFont);
  button.addActionListener(this);

  MeinZeichenPanel Me = new MeinZeichenPanel(); // hier das Objekt vom Anfang für die GUI.
 
  frame.getContentPane().add(BorderLayout.EAST, button);
  frame.getContentPane().add(BorderLayout.WEST, Me); // vielleicht müsste diese Zeile weg?
  frame.setSize(200,200);
  frame.setVisible(true);
 }
 
 public void actionPerformed(ActionEvent event) {
  frame.repaint();
  frame.validate(); // was die genau macht?
 }
}

class MeinZeichenPanel extends JPanel {
 public void paintComponent(Graphics g) {
   g.setColor(Color.blue);
   g.fillRect(300,300,500,500);
 }
}

Danke
P.
 
wie ich am Anfang sagte ist validate() dafür da auf bei GUI-Änderungen für Ordnung zu sorgen,
das bezog sich auf deine eigene Idee,
Beim Code such ich nach einer Möglichkeit, dass das Quadrat, erst erzeugt wird wenn man den Button klickt. Habe versucht [c]frame.getContentPane().add(BorderLayout.CENTER, Me);[/c] in die [c]public void actionPerformed(ActionEvent event)[/c] Methode zu schreiben aber es wird nicht gezeichnet?
also, mache das im Listener, und damit dann gezeichnet wird (NACH dem Einfügen VOR dem repaint()) validate() aufrufen

------

eine lokale Variable aus dem Konstruktor kann generell von niemand anders gesehen werden,
verwende evtl. Instanzattribute, so wie frame
 
egal was immer an Lösungsvarianten kommen können, bedenke doch paar ganz logische Konstanten:
- es braucht genau ein Zeichen-Objekt, welches ENTWEDER am Anfang ODER später im Listener erzeugt und auch in die GUI eingefügt wird,
ohne diese Schritte kann doch offensichtlich nichts funktionieren

Mit Zeichen-Objekt, meinst du die Methode die das Gui zuegs enthält?

Ok habe das so abgeändert?

abgeändert?
Java:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Button2 implements ActionListener {
 
 JFrame frame;
 
 public static void main(String[] args) {
  Button2 gui = new Button2();
  gui.los();
 }

 public void los() {
  frame = new JFrame();
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  JButton button = new JButton("klick mich");
  Font bigFont = new Font("roman", Font.BOLD, 10);
  button.setFont(bigFont);
  button.addActionListener(this);

  MeinZeichenPanel Me = new MeinZeichenPanel();
 
  frame.getContentPane().add(BorderLayout.EAST, button);
  
  frame.setSize(200,200);
  frame.setVisible(true);
 }
 
 public void actionPerformed(ActionEvent event) {
  MeinZeichenPanel Me = new MeinZeichenPanel();
  frame.getContentPane().add(BorderLayout.WEST, Me);
  frame.validate();
  frame.repaint();
 }
}

class MeinZeichenPanel extends JPanel {
 public void paintComponent(Graphics g) {
   g.setColor(Color.blue);
   g.fillRect(300,300,500,500);
 }
}


die setVisible() Variante
Java:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
 
public class Button3 implements ActionListener {
 
 JFrame frame;
 MeinZeichenPanel Me;
 
 public static void main(String[] args) {
  Button3 gui = new Button3();
  gui.los();
 }
 
 public void los() {
  Me = new MeinZeichenPanel();
  frame = new JFrame();
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  JButton button = new JButton("klick mich");
  Font bigFont = new Font("roman", Font.BOLD, 10);
  button.setFont(bigFont);
  button.addActionListener(this);
 
  frame.getContentPane().add(BorderLayout.EAST, button);
  Me.setVisible(false);
  frame.setSize(200,200);
  frame.setVisible(true);
 }
 
  public void actionPerformed(ActionEvent event) {
   Me.setVisible(true);
   frame.getContentPane().add(BorderLayout.WEST, Me); // Listener müsste ja wissen wohin damit?
 }
}
 
class MeinZeichenPanel extends JPanel {
 public void paintComponent(Graphics g) {
   g.setColor(Color.blue);
   g.fillRect(300,300,150,150);
 }
}

Danke
P.
 
vorher hattest du doch an BorderLayout.CENTER gedacht?
damit ginge die validate-Variante, wenn auch noch die Size ordentlich erhöht wird, schließlich ist das Rechteck ziemlich weit recht unten in MeinZeichenPanel,

was in CENTER eingefügt wird, bekommt den ganzen Platz, WEST ist etwas problematischer

bei setVisible(true) ist der gedachte Trick gleich am Anfang einzufügen,
wenn erst später, dann ist erstens wieder validate() nötig und zweitens hätte es überhaupt keine Bedeutung ob am Anfang nicht visible,
da sowieso nicht eingefügt,
aber auch egal, falls dir die erste Variante reicht
 
Hey Slater,

Vielen Dank für die ganze Aufklärung, jetzt funktionierts!

Stimmt der LayoutManager musste auf CENTER gesetzt werden, und die frame size heraufgeschraubt werden oder die Masse von fillRect runter.

wünsche einen schönen Abend
Patrick
 
Also es funktionieren beide Varianten, bei der dritten mit den if-else Anweisungen werde ich wohl noch etwas herumcoden.

Vielen Dank
P.
 
Ach und im Übirgen sollte das Programm im EventDispatch-Thread laufen:
Java:
public static void main(String[] args) {
	EventQueue.invokeLater(new Runnable() {
		public void run() {
			new Button3().los();
		}
	});
}
 

Zurück
Oben