Jslider 增长和收缩图标

Jslider grow and shrink icon

抱歉,如果这个问题已经有人问过。我正在尝试在 Java 中实现一个 JSlider,它将在 GUI 中增大和缩小图标。到目前为止,我已经开发了 GUI 并实现了滑块等,但是程序 returns "AWT-EventQueue-0" NullPointerExceptions 当我尝试移动滑块时(调用再次绘制对象。下面我复制了代码对于 GUI 和其中使用的 CarIcon class。感谢您的帮助!抱歉,如果我在这里犯了任何明显的错误,我是 GUI 编码的新手。

这是滑块 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;       
}

这是 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;
 }

问题:

  • 不要给你的 class Graphics 或 Graphics2D 字段,因为这样做几乎可以保证你的 gui 图形由于不稳定的 Graphics 对象而出现错误,或者让它抛出 NullPointerException 试图使用 null图形对象。
  • 您不应该尝试通过调用 paintIcon(...) 直接绘制图标。让 Java 自己来做这件事。相反,只需在更改图标宽度后在包含图标的 JLabel 上调用 repaint()——就是这样!

我是这样测试的:

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;
}