2

我正在用 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。我只是使用框架。我的程序有什么问题?谢谢!

这是我的一些代码(截至目前,该程序已超过 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();
}
4

2 回答 2

2

啊哈,强制转换变量,null,图形,我来猜一猜——你试图将 Graphics 对象保存为类字段,你将它强制转换为 Graphics2D,它是 null。如果是这样,您将需要阅读如何使用 Swing 进行绘图,因为它不是这样做的。您必须使用 JVM 提供的 Graphics 对象并传递给 JComponent(例如 JPanel)的paintComponent(Graphics g)方法。这是开始学习在 Swing 中执行自定义绘画的一个不错的链接。

再一次,你会想要重构你的代码,因为你的类听起来太大了。此外,您还需要学习和使用 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...

您正在使用一个为空的变量,因此它引发 NPE 也就不足为奇了。请阅读我链接到的教程。

您将希望在paintComponent(...)JPanel 或其他 JComponent 派生类的方法覆盖中进行绘图,或者在 BufferedImage 中通过提取其 Graphics 对象并使用它进行绘图。如果您正在创建静态图像,例如和弦选项卡,那么 BufferedImages 可能是您的选择,然后将它们显示在 JLabel 中保存的 ImageIcon 或 paintComponent 方法中。

于 2012-11-25T23:56:16.160 回答
2

正是您所期望的:

Graphics g = null;
Graphics2D g2 = (Graphics2D) g;

此外,您的paint方法违反了自定义绘画最重要的规则之一,它未能调用super.paint这会产生更多问题,因此值得列出。

执行自定义绘画时优先覆盖的方法是paintComponent,但是,因为您要覆盖Frame(??) 它没有paintComponent方法。

这里有一些想法......

  1. 在 AWT 上使用 Swing 组件。它们更容易使用。
  2. 从类似的东西扩展JPanel并在其上执行您的自定义绘画。这为您提供了更灵活的设计选择并减少了问题。
  3. 总是打电话super.paintXxx,如果你不打电话,预计事情会在你的脸上爆炸。
  4. 所有绘画都必须通过 apaint方法完成。您无法控制油漆过程,只需接受它并继续前进。您可以鼓励重新绘制,但您只能在paint方法的上下文中进行绘制。
  5. Graphics上下文由系统控制。如果你想在上面画画,你必须等待一个可用,见前一点。这个上下文可以改变,所以你永远不应该保持对它的引用。上下文是共享的Graphics,未能遵守绘画链将导致出现绘画伪影

您可能想抽出时间阅读

于 2012-11-26T00:03:47.147 回答