gpt4 book ai didi

java - 在调用另一个方法后调用方法时出现空指针异常?

转载 作者:行者123 更新时间:2023-11-29 06:44:13 25 4
gpt4 key购买 nike

我有一个图像编辑程序。它有多种方法,如灰度、缩放、合并图像等。每种方法都可以完美地独立工作。但是,在调用 mergeImg 方法后调用 grayScale 方法时出现错误。如果我先应用灰度,则不会发生这种情况。

这里是错误:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at Picture.width(Picture.java:51)
at Picture$4.actionPerformed(Picture.java:222)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.AbstractButton.doClick(AbstractButton.java:376)
at javax.swing.plaf.basic.BasicMenuItemUI.doClick(BasicMenuItemUI.java:833)
at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(BasicMenuItemUI.java:877)
at java.awt.Component.processMouseEvent(Component.java:6504)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
at java.awt.Component.processEvent(Component.java:6269)
at java.awt.Container.processEvent(Container.java:2229)
at java.awt.Component.dispatchEventImpl(Component.java:4860)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Component.dispatchEvent(Component.java:4686)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
at java.awt.Container.dispatchEventImpl(Container.java:2273)
at java.awt.Window.dispatchEventImpl(Window.java:2713)
at java.awt.Component.dispatchEvent(Component.java:4686)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:707)
at java.awt.EventQueue.access$000(EventQueue.java:101)
at java.awt.EventQueue$3.run(EventQueue.java:666)
at java.awt.EventQueue$3.run(EventQueue.java:664)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.awt.EventQueue$4.run(EventQueue.java:680)
at java.awt.EventQueue$4.run(EventQueue.java:678)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:677)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

这是我的代码:

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import javax.swing.*;
import java.awt.image.*;
import javax.imageio.ImageIO;
import java.lang.Math;

public class Picture{
JFileChooser fileChooser = new JFileChooser(); //file chooser
final JFrame frame = new JFrame("ImageEdit"); //creates JFrame
Container content; //creates container to place GUI objects in
static BufferedImage image; //original image
BufferedImage image2; //image after changes are made
BufferedImage mergeImage; //used for mergeImg method
JLabel imageLabel; //used to display image

//constructor; welcomes user, asks for image input
public Picture() {
//pops up prior to JFileChooser, intstructing user on what to do
Object[] options = {"Browse...", "Exit"};
ImageIcon welcomeIcon = new ImageIcon("GUI-images/welcome-icon.png");
int getFile = JOptionPane.showOptionDialog(frame, "Welcome to ImageEdit. To begin, please select an image file to edit.",
"Welcome!", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE, welcomeIcon, options, options[0]);

//if user selects browse option, do this:
if (getFile == JOptionPane.YES_OPTION) {
//asks for image file as input
browse();
}

//otherwise, exit program
else {
//exit program
System.exit(0);
}
}

//method returns width of image
public int width() {
int width = image.getWidth();
return width;
}

//method returns height of image
public int height() {
int height = image.getHeight();
return height;
}

//method sets updated image as "original" image
public void setImage() {
this.image = image2;
}

//method writes image in destination
public void saveImage() {
//gets file name & destination from user through JFileChooser
fileChooser.setDialogTitle("Save As...");
fileChooser.showSaveDialog(frame);

//writes image to new file with given name & location
try {
ImageIO.write(this.image, "JPG", fileChooser.getSelectedFile());
}
catch (IOException f) {
System.out.println("Saving failed! Could not save image.");
}
}

//method browses for new file
public void browse() {
//asks for new image file
fileChooser.setDialogTitle("Choose an image file:");
fileChooser.showOpenDialog(frame);
File selectedFile = fileChooser.getSelectedFile();

//if user has selected image file, continue
if (fileChooser.getSelectedFile() != null) {
try {
//reads selectedFile as image
image = ImageIO.read(selectedFile);
}
catch (IOException e) {
System.out.println("Invalid image file: " + selectedFile);
System.exit(0);
}
}

//else print error message
else {
System.out.println("Error! No File Selected.");
}
}

//method creates frame, adds menubar with options, provides parameters for other methods
public void show() {
//set frame title, set it visible, etc
content = frame.getContentPane();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);

//add the image to the frame
ImageIcon icon = new ImageIcon(image);
imageLabel = new JLabel(icon);
frame.setContentPane(imageLabel);

//adds a menubar on the frame with program name, File & Edit menus
JMenuBar menuBar = new JMenuBar();
frame.setJMenuBar(menuBar);
JMenu progName = new JMenu("ImageEdit");
progName.setBackground(Color.RED);
menuBar.add(progName);
JMenu fileMenu = new JMenu("File");
menuBar.add(fileMenu);
JMenu editMenu = new JMenu("Edit");
menuBar.add(editMenu);

//adds options to JMenus
//option to exit application
ImageIcon exitIcon = new ImageIcon("GUI-images/app-exit.png");
JMenuItem exitAction = new JMenuItem("Exit", exitIcon);
progName.add(exitAction);

//if exit option is selected, do this:
exitAction.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//prompts to save file before exiting
ImageIcon saveIcon = new ImageIcon("GUI-images/save-icon.png");
int askSave = JOptionPane.showConfirmDialog(null,"Save image before exit?", "Save...",
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, saveIcon);
if (askSave == JOptionPane.YES_OPTION) {
//opens save image method, then exits
saveImage();
System.exit(0);
}
else {
//exits without saving
System.exit(0);
}
}
});

//option to open a new image
ImageIcon newIcon = new ImageIcon("GUI-images/new-image.png");
JMenuItem newAction = new JMenuItem("Open Image", newIcon);
fileMenu.add(newAction);

//if new option is selected, do this:
newAction.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//prompts to save image before opening new image
ImageIcon saveIcon = new ImageIcon("GUI-images/save-icon.png");
int askSave = JOptionPane.showConfirmDialog(null,"Save current image?", "Save...",
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, saveIcon);
//if they do want to save first, do this:
if (askSave == JOptionPane.YES_OPTION) {
//opens save image method, then asks asks for new image file
saveImage();

//clears old image
imageLabel.setIcon(null);

//browses for new image
browse();
//displays new image
imageLabel.setIcon(new ImageIcon(image));

//resizes canvas to fit new image
frame.setSize(width(), height());
}
//if they don't want to save, do this:
else {
//erases old image
imageLabel.setIcon(null);

//browses for new image
browse();

//displays new image
imageLabel.setIcon(new ImageIcon(image));

//resizes canvas to fit new image
frame.setSize(width(), height());
}
}
});

//option to save current image
ImageIcon saveIcon = new ImageIcon("GUI-images/save-image.png");
JMenuItem saveAction = new JMenuItem("Save Image As...", saveIcon);
fileMenu.add(saveAction);

//if save option is selected, do this:
saveAction.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//opens save image method
saveImage();
}
});

//option to make current image grayscale
ImageIcon gsIcon = new ImageIcon("GUI-images/grayscale-image.png");
JMenuItem grayScale = new JMenuItem("Grayscale", gsIcon);
editMenu.add(grayScale);

//if grayscale option is selected, do this:
grayScale.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//grabs height and width of image,
//then calls grayscale method
grayscale(width(), height());
}
});

//option to scale current window to new dimensions
ImageIcon scaleIcon = new ImageIcon("GUI-images/scale-image.png");
JMenuItem scaleImg = new JMenuItem("Scale Image", scaleIcon);
editMenu.add(scaleImg);

//if scale option is selected, do this:
scaleImg.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//asks for height and width to create new image
ImageIcon widthIcon = new ImageIcon("GUI-images/LR-arrows.png");
String scaleWidth = (String)JOptionPane.showInputDialog(null,"What should the new width be?",
"Scale Image", JOptionPane.QUESTION_MESSAGE, widthIcon, null, null);
ImageIcon heightIcon = new ImageIcon("GUI-images/UD-arrows.png");
String scaleHeight = (String)JOptionPane.showInputDialog(null,"What should the new height be?",
"Scale Image", JOptionPane.QUESTION_MESSAGE, widthIcon, null, null);

//turns user input strings into doubles
double x = Double.parseDouble(scaleWidth);
double y = Double.parseDouble(scaleHeight);

//casts doubles as ints
int newWidth = (int)x;
int newHeight = (int)y;

//resizes frame to fit new image dimensions
frame.setSize(newWidth, newHeight);

//calls scale method to resize image using given dimensions
scale(newWidth, newHeight);
}
});

//option to merge two images together
ImageIcon mergeIcon = new ImageIcon("GUI-images/merge-image.png");
JMenuItem mergeImg = new JMenuItem("Merge Image", mergeIcon);
editMenu.add(mergeImg);

//if merge option is selected, do this:
mergeImg.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//asks for image file as input
fileChooser.setDialogTitle("Choose an image file to merge current image with.");
fileChooser.showOpenDialog(frame);
File mergeFile = fileChooser.getSelectedFile();

//if user has selected image file, continue
if (fileChooser.getSelectedFile() != null) {
try {
//reads selectedFile as image
mergeImage = ImageIO.read(mergeFile);
}
catch (IOException f) {
System.out.println("Invalid image file: " + mergeFile);
System.exit(0);
}
}

//else print error message
else {
System.out.println("Error! No File Selected.");
}

//if two images are same size, merge them
if (width() == mergeImage.getWidth() && height() == mergeImage.getHeight()) {
mergeImg(width(), height(), mergeImage);
}
//else, resize the second image to size of original, then merge
else {
scale(width(), height());
mergeImg(width(), height(), mergeImage);
}
}
});

//option to rotate image by x degrees
ImageIcon rotateIcon = new ImageIcon("GUI-images/rotate-image.png");
JMenuItem rotateImage = new JMenuItem("Rotate Image", rotateIcon);
editMenu.add(rotateImage);

//if rotate option is selected, do this:
rotateImage.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String rotateAngle = (String)JOptionPane.showInputDialog(null,"By what angle would you like to rotate?",
"Input Degrees", JOptionPane.QUESTION_MESSAGE, null/*icon goes here*/, null, null);

//turns user input strings into doubles
double angleDegs = Double.parseDouble(rotateAngle);

//converts degrees to rads
double angle = Math.toRadians(angleDegs);

//applies sine and cosine functions
int sin = (int)Math.sin(angle);
int cos = (int)Math.cos(angle);

//gets new width of rotated image
int newWidth = width()*sin + height()*cos;
int newHeight = height()*sin + width()*cos;

//sets frame to new image size
frame.setSize(newWidth, newHeight);

//calls rotate method to rotate image
rotate(newWidth, newHeight, angle);
}
});

//paint the frame
frame.pack();
frame.repaint();
frame.setVisible(true);
}

//method converts image to grayscale; 6 lines of code
public void grayscale(int width, int height) {
// create a grayscale image with original dimensions
image2 = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);

// convert colored image to grayscale
ColorConvertOp grayScale = new ColorConvertOp(image.getColorModel().getColorSpace(),
image2.getColorModel().getColorSpace(),null);
grayScale.filter(image,image2);
imageLabel.setIcon(new ImageIcon(image2));

//sets new image as "original"
setImage();
}

//method scales image to user-input dimensions; 5 lines of code
public void scale(int width, int height){
//uses user-input dimensions to create new image
image2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = image2.createGraphics();

//gets new dimensions and resizes image
g.drawImage(image, 0, 0, image2.getWidth(), image2.getHeight(), 0, 0, width(), height(), null);
imageLabel.setIcon(new ImageIcon(image2));

//sets new image as "original"
setImage();
}

//method merges two images together; 14 lines of code
public void mergeImg(int width, int height, BufferedImage mergeImage) {
//creates new image from two images of same size
BufferedImage image2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
//get color from original image
Color c = new Color(image.getRGB(i, j));

//get colors from merge image
Color c2 = new Color(mergeImage.getRGB(i, j));

//average the colors
int r = (c.getRed()+c2.getRed())/2;
int g = (c.getGreen()+c2.getGreen())/2;
int b = (c.getBlue()+c2.getBlue())/2;
Color avgColor = new Color(r, g, b);

//set colors of new image to average of the two images
image2.setRGB(i, j, avgColor.getRGB());
imageLabel.setIcon(new ImageIcon(image2));
}
}

mergeImage = null;
//sets new image as "original"
setImage();
}

//method rotates image by user-input angle; 18 lines of code
public void rotate(int width, int height, double angle) {
//rotates image around center point
BufferedImage image2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

//defines sin and cos functions
double sin = Math.sin(angle);
double cos = Math.cos(angle);

//gets coordinates of image center
double Xc = width/2;
double Yc = height/2;

//rotate
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
//new i,j at center of image
double iPrime = i - Xc;
double jPrime = j - Yc;
//i,j at new points after rotation
int xPrime = (int) (iPrime * cos - jPrime * sin + Xc);
int yPrime = (int) (iPrime * sin + jPrime * cos + Yc);

// plot pixel (i, j) the same color as (xPrime, yPrime) if it's in bounds
if (xPrime >= 0 && xPrime < width && yPrime >= 0 && yPrime < height) {
image2.setRGB(xPrime, yPrime, image.getRGB(i, j));
imageLabel.setIcon(new ImageIcon(image2));
}
}
}

//sets new image as "original"
setImage();
}

//main method; starts program
public static void main(String[] args) {
//creates new picture from image file
Picture p = new Picture();

//shows picture on JFrame
p.show();
}
}

有什么想法吗?感谢您的帮助!

最佳答案

从堆栈轨迹和代码来看,好像是这个方法

//method returns width of image
public int width() {
int width = image.getWidth();
return width;
}

抛出一个 NullPointerException。如果 imagenull,唯一会导致这种情况。

我建议您逐步检查有问题的方法,并检查将 null 分配给 image 变量的位置和原因。


一个可能的问题是您在方法 rotatemergeImg 中重新声明了 image2

BufferedImage image2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

这有效地“隐藏”了 this.image2。当您稍后调用 setImage 并执行

this.image = image2;

image2 没有引用您准备的局部变量。

关于java - 在调用另一个方法后调用方法时出现空指针异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7798406/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com