Начинающий Graphics2D Java: repaint ()

Я пытаюсь изменить цвет своих красных кругов в обработчике действий, а затем в 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();
    }

}
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
777
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Объекты 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
}

Спасибо, это имеет смысл. Сейчас он работает.

Alfie brown 09.12.2018 16:53

(1-) @Alfiebrown, нет, это еще не все изменения, которые нужно сделать. Да, это может решить проблему, но весь код имеет неправильную структуру. Переменные g2 и g3 совершенно не нужны. Прочтите другие ответы и прочтите руководство, чтобы узнать, как правильно рисовать.

camickr 09.12.2018 17:02

Другие вопросы по теме