2

ActionListener を実装する Java でグラフィカル ユーザー インターフェイス プログラムを作成しています。このプログラムは、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 で描画する方法を読んでおくとよいでしょう。paintComponent(Graphics g)JVM によって提供され、JComponent の (JPanel などの)メソッドに渡される Graphics オブジェクトを使用する必要があります。これは、 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...

null の変数を使用しているため、NPE がスローされても驚くことではありません。私がリンクしたチュートリアルを読んでください。

paintComponent(...)JPanel またはその他の JComponent 派生クラスのメソッド オーバーライドで描画を行うか、Graphics オブジェクトを抽出して描画することにより BufferedImage で描画を行う必要があります。コードタブなどの静的画像を作成している場合は、BufferedImages が適している可能性が高く、JLabel に保持されている ImageIcon または paintComponent メソッドでそれらを表示します。

于 2012-11-25T23:56:16.160 に答える
2

あなたは何を期待していましたか:

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

また、あなたのpaintメソッドは、カスタム ペインティングの最も重要なルールの 1 つを破っています。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 に答える