Swing #2: Usuwanie narysowanych kształtów

Spis treści

Zadanie

Napisz aplikację wykorzystującą elementy AWT oraz Swing, która zawiera trzy przyciski:

  • Pierwszy zmienia kolor tła panelu na losowy kolor: zielony, niebieski, lub czerwony.
  • Drugi przycisk zmienia własne tło na dowolny kolor zdefiniowany przez ciebie. (Wykorzystaj metodę setBackground(Color) klasy JButton)
  • Trzeci przycisk zmienia swoją etykietę na „Wciśnięty", po wciśnięciu. (Wykorzystaj metodę setText(String) klasy JButton)

Wszystkie elementy zdefiniuj w oddzielnych klasach (zewnętrznych) i skorzystaj z jednego z zarządców rozkładem.

Rozwiązanie

Postępując zgodnie ze wskazówkami zadanie nie powinno sprawiać problemów. Ponieważ w zadaniu jest powiedziane, że klasy mają być zdefiniowane oddzielnie, musimy przekazać pierwszemu przyciskowi referencję panelu, w którym będzie zmieniane tło.

Przycisk zmieniający tło panelu:

import java.awt.Color;
import java.awt.event.*;
import java.util.Random;

import javax.swing.*;

class FirstButton extends JButton implements ActionListener {

	private JPanel buttonPanel;
	private Color[] colors = { Color.GREEN, Color.BLUE, Color.RED };

	FirstButton(JPanel buttonPanel) {
		super("Pierwszy");
		this.buttonPanel = buttonPanel;
		addActionListener(this);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		int index = new Random().nextInt(colors.length);
		buttonPanel.setBackground(colors[index]);
	}
}

Przycisk zmieniający własne tło:

import java.awt.Color;
import java.awt.event.*;

import javax.swing.*;

class SecondButton extends JButton implements ActionListener {

	SecondButton() {
		super("Drugi");
		addActionListener(this);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		setBackground(Color.YELLOW);
	}
}

Przycisk zmieniający swoją etykietę:

import java.awt.event.*;

import javax.swing.*;

class ThirdButton extends JButton implements ActionListener {

	private boolean wcisniety = false;

	ThirdButton() {
		super("Nie wciśnięty");
		addActionListener(this);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if (wcisniety)
			setText("Wciśnięty");
		else
			setText("Nie wciśnięty");
		wcisniety = !wcisniety;
	}
}

Panel:

import java.awt.*;

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

public class ButtonPanel extends JPanel{

	public static final int HEIGHT = 100;
	public static final int WIDTH = 300;

	private JButton greenButton;
	private JButton blueButton;
	private JButton redButton;

	public ButtonPanel() {
		greenButton = new FirstButton(this);
		blueButton = new SecondButton();
		redButton = new ThirdButton();

		setLayout(new FlowLayout());
		setPreferredSize(new Dimension(WIDTH, HEIGHT));
		add(greenButton);
		add(blueButton);
		add(redButton);
	}
}

Ramka:

import javax.swing.*;

public class ActionFrame extends JFrame {

	public ActionFrame() {
		super("Test akcji");

		JPanel buttonPanel = new ButtonPanel();
		add(buttonPanel);

		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		pack();
		setVisible(true);
	}
}

Klasa testowa:

import java.awt.EventQueue;

class Test {
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			@Override
			public void run() {
				new ActionFrame();
			}
		});
	}
}

Dyskusja i komentarze

Masz pytania do tego wpisu? Może chcesz się podzielić spostrzeżeniami? Zapraszamy dyskusji na naszej grupie na Facebooku.

Poniżej znajdziesz archiwalne wpisy z czasów, gdy strona była jeszcze hobbystycznym blogiem.

jacek

nie mogę tego zrozumieć, nie mogłem zrobić samemu, więc skopiowałem to wszystko, ale i tak mam ze 20 błędów

Arkadiusz

Jakie to błędy? Wklej jej i pamiętaj o znacznikach <code></code>

paulonio

Ja wykorzystałem to co było na lekcji i zmieniłem tylko w tym miejscu :) <code> if(source == kolorButton) setBackground(new Color( (int)(Math.random()*255),(int)(Math.random()*255),(int)(Math.random()*255) )); else if(source == blueButton) setBackground(Color.BLUE); else if(source == offButton) offButton.setText("Wciśnięty"); </code>

Mr_Fisq

Pytanie: Dlaczego linijka: <code> wcisniety = !wcisniety; </code> Występuje dopiero po instrukcji warunkowej, a nie przed? Takie rozwiązanie, iż napis na przycisku jest przeciwny do stanu składowej: <code> wcisniety </code>

KUX

Losowy kolor to metoda wewnątrz konstruktora domyslnego: public void losujKolor() { Color[] colors ={Color.YELLOW,Color.RED,Color.GREEN}; Color colorW = colors[new Random().nextInt(colors.length)]; setBackground(colorW); }

Robert

Nie doczytałem i moje guziki to klasy wewnętrzne. Mój pomysł na przycisk zmieniający losowo tło panelu: class Guzik1 extends JButton implements ActionListener { Guzik1() { super("Przycisk1"); addActionListener(this); } @Override public void actionPerformed(ActionEvent e) { Random losuj = new Random(); int a = losuj.nextInt(14); if (a&gt;=0 &amp;&amp; a=5 &amp;&amp; a=10 &amp;&amp; a&lt;=14) { buttonpanel.setBackground(Color.RED); String b = Integer.toString(a); guzik1.setText(&quot;Wylosowano &quot;+b+&quot; wiec tlo czerwone.&quot;); } } } Najpierw losuje liczbę 0-14, przypisuję jej kolor, następnie rzutuję liczbę na String żeby wyświetlić ją na przycisku (bo setText() wyświetla tylko String). Pozdrawiam

Robert

Dlaczego w klasie ButtonPanel jest: greenButton = new FirstButton(this); chodzi mi konkretnie o 'this'; Pozdrawiam

Damian

"FirstButton(JPanel buttonPanel) { ... }" Oznacza to, że stworzony został konstruktor wymaga referencji do obiektu klasy JPanel, lub po niej dziedziczącej. Ta z kolei jest wymagana, żeby obiekt klasy "FirstButton" wiedział jakiego obiektu dotyczy jego zadanie, czyli zmiana tła panelu...

snt.banzai

należy jednakowoż zauważyć, iż pierwsze kliknięcie na trzeci przycisk nie powoduje zmiany wyświetlanego napisu. Ma to miejsce dopiero za drugim kliknięciem. A przynajmniej tak działa to u mnie.

Piotr

To chyba błąd. W każdym razie po zmianie "false" na "true" w lini "private boolean wcisniety = false;" w klasie "ThirdButton" zmienia się od pierwszego kliknięcia.

Leon

Moje losowanie kolorów wygląda następująco: Random r = new Random(); switch(r.nextInt(3)){ case 0: buttonPanel.setBackground(Color.GREEN); case 1: buttonPanel.setBackground(Color.red); case 2: buttonPanel.setBackground(Color.blue); } Dlaczego zawsze mi wyświetla tylko niebieski kolor?

void

A gdzie masz break? Jak nie ma break to leci po kolejnych "opcjach" i ostatecznie zostaje blue.

Bartol

Mam pytanie odnośnie tego pierwszego przycisku losujacego kolory. Za kazdym razem gry puszcze program i pierwszy przycisk jaki chce wcisną jest wlasnie tym przyciskiem losujacym kolor tla to wywal mi błąd w tej linijce: int index = new Random().nextInt(colors.length); ale jak najpierw klikne w ktorykolwiek inny przycisk i dopiero w ten to wszystko dziala pieknie, ktoświe dlaczego tak sie dzieje ?!