Пояснения по коду java graphics
учу java, в частности застрял на примере по книге Сиерра К. Изучаем Java 2012г. стр 401.
В примере кода при нажатии на кнопку должен сгенирироваться новый градиентный цвет круга, за это отвечает
public void actionPerformed(ActionEvent event) {
frame.repaint();
}
Но у меня вылетает исключение Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
Отсюда 2а вопроса...
Почему? ведь казалось бы я все сделал по книге...
Кто может дать пояснения по следующему... в кгине сказанно, что
frame.repaint(); - Когда пользователь нажимает кнопку вызываем для фрейма метод repaint(). Это значит, что метод paintComponent() вызывается для каждого виджета во фрейме!
Каким образом вызывается метод public void paintComponent(Graphics g)? Ведь я же не вызываю его явно drawPanel.paintComponent(Graphics g); кто то может объяснить?
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class SimpleGui3C implements ActionListener {
JButton frame;
public static void main(String[] args) {
SimpleGui3C gui = new SimpleGui3C();
gui.go();
}
public void go() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton button = new JButton("Сменить цвет круга");
button.addActionListener((ActionListener) this);
MyDrawPanel drawPanel = new MyDrawPanel();
frame.getContentPane().add(BorderLayout.SOUTH, button);
frame.getContentPane().add(BorderLayout.CENTER, drawPanel);
frame.setSize(300,300);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent event) {
//try {
frame.repaint();
//} catch (Exception e) {
// System.out.println(e.getMessage());
// System.out.println(e.getStackTrace().toString());
//}
}
}
class MyDrawPanel extends JPanel{
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
int red = (int) (Math.random() * 255);
int green = (int) (Math.random() * 255);
int blue = (int) (Math.random() * 255);
Color startColor = new Color(red, green, blue);
red = (int) (Math.random() * 255);
green = (int) (Math.random() * 255);
blue = (int) (Math.random() * 255);
Color endColor = new Color(red, green, blue);
GradientPaint gradient = new GradientPaint(70, 70, startColor, 150, 150, endColor);
g2d.setPaint(gradient);
g2d.fillOval(70, 70, 100, 100);
}
private static final long serialVersionUID = 1L;
}
Ответы (2 шт):
Обратите внимание на этот фрагмент кода:
public void actionPerformed(ActionEvent event) {
try {
frame.repaint();
Здесь frame становится null, отсюда NullPointerException. Почему? Потому что вот здесь
public class Test implements ActionListener {
JButton frame;
frame не инициализирован. Поэтому напишите так:
public class Test implements ActionListener {
JFrame frame = new JFrame();
и в методе go() уберите такую же строку
JFrame frame = new JFrame();
И заработает.
Если вы это скопировали из книжки/ресурса - все просто: авторы ошиблись. Или вы плохо переписали.
Отвечу на второй ваш вопрос, если вы внимательно читали предыдущие главы этой книги. То там вы розбирали такую вещь как полиморфизм и интерфейсы. Так вот что-бы добавить елемент на JFrame он должен реализовывать интерфейс JPanel - отсюда следует что каждый елемент который мы можем добавлять во JFrame реализует этот интерфейс. Тогда не сложно догадатся как же все таки JFrame вызывает методы paintComponent(). Например у него в нутри скорее всего есть колекция обобщенная интерфейсным типом JPanel :
List<JPanel> jPanels = new ArrayList<>(); // можно представить что она выглядит так.
И как дальше не сложно понять в момент вызова метода нашего класа JFrame - repaint() мы переберем все елементы хранящиеся в этой колекции и вызовим метод paintComponent(Graphics g) каждого елемента. Примерно так и вам совсем не обязательно самому вызывать метод paintComponent(Graphics g). Лучше перечитайте предыдущие главы. Особенно 10 - 11.