sorry if this has already been asked at some point. I'm trying to implement a JSlider in Java that will grow and shrink an icon in a GUI. So far I have developed the GUI and implemented the slider etc., but the program returns "AWT-EventQueue-0" NullPointerExceptions when I try to move the slider (which call paints the object again. Below I've copied the code for the GUI and for the CarIcon class used therein. Thanks for your help! Sorry if I have made any obvious mistakes here, I am new to GUI coding.
Here's the Slider GUI:
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.Timer;
public SliderGui(){
}
public void initGUI() {
JFrame frame = new JFrame("Slider");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setPreferredSize(new Dimension(F_WIDTH, F_HEIGHT));
frame.setLayout(new BorderLayout());
CarIcon initI = new CarIcon(DEFAULT_SIZE);
this.imagePan = new JLabel(initI);
frame.add(imagePan, BorderLayout.CENTER);
this.setSlider(frame);
}
public void setSlider(JFrame frame) {
JSlider sizeSlider = new JSlider(JSlider.VERTICAL, MIN_SIZE,
MAX_SIZE, DEFAULT_SIZE);
sizeSlider.setMajorTickSpacing(10);
sizeSlider.setMinorTickSpacing(5);
sizeSlider.setPaintTicks(true);
sizeSlider.setPaintLabels(true);
sizeSlider.addChangeListener((ChangeEvent e) -> {
JSlider source = (JSlider)e.getSource();
if (!source.getValueIsAdjusting()) {
int level = (int)source.getValue();
this.icon.setWidth(level);
this.icon.paintIcon(imagePan, this.g, x, y);
}
});
frame.add(sizeSlider, BorderLayout.WEST);
}
public static void main(String[] args) {
SliderGui test = new SliderGui();
test.initGUI();
}
public CarIcon icon;
public Graphics2D g;
private JLabel imagePan;
static final int x = 350;
static final int y = 350;
static final int F_WIDTH = 700;
static final int F_HEIGHT = 700;
static final int MAX_SIZE = 200;
static final int MIN_SIZE = 5;
static final int DEFAULT_SIZE = 75;
}
And here's the CarIcon class:
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
public class CarIcon implements Icon
{
public CarIcon(int aWidth)
{
width = aWidth;
}
public void setWidth(int aWidth) {
this.width = aWidth;
}
public int getIconWidth()
{
return width;
}
public int getIconHeight()
{
return width / 2;
}
public void paintIcon(Component c, Graphics g, int x, int y)
{
Graphics2D g2 = (Graphics2D) g;
Rectangle2D.Double body
= new Rectangle2D.Double(x, y + width / 6,
width - 1, width / 6);
Ellipse2D.Double frontTire
= new Ellipse2D.Double(x + width / 6, y + width / 3,
width / 6, width / 6);
Ellipse2D.Double rearTire
= new Ellipse2D.Double(x + width * 2 / 3, y + width / 3,
width / 6, width / 6);
// The bottom of the front windshield
Point2D.Double r1
= new Point2D.Double(x + width / 6, y + width / 6);
// The front of the roof
Point2D.Double r2
= new Point2D.Double(x + width / 3, y);
// The rear of the roof
Point2D.Double r3
= new Point2D.Double(x + width * 2 / 3, y);
// The bottom of the rear windshield
Point2D.Double r4
= new Point2D.Double(x + width * 5 / 6, y + width / 6);
Line2D.Double frontWindshield
= new Line2D.Double(r1, r2);
Line2D.Double roofTop
= new Line2D.Double(r2, r3);
Line2D.Double rearWindshield
= new Line2D.Double(r3, r4);
g2.fill(frontTire);
g2.fill(rearTire);
g2.setColor(Color.red);
g2.fill(body);
g2.draw(frontWindshield);
g2.draw(roofTop);
g2.draw(rearWindshield);
}
private int width;
}
Problems:
paintIcon(...)
. Let Java itself do this. Instead simply call repaint()
on the JLabel that holds the icon after changing your icon's width -- that's it!This is how I tested it:
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
@SuppressWarnings("serial")
public class ResizeIcon extends JPanel {
private static final int PREF_W = 800;
private static final int PREF_H = 650;
private static final int MAX_ICON_WIDTH = 400;
private int iconWidth = MAX_ICON_WIDTH / 2;
private CarIcon carIcon = new CarIcon(iconWidth);
private JLabel carLabel = new JLabel(carIcon);
private JSlider slider = new JSlider(0, MAX_ICON_WIDTH, iconWidth);
public ResizeIcon() {
slider.setMajorTickSpacing(50);
slider.setMinorTickSpacing(10);
slider.setPaintLabels(true);
slider.setPaintTicks(true);
slider.setPaintTrack(true);
slider.setSnapToTicks(true);
slider.addChangeListener(new SliderListener());
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
setLayout(new BorderLayout());
add(slider, BorderLayout.PAGE_START);
add(carLabel, BorderLayout.CENTER);
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class SliderListener implements ChangeListener {
@Override
public void stateChanged(ChangeEvent e) {
int value = slider.getValue();
carIcon.setWidth(value);
carLabel.repaint();
}
}
private static void createAndShowGui() {
ResizeIcon mainPanel = new ResizeIcon();
JFrame frame = new JFrame("Resize Icon");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
class CarIcon implements Icon {
public CarIcon(int aWidth) {
width = aWidth;
}
public void setWidth(int aWidth) {
this.width = aWidth;
}
public int getIconWidth() {
return width;
}
public int getIconHeight() {
return width / 2;
}
public void paintIcon(Component c, Graphics g, int x, int y) {
Graphics2D g2 = (Graphics2D) g;
Rectangle2D.Double body = new Rectangle2D.Double(x, y + width / 6, width - 1, width / 6);
Ellipse2D.Double frontTire = new Ellipse2D.Double(x + width / 6, y + width / 3, width / 6,
width / 6);
Ellipse2D.Double rearTire = new Ellipse2D.Double(x + width * 2 / 3, y + width / 3,
width / 6, width / 6);
// The bottom of the front windshield
Point2D.Double r1 = new Point2D.Double(x + width / 6, y + width / 6);
// The front of the roof
Point2D.Double r2 = new Point2D.Double(x + width / 3, y);
// The rear of the roof
Point2D.Double r3 = new Point2D.Double(x + width * 2 / 3, y);
// The bottom of the rear windshield
Point2D.Double r4 = new Point2D.Double(x + width * 5 / 6, y + width / 6);
Line2D.Double frontWindshield = new Line2D.Double(r1, r2);
Line2D.Double roofTop = new Line2D.Double(r2, r3);
Line2D.Double rearWindshield = new Line2D.Double(r3, r4);
g2.fill(frontTire);
g2.fill(rearTire);
g2.setColor(Color.red);
g2.fill(body);
g2.draw(frontWindshield);
g2.draw(roofTop);
g2.draw(rearWindshield);
}
private int width;
}