Создал JPanel
на котором есть 3 кнопки, и овал, нарисованный в методе paintComponent()
. По задумке, при нажатии на одну из кнопок, она обводится в рамочку, и выбирается ее цвет, которым потом можно будет залить нарисованный овал. При клике на сам овал происходит заливка:
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import gui.exercises.a.abs.AExercise;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import javax.swing.border.Border;
public class ImageFiller extends AExercise {// AExercise - класс-наследник JPanel
private Color color;
public ImageFiller(JFrame jFrame) {
super(jFrame);
color = Color.WHITE;
init();
}
private void init(){
exerciseTitle = new JLabel("Выбери подходящий цвет и раскрась рисунок.");
exerciseTitle.setHorizontalAlignment(SwingConstants.CENTER);
exerciseTitle.setFont(new Font("Tahoma", Font.PLAIN, 34));
exerciseTitle.setBounds(260, 40, 750, 54);
add(exerciseTitle);
smile.setLocation(20, 550);
JButton color1 = new JButton();
color1.setBounds(1200, 200, 50, 50);
color1.setBackground(Color.BLUE);
Border border = BorderFactory.createMatteBorder(4, 4, 4, 4, Color.BLACK);
add(color1);
JButton color2 = new JButton();
color2.setBounds(1200, 255, 50, 50);
color2.setBackground(Color.YELLOW);
add(color2);
JButton color3 = new JButton();
color3.setBounds(1200, 310, 50, 50);
color3.setBackground(Color.GREEN);
add(color3);
color1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(!color1.getBorder().equals(border)){
color1.setBorder(border);
}
color = color1.getBackground();
}
});
color2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(!color2.getBorder().equals(border)){
color2.setBorder(border);}
color = color2.getBackground();
}
});
color3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(!color3.getBorder().equals(border)){
color3.setBorder(border);
}
color = color3.getBackground();
}
});
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(color);
g2d.fillOval(600, 300, 200, 200);
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
repaint();
}
});
}
}
AExercise
public abstract class AExercise extends JPanel {
protected JFrame jFrame;
protected JLabel exerciseTitle;
protected PlaySound playSound;
protected JLabel smile;
protected static final String correctImage = "/img/gif/858131397.gif";
protected static final String correctSound = "/sound/app.wav";
protected static final String incorrectImage = "/img/gif/no.gif";
protected static final String incorrectSound = "/sound/no.wav";
/**
* Create the panel.
*/
public AExercise(JFrame jFrame) {
this.jFrame = jFrame;
setBounds(0, 0, 1300, 750);
setBackground(new Color(204, 255, 255));
setBorder(new EmptyBorder(5, 5, 5, 5));
playSound = ((ATrain) jFrame).getPlaySound();
setLayout(null);
init();
}
private void init(){
JButton b = new JButton("Назад");
b.setBounds(1150, 640, 100, 40);
add(b);
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
playSound.stopSound();
jFrame.setContentPane(new AExercises(jFrame));
repaint();
revalidate();
}
});
smile = new JLabel();
smile.setIcon(new ImageIcon(ATrain.class.getResource("/img/gif/230646016.gif")));
smile.setBounds(0, 0, smile.getIcon().getIconWidth(), smile.getIcon().getIconHeight());
add(smile);
}
protected void answer(String icon, String sound){
smile.setIcon(new ImageIcon(ATrain.class.getResource(icon)));
if(playSound.getClip()!=null){
playSound.stopSound();
}
playSound.playSound(sound);
}
}
Всё в общем то работает, но почему-то при первом нажатии на любую из кнопок с выбором цвета, заливка происходит автоматически (а не при последующем клике на овал). При последующих кликах всё работает нормально. Долго думал что может быть этому причиной. В результате оказалось, что если закомментировать if в actionPerformed кнопок, то всё работает, но тогда я оказываюсь без рамочки для выбранного цвета. Может кто-то объяснить, почему при первом клике вызывается repaint(), или это в другом дело?
UPD
Немного поменял класс. Отдельно создал объект овала. Проблема осталась..
private Ellipse2D oval = new Ellipse2D.Double(600, 300, 200, 200);
Переместил листнер в init()
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if(oval.contains(e.getX(), e.getY()))
repaint();
}
});
UPD2. РЕШЕНИЕ ГОТОВО
Отредактировал класс, как посоветовал Regent, пофиксил баг с преждевременным заливкой. Добавил ещё несколько фигур которые можно залить (отдельно от остальных).
Рабочий код:
package gui.exercises.a;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Ellipse2D;
import javax.swing.*;
import javax.swing.border.Border;
import gui.exercises.a.abs.AExercise;
public class ImageFiller extends AExercise
{
private Color color;
private Oval oval1 = new Oval(new Ellipse2D.Double(450, 300, 200, 200), Color.WHITE);
private Oval oval2 = new Oval(new Ellipse2D.Double(600, 300, 200, 200), Color.WHITE);
private Oval oval3 = new Oval(new Ellipse2D.Double(750, 300, 200, 200), Color.WHITE);
private Oval [] ovals = {oval1, oval2, oval3};
private JButton [] buttons = new JButton[ovals.length];
private static final Color[] colors = { Color.BLUE, Color.YELLOW, Color.GREEN };
public ImageFiller(JFrame jFrame)
{
super(jFrame);
color = Color.WHITE;
init();
}
private void init()
{
exerciseTitle = new JLabel("Выбери подходящий цвет и раскрась рисунок.");
exerciseTitle.setHorizontalAlignment(SwingConstants.CENTER);
exerciseTitle.setFont(new Font("Tahoma", Font.PLAIN, 34));
exerciseTitle.setBounds(260, 40, 750, 54);
add(exerciseTitle);
Border border = BorderFactory.createMatteBorder(4, 4, 4, 4, Color.BLACK);
ActionListener actionListener = new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
JButton button = (JButton)e.getSource();
if (!button.getBorder().equals(border))
{
button.setBorder(border);
for(JButton jb: buttons){
if(!jb.equals(button))
jb.setBorder(BorderFactory.createLineBorder(Color.black));
}
}
color = button.getBackground();
}
};
for (int i = 0; i < colors.length; i++)
{
buttons[i] = createAndAddButton(i, actionListener);
}
addMouseListener(new MouseAdapter()
{
@Override
public void mouseClicked(MouseEvent e)
{
if (oval1.getElips().contains(e.getX(), e.getY()))
{
oval1.setColor(color);
repaint();
}
if (oval2.getElips().contains(e.getX(), e.getY()))
{
oval2.setColor(color);
repaint();
}
if (oval3.getElips().contains(e.getX(), e.getY()))
{
oval3.setColor(color);
repaint();
}
}
});
}
@Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for(Oval o:ovals){
g2d.setColor(o.getColor());
g2d.fill(o.getElips());
}
}
private JButton createAndAddButton(int index, ActionListener actionListener)
{
JButton button = new JButton();
button.setBounds(1200, 200 + index * 55, 50, 50);
button.setBackground(colors[index]);
add(button);
button.addActionListener(actionListener);
return button;
}
}
Для этого создал отдельную сущность Oval, в которой инкапсулирована фигура, и ее цвет.
class Oval{
private Ellipse2D elips;
private Color color;
public Oval(Ellipse2D elips, Color color) {
super();
this.elips = elips;
this.color = color;
}
public Ellipse2D getElips() {
return elips;
}
public void setElips(Ellipse2D elips) {
this.elips = elips;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((color == null) ? 0 : color.hashCode());
result = prime * result + ((elips == null) ? 0 : elips.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Oval other = (Oval) obj;
if (color == null) {
if (other.color != null)
return false;
} else if (!color.equals(other.color))
return false;
if (elips == null) {
if (other.elips != null)
return false;
} else if (!elips.equals(other.elips))
return false;
return true;
}
@Override
public String toString() {
return "Oval [elips=" + elips + ", color=" + color + "]";
}
}
PS: Ещё раз огромное спасибо Regent, без его активного участия в комментариях у меня ничего бы не получилось!
Оборудование для ресторана: новинки профессиональной кухонной техники
Частный дом престарелых в Киеве: комфорт, забота и профессиональный уход
Хочу передать строку из Activity в Fragment, помогите исправить ошибку
Необходимо получить список событий чужого Google-календаряПытаюсь сделать так:
Получил много ошибок, но считаю что основная эта, подскажите пожалуйста, в чем проблема?