Reputation: 944
I am writing a graphical user interface program in Java that implements ActionListener. The program is a guitar chord visualizer using 2D graphics. I have a toolbar where the user selects what chord to be displayed. So in the actionPerformed(ActionEvent e) method, when the user selects a certain chord, that choice calls a method where the chord is displayed. However, when I test the program I get tons of errors. Here are the error messages
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at fretboard.displayAMajor(fretboard.java:493)
at fretboard.actionPerformed(fretboard.java:74)
at java.awt.MenuItem.processActionEvent(MenuItem.java:650)
at java.awt.MenuItem.processEvent(MenuItem.java:609)
at java.awt.MenuComponent.dispatchEventImpl(MenuComponent.java:343)
at java.awt.MenuComponent.dispatchEvent(MenuComponent.java:331)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:707)
at java.awt.EventQueue.access$400(EventQueue.java:82)
at java.awt.EventQueue$2.run(EventQueue.java:663)
at java.awt.EventQueue$2.run(EventQueue.java:661)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:98)
at java.awt.EventQueue$3.run(EventQueue.java:677)
at java.awt.EventQueue$3.run(EventQueue.java:675)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:674)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:296)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:211)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:196)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:188)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
Also, I am not using JPanel or JFrame. I am simply using Frame. What is wrong with my program? Thanks!
Here is some of my code (The program is over 500 lines as of now).
public class fretboard extends Frame implements ActionListener{
public static void main(String[] args) {
Frame frame = new fretboard();
frame.setSize(1280, 960);
frame.setVisible(true);
}
/**
* Create the menu bar and set title
*/
public fretboard() {
// Change the title of the window
setTitle("Fretboard");
// Create a menu bar where user will be given choice of chords
MenuBar mb = new MenuBar();
setMenuBar(mb);
Menu menu = new Menu("Chords");
mb.add(menu);
}
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if("A Major".equals(command)) {
displayAMajor();
}
This method contains the bulk of my program. Here are just a few lines.
public void paint(Graphics g) {
// Declare local variables
int h = 40, w = 26, x = 695, y = 230;
Graphics2D g2 = (Graphics2D) g;
Font font = new Font("SansSerif", Font.BOLD, 28);
Font font1 = new Font("SansSerif", Font.BOLD, 18);
// Declare the note variables
// First string
Ellipse2D E1 = new Ellipse2D.Double(x, y-110, w, h);
// Open the image
File fretBoardFile = new File("/Users/macbook/desktop/Gibson_Fretboard.jpg");
BufferedImage bi = null;
try {
bi = ImageIO.read(fretBoardFile);
g.drawImage(bi, 25, 25, null);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Draw notes
// Draw the E note on the open 1st string
// Change color to blue
g2.setColor(Color.blue);
g2.draw(E1);
g2.fill(E1);
g2.setColor(Color.white);
g2.setFont(font);
g2.drawString("E", x+5, y-80);
// Change color back to blue
g2.setColor(Color.blue);
public void displayAMajor() {
// Declare local variables
int h = 40, w = 26, x = 695, y = 230;
Graphics g = null;
Graphics2D g2 = (Graphics2D) g;
//Graphics2D g2 = new Graphics();
Font font = new Font("SansSerif", Font.BOLD, 28);
// Declare notes
Ellipse2D E1 = new Ellipse2D.Double(x, y-110, w, h);
// Display notes for the A Major chord
// Draw the E note on the open 1st string
// Change color to red
g2.setColor(Color.red);
g2.draw(E1);
g2.fill(E1);
g2.setColor(Color.white);
g2.setFont(font);
g2.drawString("E", x+5, y-80);
// Change color back to blue
g2.setColor(Color.blue);
repaint();
}
Upvotes: 2
Views: 901
Reputation: 347234
Just what did you expect from:
Graphics g = null;
Graphics2D g2 = (Graphics2D) g;
Also, your paint
method breaks one of the most important rules of custom painting, it fails to call super.paint
this is going to create more problems then it is worth listing.
The preferred method to override when performing custom painting is paintComponent
, but, because you're overriding Frame
(??) it doesn't have a paintComponent
method.
Here's some ideas...
JPanel
and perform your custom painting on it instead. This provides you with more flexible design choices and cause less issues.super.paintXxx
, if you don't, expect things to blow up in your face.paint
method. You do not control over the paint process, just accept it and move on. You can encourage a repaint, but you must only paint from within the context of a paint
method.Graphics
context is controlled by the system. If you want to paint on it, you must wait for one to become available, see previous point. This context can change, so you should never maintain a reference to it. The Graphics
context is shared, failing to honor the paint chain will result in paint artifacts appearingYou might like to make the time to have a read through
Upvotes: 2
Reputation: 285405
Aha, casting variables, null, graphics, I'm going to take a guess -- you're trying to save the Graphics object as a class field, you're casting it to Graphics2D, and it's null. If so, you'll want to read up on how to do drawing with Swing because that's not how it's done. You must use the Graphics object provided by the JVM and passed into a JComponent's (such as a JPanel's) paintComponent(Graphics g)
method. This is a decent link to start learning about Performing Custom Painting in Swing.
And again, you'll want to refactor your code because your class sounds way too big. Also you'll want to learn and use Java naming conventions. Class names should start with upper case letters for instance.
Yikes, it's even worse:
Graphics g = null; // ******* this is null!!!!
Graphics2D g2 = (Graphics2D) g; // ***** it's *STILL* null!!
//Graphics2D g2 = new Graphics();
Font font = new Font("SansSerif", Font.BOLD, 28);
Ellipse2D E1 = new Ellipse2D.Double(x, y-110, w, h);
g2.setColor(Color.red); // ***** it's *STILL* null!!
g2.draw(E1); // ***** it's *STILL* null!!
g2.fill(E1); // **** etc...
You're using a variable that is null, so it should be no surprise that it throws a NPE. Please read the tutorial that I've linked to.
You'll want to do your drawing either in the paintComponent(...)
method override of a JPanel or other JComponent-derived class, either that or in a BufferedImage by extracting its Graphics object and drawing with that. If you're creating static images such as chord tabs, then BufferedImages will likely be the way to go, and then display them either in a ImageIcon held in a JLabel or in a paintComponent method.
Upvotes: 2