Начинающий Graphics2D Java: repaint () - PullRequest
0 голосов
/ 09 декабря 2018

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

}

Ответы [ 3 ]

0 голосов
/ 09 декабря 2018

Метод 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 по Custom Painting для получения дополнительной информации и лучших примеров того, как структурировать ваш код.Например, вы НЕ должны использовать статические переменные.

0 голосов
/ 09 декабря 2018

Происходит следующее:

  • Вы меняете 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
}
0 голосов
/ 09 декабря 2018

Графические объекты не долговечны, не стабильны, и вы не должны использовать их таким образом.Вместо настройки g2 или любого другого поля Graphics создайте поле Color, скажем, с именем Color circleColor = ...;, и измените this .В методе protected void paintComponent(Graphics g) вызовите g.setColor(circleColor);, и это должно сработать.

Удалите эти поля, поскольку они опасны:

// static Graphics2D g2;
// static Graphics2D g3; 

Кроме того, в вашем коде показано чрезмерное использованиемодификатор static, и я рискну рекомендовать, чтобы ни одно из ваших полей не было статическим, кроме константы:

static final int NUM
...