我正在用Java编写一个实现ActionListener的图形用户界面程序。该程序是使用2D图形的吉他和弦可视化器。我有一个工具栏,用户可以选择要显示的和弦。因此在actionPerformed(ActionEvent e)方法中,当用户选择某个和弦时,该选项会调用显示和弦的方法。但是,当我测试程序时,我遇到了大量的错误。以下是错误消息
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)
另外,我没有使用JPanel或JFrame。我只是使用Frame。 我的计划有什么问题?谢谢!
以下是我的一些代码(截至目前,该程序已超过500行)。
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();
}
答案 0 :(得分:2)
啊哈,投射变量,null,图形,我要猜测 - 你试图将Graphics对象保存为类字段,你将它转换为Graphics2D,它是null。如果是这样,你会想要了解如何使用Swing绘图,因为这不是它的完成方式。您必须使用JVM提供的Graphics对象并将其传递给JComponent(例如JPanel的)paintComponent(Graphics g)
方法。这是开始在Swing中学习Performing Custom Painting的一个不错的链接。
同样,你会想要重构你的代码,因为你的类听起来方式太大了。您还需要学习和使用Java命名约定。例如,类名应以大写字母开头。
哎呀,情况更糟:
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...
你正在使用一个null的变量,所以它抛出一个NPE就不足为奇了。请阅读我链接到的教程。
您需要在JPanel或其他JComponent派生类的paintComponent(...)
方法覆盖中进行绘制,或者在BufferedImage中通过提取其Graphics对象并使用它进行绘制。如果您正在创建静态图像(如和弦选项卡),那么BufferedImages可能会成为可行的方式,然后将它们显示在JLabel或paintComponent方法中的ImageIcon中。
答案 1 :(得分:2)
您对此的期望是什么:
Graphics g = null;
Graphics2D g2 = (Graphics2D) g;
此外,您的paint
方法违反了自定义绘画最重要的规则之一,它无法调用super.paint
这会产生更多问题,因此值得列出。
执行自定义绘制时要覆盖的首选方法是paintComponent
,但是,因为您覆盖了Frame
(??),所以它没有paintComponent
方法。
这是一些想法......
JPanel
等内容扩展并在其上执行自定义绘画。这为您提供了更灵活的设计选择,并减少了问题。super.paintXxx
,希望事情能够在你脸上爆炸。paint
方法完成。你无法控制油漆过程,只需接受它并继续前进。您可以鼓励重绘,但您只能在paint
方法的上下文中进行绘制。Graphics
上下文由系统控制。如果要在其上绘画,则必须等待其中一个可用,请参阅上一点。这个上下文可以改变,所以你永远不应该保持对它的引用。共享Graphics
上下文,未能遵守绘制链将导致出现绘制工件您可能希望抽出时间阅读