2010-01-12 49 views
1

我跑了下面的代碼10次。在10次運行中,3次顯示菜單欄和矩形,3次只顯示矩形,4次顯示沒有任何結果。我究竟做錯了什麼?Fickle JMenuBar

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 
import static java.awt.Color.*; 
import java.awt.image.*; 


public class GUI extends JFrame implements KeyListener, ActionListener 
{ 
    int x, y; 
    public static void main(String[] args) 
    { 
     new GUI(); 
    } 
    public GUI() 
    { 
     try 
     { 
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
     } catch (Exception e) 
     { 
      e.printStackTrace(); 
     }  
     frameInit(); 
     setSize(1024,768); 
     setDefaultCloseOperation(EXIT_ON_CLOSE);; 
     setVisible(true); 
     setJMenuBar(createMenuBar()); 
     addKeyListener(this); 
     createBufferStrategy(2); 
     x = 0; 
     y = 49; 
    } 
    public void paint(Graphics gm) 
    { 
     BufferStrategy bs = getBufferStrategy(); 
     try 
     { 
      Graphics g = bs.getDrawGraphics(); 
      super.paint(g); 
      g.setColor(WHITE); 
      g.drawRect(0,0,1024,768); 
      g.setColor(BLACK); 
      g.fillRect(x,y,100,100); 
      bs.show(); 
     }catch(Exception e) 
     { 

     } 
    } 
    public JMenuBar createMenuBar() 
    { 
     JMenuBar menuBar = new JMenuBar(); 
     JMenu fileMenu = new JMenu("File"); 
     fileMenu.setMnemonic(KeyEvent.VK_F); 
     JMenuItem save = new JMenuItem("Save"); 
     save.setMnemonic(KeyEvent.VK_S); 
     save.addActionListener(this); 
     JMenuItem load = new JMenuItem("Load"); 
     load.setMnemonic(KeyEvent.VK_L); 
     load.addActionListener(this); 
     JMenuItem quit = new JMenuItem("Quit"); 
     quit.setMnemonic(KeyEvent.VK_Q); 
     quit.addActionListener(this); 
     fileMenu.add(save); 
     fileMenu.add(load); 
     fileMenu.addSeparator(); 
     fileMenu.add(quit); 
     JMenu editMenu = new JMenu("Edit"); 
     editMenu.setMnemonic(KeyEvent.VK_E); 
     JMenuItem undo = new JMenuItem("Undo"); 
     undo.setMnemonic(KeyEvent.VK_U); 
     undo.addActionListener(this); 
     JMenuItem redo = new JMenuItem("Redo"); 
     redo.setMnemonic(KeyEvent.VK_R); 
     redo.addActionListener(this); 
     editMenu.add(undo); 
     editMenu.add(redo); 
     JMenu helpMenu = new JMenu("Help"); 
     helpMenu.setMnemonic(KeyEvent.VK_H); 
     JMenuItem controls = new JMenuItem("Controls"); 
     controls.setMnemonic(KeyEvent.VK_C); 
     controls.addActionListener(this); 
     JMenuItem about = new JMenuItem("About"); 
     about.setMnemonic(KeyEvent.VK_A); 
     about.addActionListener(this); 
     helpMenu.add(controls); 
     helpMenu.addSeparator(); 
     helpMenu.add(about); 
     menuBar.add(fileMenu); 
     menuBar.add(editMenu); 
     menuBar.add(helpMenu); 
     menuBar.setLocation(0,23); 
     return menuBar; 
    } 
    public void actionPerformed(ActionEvent e) 
    { 
     System.out.println(e.getActionCommand()); 
     repaint(); 
    } 
    public void keyPressed(KeyEvent e) 
    { 
     if(e.getKeyCode()==KeyEvent.VK_UP) 
     { 
      y-=10; 
     } 
     if(e.getKeyCode()==KeyEvent.VK_DOWN) 
     { 
      y+=10; 
     } 
     if(e.getKeyCode()==KeyEvent.VK_LEFT) 
     { 
      x-=10; 
     } 
     if(e.getKeyCode()==KeyEvent.VK_RIGHT) 
     { 
      x+=10; 
     } 
     repaint(); 
    } 
    public void keyReleased(KeyEvent e) 
    { 
    } 
    public void keyTyped(KeyEvent e) 
    {  
    } 

} 

回答

2

由於您重寫了JFrame的繪製方式,因此完全忽略了JMenu欄的繪畫。

不要繼承JFrame,使用自定義組件,這裏是對代碼的快速編輯,不需要太多考慮,我只是移動一些部分。

它的工作原理時代的100%對我來說:

it works fine like this http://img706.imageshack.us/img706/1291/capturadepantalla201001l.png

//I ran the following code 10 times. Of the 10 runs, 3 showed both the menu bar and the rectangle, 3 showed only the rectangle, and 4 showed nothing at all. What am I doing wrong? 

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 
import static java.awt.Color.*; 
import java.awt.image.*; 


public class GUI extends JComponent implements KeyListener, ActionListener { 
    private int x, y; 
    public static void main(String[] args) { 
     setLnF(); 
     // Don't subclass it just use it. 
     JFrame frame = new JFrame(); 
     //frameInit(); 
     frame.setSize(1024,768); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     //frame.setVisible(true); 

     GUI gui = new GUI(); 

     frame.setJMenuBar(gui.createMenuBar()); 
     frame.addKeyListener(gui);  
     frame.add(gui) ; 
     frame.setVisible(true); // should be the last thing to call 


    } 
    private static void setLnF() { 
     try { 
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
     } catch (ClassNotFoundException e) { 
      e.printStackTrace(); 
     } catch(InstantiationException ie) { 
      ie.printStackTrace(); 
     } catch(IllegalAccessException iae) { 
      iae.printStackTrace(); 
     } catch(UnsupportedLookAndFeelException u) { 
      u.printStackTrace(); 
     } 
    } 
    public GUI() { 
     //createBufferStrategy(2); 
     x = 0; 
     y = 49; 
    } 
    public void paint(Graphics gm) { 
     //BufferStrategy bs = getBufferStrategy(); 
     try { 
      Graphics g = gm; // bs.getDrawGraphics(); 
      super.paint(g); 
      g.setColor(WHITE); 
      g.drawRect(0,0,1024,768); 
      g.setColor(BLACK); 
      g.fillRect(x,y,100,100); 
      //bs.show(); 
     }catch(Exception e) { 
      e.printStackTrace(); 
     } 
    } 
    public JMenuBar createMenuBar() { 
     JMenuBar menuBar = new JMenuBar(); 
     JMenu fileMenu = new JMenu("File"); 
     fileMenu.setMnemonic(KeyEvent.VK_F); 
     JMenuItem save = new JMenuItem("Save"); 
     save.setMnemonic(KeyEvent.VK_S); 
     save.addActionListener(this); 
     JMenuItem load = new JMenuItem("Load"); 
     load.setMnemonic(KeyEvent.VK_L); 
     load.addActionListener(this); 
     JMenuItem quit = new JMenuItem("Quit"); 
     quit.setMnemonic(KeyEvent.VK_Q); 
     quit.addActionListener(this); 
     fileMenu.add(save); 
     fileMenu.add(load); 
     fileMenu.addSeparator(); 
     fileMenu.add(quit); 
     JMenu editMenu = new JMenu("Edit"); 
     editMenu.setMnemonic(KeyEvent.VK_E); 
     JMenuItem undo = new JMenuItem("Undo"); 
     undo.setMnemonic(KeyEvent.VK_U); 
     undo.addActionListener(this); 
     JMenuItem redo = new JMenuItem("Redo"); 
     redo.setMnemonic(KeyEvent.VK_R); 
     redo.addActionListener(this); 
     editMenu.add(undo); 
     editMenu.add(redo); 
     JMenu helpMenu = new JMenu("Help"); 
     helpMenu.setMnemonic(KeyEvent.VK_H); 
     JMenuItem controls = new JMenuItem("Controls"); 
     controls.setMnemonic(KeyEvent.VK_C); 
     controls.addActionListener(this); 
     JMenuItem about = new JMenuItem("About"); 
     about.setMnemonic(KeyEvent.VK_A); 
     about.addActionListener(this); 
     helpMenu.add(controls); 
     helpMenu.addSeparator(); 
     helpMenu.add(about); 
     menuBar.add(fileMenu); 
     menuBar.add(editMenu); 
     menuBar.add(helpMenu); 
     menuBar.setLocation(0,23); 
     return menuBar; 
    } 
    public void actionPerformed(ActionEvent e) { 
     System.out.println(e.getActionCommand()); 
     repaint(); 
    } 
    public void keyPressed(KeyEvent e) { 
     if(e.getKeyCode()==KeyEvent.VK_UP) { 
      y-=10; 
     } 
     if(e.getKeyCode()==KeyEvent.VK_DOWN) { 
      y+=10; 
     } 
     if(e.getKeyCode()==KeyEvent.VK_LEFT) { 
      x-=10; 
     } 
     if(e.getKeyCode()==KeyEvent.VK_RIGHT) { 
      x+=10; 
     } 
     repaint(); 
    } 
    public void keyReleased(KeyEvent e) { 
    } 
    public void keyTyped(KeyEvent e) {  
    } 

} 

編輯

你的問題是在這裏:

frameInit(); 
    setSize(1024,768); 
    setDefaultCloseOperation(EXIT_ON_CLOSE);; 
    setVisible(true); //<-- exaaaactly here!! 
    setJMenuBar(createMenuBar()); 
    addKeyListener(this); 
    createBufferStrategy(2); 

該行剛剛轉會結束,它應該工作得很好。

frameInit(); 
    setSize(1024,768); 
    setDefaultCloseOperation(EXIT_ON_CLOSE);; 
    ///setVisible(true); //<-- exaaaactly here!! 
    setJMenuBar(createMenuBar()); 
    addKeyListener(this); 
    createBufferStrategy(2); 
    setVisible(true); 

我說的有關子類化JFrame仍然有效。

+0

只是出於好奇,關於子類分類JFrame – resotpvl 2010-01-14 20:00:53

+1

有什麼不好?因爲通過繼承你將你的類綁定到JFrame非常深入,在這種情況下,現在是必要的。重新定義類的行爲時,應該繼承(子類),當功能發生變化時,不僅在數據發生變化時。在這個例子中,你只是使用JFrame,沒有理由繼承它。繼承也使得執行單元測試變得更加困難(因爲要測試你的代碼,你必須始終創建一個JFrame),同時使用組合可以單獨測試你的功能。繼承是在OOP中的地位,但不應該被濫用。 – OscarRyz 2010-01-14 21:33:42

0

首先,您使用的是不良支架風格。但是,這不是問題在這裏。

在線48你忽略了異常:

try { 

} catch(Exception e) { 

} 

如果添加此:

e.printStackTrace(); 

它會告訴你是什麼問題,當我跑它,它說:

java.lang.NullPointerException 
at GUI.paint(GUI.java:41) 
at sun.awt.RepaintArea.paintComponent(RepaintArea.java:276) 
at sun.awt.RepaintArea.paint(RepaintArea.java:241) 
at apple.awt.ComponentModel.handleEvent(ComponentModel.java:263) 

GUI.java在第41行是:

BufferStrategy bs = getBufferStrategy(); 
try { 
    Graphics g = bs.getDrawGraphics(); // <--- this line 

這裏您的bs變量爲空,方法getBufferStrategy返回null而不是有效的對象引用。爲什麼?我不知道,你回答我。那是什麼getBufferStrategy

但至少從那裏我看到的是,你的NullPointerException嘗試添加printStackTrace看看你打印什麼。 don't just ignore them

+0

BufferStrategy中是類,允許的多緩衝中的JFrame getBufferStrategy是JFrame中方法,以允許你得到BufferStrategy中(假設你創建了一個)的特定JFrame的,然後getDrawGraphics後讓您得到圖形對象,具有相關聯的該BufferStrategy(或至少,這是我對其原始的理解) NullPointerException發生B/C的關於在髒區域繪畫 任何想法我怎麼能解決這個問題 – resotpvl 2010-01-14 20:03:52

+0

你是如何回答這個問題兩次? – 2013-12-30 09:17:59

+0

@koray我剛剛做了,可能這不再可能,但3年前它是 – OscarRyz 2013-12-30 18:39:39

0

代碼中有一堆錯誤。 Numero uno是你不應該重寫JFrame的paint()方法。相反,您應該創建一些JComponent,然後將其組件添加到您的JFrame的contentPane中,然後執行它的paintComponent方法,然後執行add()

編輯:奧斯卡的評論也很好!

+0

的確,實際上,您不應該將JFrame繼承到第一位!你的代碼並不是一個真正的JFrame子類,你只是在使用它。 – OscarRyz 2010-01-12 02:09:07