Я пытаюсь изменить цвет своих красных кругов в обработчике действий, а затем в repaint(), и я не мог понять, почему это не работает.
Импорт сюда
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.JPanel;
Мой класс здесь:
public class CirclePanel extends JPanel implements ActionListener {
static JFrame f;
static JButton run1, run2, reset, quit;
static JPanel btnPanel;
static CirclePanel circlePanel;
static final int NUM = 5;
static Color c;
static Graphics2D g2;
static Graphics2D g3;
public CirclePanel(){
f = new JFrame();
f.setTitle("Dining Philosophers");
f.setDefaultCloseOperation(EXIT_ON_CLOSE);
f.setSize(1000,1000);
f.setLayout(new BorderLayout());
btnPanel = new JPanel();
btnPanel.setPreferredSize(new Dimension(250, 100));
btnPanel.add(run1 = new JButton("Run 1"));
btnPanel.add(run2 = new JButton("Run 2"));
btnPanel.add(reset = new JButton("Reset"));
btnPanel.add(quit = new JButton("Quit"));
run1.setPreferredSize(new Dimension(180, 50));
run2.setPreferredSize(new Dimension(180, 50));
reset.setPreferredSize(new Dimension(180, 50));
quit.setPreferredSize(new Dimension(180, 50));
run1.addActionListener(this);
f.add(btnPanel, BorderLayout.SOUTH);
f.add(this, BorderLayout.CENTER);
f.setVisible(true);
}
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g2 = (Graphics2D) g;
g3 = (Graphics2D) g;
g2.translate(470, 400);
c = Color.red;
for(int i = 0; i < NUM; ++i){
c = Color.red;
g2.setColor( c);
g2.fillOval(150, 0, 100, 100);
g3.setColor(Color.BLACK);
g3.fillOval(90, 0, 30, 30);
g2.rotate(2*Math.PI/ NUM);
}
}
Как вы можете видеть, когда я нажимаю кнопку Run1, она попадает в обработчик действий и выполняет метод перерисовки, но ничего не меняется.
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == run1) {
System.out.println("Entered Action Handler");
g2.setColor(Color.green);
repaint();
}
}
Вот мой основной:
public static void main(String[] args) {
new CirclePanel();
}
}




Объекты Graphics недолговечны, нестабильны, и вы не должны использовать их таким образом. Вместо установки g2 или любой другой Graphics поле создайте поле Color, скажем, с именем Color circleColor = ...;, и измените это. В методе protected void paintComponent(Graphics g) вызовите g.setColor(circleColor);, и это должно сработать.
Удалите эти поля, так как они опасны:
// static Graphics2D g2;
// static Graphics2D g3;
Также ваш код показывает чрезмерное использование модификатора static, и я рискну рекомендовать, чтобы ни одно из ваших полей не было статическим, за исключением константы:
static final int NUM
Метод repaint () в конечном итоге вызовет метод paintComponent () вашей панели. Swing передаст объект Graphics, который будет использоваться в рисовании.
В коде рисования вы всегда жестко указываете цвет как КРАСНЫЙ. Не делай этого.
Вместо этого вам нужно определить переменную в своем классе панели. Допустим, «circleColor» (то есть «circleColor» заменяет вашу переменную «c», потому что имена переменных должны быть более информативными, а не просто одиночным символом).
Затем в вашем коде ActionListener вы делаете:
//g2.setColor(Color.green);
circleColor = Color.green;
Это в методе paintCompnent (), который вы делаете:
//c = Color.red;
g.setColor(circleColor);
Также:
static Graphics2D g2;
static Graphics2D g3;
Ни в одной из этих переменных нет необходимости. Вы всегда используете объект Graphics, который передается методу рисования.
Прочтите раздел руководства по Swing на Картина на заказ для получения дополнительной информации и лучших примеров того, как структурировать ваш код. Например, вам НЕ следует использовать статические переменные.
Что происходит:
g2 в слушателе действий.repaint();, поэтому вызывается paintComponent(Graphics g).paintComponent(Graphics g) вы устанавливаете цвет g2 на c, поэтому вы отменяете изменения, сделанные в слушателе действий.Вот почему круги в итоге не меняют цвет.
Вы должны установить c = Color.RED; в конструкторе, а не в цикле for, тогда вы можете просто изменить значение c в слушателе действий c = Color.GREEN;.
Также вы устанавливаете c = Color.RED; как в цикле for, так и перед ним, что бесполезно.
Обновлено:
Как предлагает @camickr, ваш код также плохо структурирован.
g2 и g3, потому что вы можете рисовать несколько фигур
используя тот же объект Graphics g.g вне метода paintComponent, потому что вы можете просто изменить переменную Color c, как я сказал выше.static. Просто сделайте их private, и если вам нужно получить к ним доступ извне класса, вы должны создать несколько getters и setters.Здесь вы найдете больше о статических переменных и несколько примеров.
Здесь вы найдете больше о геттерах, сеттерах и инкапсуляции.
Пример того, как вы можете изменить свой код:
public class CirclePanel extends JPanel implements ActionListener {
private JFrame f;
private JButton run1, run2, reset, quit;
private JPanel btnPanel;
private int NUM;
private Color c;
public CirclePanel(){
color1 = Color.red;
color2 = Color.black;
NUM = 5;
// Setup JFrame and stuff as you were doing.
}
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.translate(470, 400);
for(int i = 0; i < NUM; i++){
g.setColor(color1);
g.fillOval(150, 0, 100, 100);
g.setColor(color2);
g.fillOval(90, 0, 30, 30);
g.rotate(2*Math.PI/ NUM);
}
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == run1) {
System.out.println("Entered Action Handler");
color1 = Color.green;
repaint();
}
}
// GETTERS and SETTERS if needed
}
(1-) @Alfiebrown, нет, это еще не все изменения, которые нужно сделать. Да, это может решить проблему, но весь код имеет неправильную структуру. Переменные g2 и g3 совершенно не нужны. Прочтите другие ответы и прочтите руководство, чтобы узнать, как правильно рисовать.
Спасибо, это имеет смысл. Сейчас он работает.