2013-05-19 42 views
0

我試圖創建一個定製JButton。我試圖通過paintComponent方法繪製它的標題,但我不喜歡這種方法的字體渲染。所以我添加了一個JLabel到我的按鈕,它在第一個地方工作得很好,但是在刪除了paintString的東西之後,編譯器會拋出錯誤,我不知道如何修復/解決。另外我可以改進什麼?在java中定製JButton中的未知異常(swing)

這些Jbutton代碼:

import javax.swing.*; 
import java.awt.*; 
import java.awt.event.*; 
import java.awt.geom.Rectangle2D; 

class myImageButton extends JButton implements MouseListener { 

    private Color fontColor = new Color(0x222); 

    private Image btn = Toolkit.getDefaultToolkit().getImage("btn.png"); 
    private Image btnHvr = Toolkit.getDefaultToolkit().getImage("btnhvr.png"); 
    private Image btnDwn = Toolkit.getDefaultToolkit().getImage("btndwn.png"); 
    private Image fallback = btn; 
    private Image currentImage = btn; 

    private JFrame parent; 
    private JLabel label; 

    private boolean mouseDown = false; 
    private int captionWidth; 
    private int captionHeight; 
    private Font font = new Font("Open Sans", Font.PLAIN, 12); 
    private FontMetrics fm = new FontMetrics(font) { }; 

    myImageButton(String text, JFrame parent) { 
    parent = parent; 
    Rectangle2D bounds = fm.getStringBounds(text, null); 
    captionWidth = (int) bounds.getWidth(); 
    captionHeight = (int) bounds.getHeight(); 
    addMouseListener(this); 
    setBounds(0,0,79,28); 
    setFont(font); 
    label = new JLabel(text); 
    this.add(label); 
    } 

    public void paintComponent(Graphics g) { 
    g.setColor(parent.getBackground()); 
    g.fillRect(0,0,getWidth(),getHeight()); 
    g.drawImage(currentImage,0,0,parent); 
    //g.setColor(fontColor); 
    //g.drawString(caption, getWidth()/2 - captionWidth/2, getHeight()/2 + captionHeight/3); 
    } 

    public void paintBorder(Graphics g) { 
    } 

    public void mousePressed(MouseEvent e) { 
    //mouse down 
    currentImage = btnDwn; 
    mouseDown = true; 
    repaint(); 
    } 

    public void mouseReleased(MouseEvent e) { 
    //mouse up 
    currentImage = btnHvr; 
    mouseDown = false; 
    repaint(); 
    } 

    public void mouseEntered(MouseEvent e) { 
    //hover on 
    if (mouseDown) { 
     currentImage = btnDwn; 
    } else { 
     currentImage = btnHvr; 
    } 
    repaint(); 
    } 

    public void mouseExited(MouseEvent e) { 
    //hover off 
    if (mouseDown) { 
     currentImage = btnDwn; 
    } else { 
     currentImage = btn; 
    } 
    repaint(); 
    } 

    public void mouseClicked(MouseEvent e) { 
    //click 
    //should be managed by parent UI class 
    } 

} 

的JFrames代碼:

import javax.swing.*; 
import java.awt.*; 
import java.awt.event.*; 

public class Launch { 
    public static void main (String[]args) { 
    JFrame jf = new JFrame(); 
    myImageButton cp = new myImageButton("Exit", jf); 
    jf.setLayout(null); 
    jf.setSize(640,480); 
    jf.setResizable(false); 

    jf.setLocationRelativeTo(null); 

    jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    jf.add(cp); 
    cp.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent evt) { 
     myImageButton_ActionPerformed(evt); 
     } 
    }); 
    cp.setLocation(50,50); 
    jf.setVisible(true); 
    } 

    public static void myImageButton_ActionPerformed(ActionEvent evt) { 
    System.out.println("Click"); 
    } 
} 

完整的異常堆棧跟蹤:

Starte C:\Users\Selim\Desktop\Launch.java 

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException 
    at myImageButton.paintComponent(myImageButton.java:38) 
    at javax.swing.JComponent.paint(Unknown Source) 
    at javax.swing.JComponent.paintChildren(Unknown Source) 
    at javax.swing.JComponent.paint(Unknown Source) 
    at javax.swing.JComponent.paintChildren(Unknown Source) 
    at javax.swing.JComponent.paint(Unknown Source) 
    at javax.swing.JLayeredPane.paint(Unknown Source) 
    at javax.swing.JComponent.paintChildren(Unknown Source) 
    at javax.swing.JComponent.paintToOffscreen(Unknown Source) 
    at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source) 
    at javax.swing.RepaintManager$PaintManager.paint(Unknown Source) 
    at javax.swing.RepaintManager.paint(Unknown Source) 
    at javax.swing.JComponent.paint(Unknown Source) 
    at java.awt.GraphicsCallback$PaintCallback.run(Unknown Source) 
    at sun.awt.SunGraphicsCallback.runOneComponent(Unknown Source) 
    at sun.awt.SunGraphicsCallback.runComponents(Unknown Source) 
    at java.awt.Container.paint(Unknown Source) 
    at java.awt.Window.paint(Unknown Source) 
    at javax.swing.RepaintManager$3.run(Unknown Source) 
    at javax.swing.RepaintManager$3.run(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source) 
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source) 
    at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source) 
    at javax.swing.RepaintManager.access$1000(Unknown Source) 
    at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source) 
    at java.awt.event.InvocationEvent.dispatch(Unknown Source) 
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source) 
    at java.awt.EventQueue.access$200(Unknown Source) 
    at java.awt.EventQueue$3.run(Unknown Source) 
    at java.awt.EventQueue$3.run(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
    at java.awt.EventQueue.dispatchEvent(Unknown Source) 
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 
    at java.awt.EventDispatchThread.run(Unknown Source) 
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException 
    at myImageButton.paintComponent(myImageButton.java:38) 
    at javax.swing.JComponent.paint(Unknown Source) 
    at javax.swing.JComponent.paintChildren(Unknown Source) 
    at javax.swing.JComponent.paint(Unknown Source) 
    at javax.swing.JComponent.paintChildren(Unknown Source) 
    at javax.swing.JComponent.paint(Unknown Source) 
    at javax.swing.JLayeredPane.paint(Unknown Source) 
    at javax.swing.JComponent.paintChildren(Unknown Source) 
    at javax.swing.JComponent.paintToOffscreen(Unknown Source) 
    at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source) 
    at javax.swing.RepaintManager$PaintManager.paint(Unknown Source) 
    at javax.swing.RepaintManager.paint(Unknown Source) 
    at javax.swing.JComponent.paint(Unknown Source) 
    at java.awt.GraphicsCallback$PaintCallback.run(Unknown Source) 
    at sun.awt.SunGraphicsCallback.runOneComponent(Unknown Source) 
    at sun.awt.SunGraphicsCallback.runComponents(Unknown Source) 
    at java.awt.Container.paint(Unknown Source) 
    at java.awt.Window.paint(Unknown Source) 
    at javax.swing.RepaintManager$3.run(Unknown Source) 
    at javax.swing.RepaintManager$3.run(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source) 
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source) 
    at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source) 
    at javax.swing.RepaintManager.access$1000(Unknown Source) 
    at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source) 
    at java.awt.event.InvocationEvent.dispatch(Unknown Source) 
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source) 
    at java.awt.EventQueue.access$200(Unknown Source) 
    at java.awt.EventQueue$3.run(Unknown Source) 
    at java.awt.EventQueue$3.run(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
    at java.awt.EventQueue.dispatchEvent(Unknown Source) 
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 
    at java.awt.EventDispatchThread.run(Unknown Source) 
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException 
    at myImageButton.paintComponent(myImageButton.java:38) 
    at javax.swing.JComponent.paint(Unknown Source) 
    at javax.swing.JComponent.paintChildren(Unknown Source) 
    at javax.swing.JComponent.paint(Unknown Source) 
    at javax.swing.JComponent.paintChildren(Unknown Source) 
    at javax.swing.JComponent.paint(Unknown Source) 
    at javax.swing.JLayeredPane.paint(Unknown Source) 
    at javax.swing.JComponent.paintChildren(Unknown Source) 
    at javax.swing.JComponent.paintToOffscreen(Unknown Source) 
    at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source) 
    at javax.swing.RepaintManager$PaintManager.paint(Unknown Source) 
    at javax.swing.RepaintManager.paint(Unknown Source) 
    at javax.swing.JComponent.paint(Unknown Source) 
    at java.awt.GraphicsCallback$PaintCallback.run(Unknown Source) 
    at sun.awt.SunGraphicsCallback.runOneComponent(Unknown Source) 
    at sun.awt.SunGraphicsCallback.runComponents(Unknown Source) 
    at java.awt.Container.paint(Unknown Source) 
    at java.awt.Window.paint(Unknown Source) 
    at javax.swing.RepaintManager$3.run(Unknown Source) 
    at javax.swing.RepaintManager$3.run(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source) 
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source) 
    at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source) 
    at javax.swing.RepaintManager.access$1000(Unknown Source) 
    at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source) 
    at java.awt.event.InvocationEvent.dispatch(Unknown Source) 
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source) 
    at java.awt.EventQueue.access$200(Unknown Source) 
    at java.awt.EventQueue$3.run(Unknown Source) 
    at java.awt.EventQueue$3.run(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
    at java.awt.EventQueue.dispatchEvent(Unknown Source) 
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 
    at java.awt.EventDispatchThread.run(Unknown Source) 
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException 
    at myImageButton.paintComponent(myImageButton.java:38) 
    at javax.swing.JComponent.paint(Unknown Source) 
    at javax.swing.JComponent.paintToOffscreen(Unknown Source) 
    at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source) 
    at javax.swing.RepaintManager$PaintManager.paint(Unknown Source) 
    at javax.swing.RepaintManager.paint(Unknown Source) 
    at javax.swing.JComponent._paintImmediately(Unknown Source) 
    at javax.swing.JComponent.paintImmediately(Unknown Source) 
    at javax.swing.RepaintManager$3.run(Unknown Source) 
    at javax.swing.RepaintManager$3.run(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source) 
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source) 
    at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source) 
    at javax.swing.RepaintManager.access$1000(Unknown Source) 
    at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source) 
    at java.awt.event.InvocationEvent.dispatch(Unknown Source) 
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source) 
    at java.awt.EventQueue.access$200(Unknown Source) 
    at java.awt.EventQueue$3.run(Unknown Source) 
    at java.awt.EventQueue$3.run(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
    at java.awt.EventQueue.dispatchEvent(Unknown Source) 
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 
    at java.awt.EventDispatchThread.run(Unknown Source) 
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException 
    at myImageButton.paintComponent(myImageButton.java:38) 
    at javax.swing.JComponent.paint(Unknown Source) 
    at javax.swing.JComponent.paintToOffscreen(Unknown Source) 
    at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source) 
    at javax.swing.RepaintManager$PaintManager.paint(Unknown Source) 
    at javax.swing.RepaintManager.paint(Unknown Source) 
    at javax.swing.JComponent._paintImmediately(Unknown Source) 
    at javax.swing.JComponent.paintImmediately(Unknown Source) 
    at javax.swing.RepaintManager$3.run(Unknown Source) 
    at javax.swing.RepaintManager$3.run(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source) 
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source) 
    at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source) 
    at javax.swing.RepaintManager.access$1000(Unknown Source) 
    at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source) 
    at java.awt.event.InvocationEvent.dispatch(Unknown Source) 
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source) 
    at java.awt.EventQueue.access$200(Unknown Source) 
    at java.awt.EventQueue$3.run(Unknown Source) 
    at java.awt.EventQueue$3.run(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
    at java.awt.EventQueue.dispatchEvent(Unknown Source) 
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 
    at java.awt.EventDispatchThread.run(Unknown Source) 
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException 
    at myImageButton.paintComponent(myImageButton.java:38) 
    at javax.swing.JComponent.paint(Unknown Source) 
    at javax.swing.JComponent.paintToOffscreen(Unknown Source) 
    at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source) 
    at javax.swing.RepaintManager$PaintManager.paint(Unknown Source) 
    at javax.swing.RepaintManager.paint(Unknown Source) 
    at javax.swing.JComponent._paintImmediately(Unknown Source) 
    at javax.swing.JComponent.paintImmediately(Unknown Source) 
    at javax.swing.RepaintManager$3.run(Unknown Source) 
    at javax.swing.RepaintManager$3.run(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source) 
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source) 
    at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source) 
    at javax.swing.RepaintManager.access$1000(Unknown Source) 
    at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source) 
    at java.awt.event.InvocationEvent.dispatch(Unknown Source) 
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source) 
    at java.awt.EventQueue.access$200(Unknown Source) 
    at java.awt.EventQueue$3.run(Unknown Source) 
    at java.awt.EventQueue$3.run(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
    at java.awt.EventQueue.dispatchEvent(Unknown Source) 
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 
    at java.awt.EventDispatchThread.run(Unknown Source) 
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException 
    at myImageButton.paintComponent(myImageButton.java:38) 
    at javax.swing.JComponent.paint(Unknown Source) 
    at javax.swing.JComponent.paintToOffscreen(Unknown Source) 
    at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source) 
    at javax.swing.RepaintManager$PaintManager.paint(Unknown Source) 
    at javax.swing.RepaintManager.paint(Unknown Source) 
    at javax.swing.JComponent._paintImmediately(Unknown Source) 
    at javax.swing.JComponent.paintImmediately(Unknown Source) 
    at javax.swing.RepaintManager$3.run(Unknown Source) 
    at javax.swing.RepaintManager$3.run(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source) 
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source) 
    at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source) 
    at javax.swing.RepaintManager.access$1000(Unknown Source) 
    at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source) 
    at java.awt.event.InvocationEvent.dispatch(Unknown Source) 
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source) 
    at java.awt.EventQueue.access$200(Unknown Source) 
    at java.awt.EventQueue$3.run(Unknown Source) 
    at java.awt.EventQueue$3.run(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
    at java.awt.EventQueue.dispatchEvent(Unknown Source) 
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 
    at java.awt.EventDispatchThread.run(Unknown Source) 

在此先感謝!

塞利姆

+1

請勿將鏈接發佈到代碼請複製相關部分到您的問題。 – Maroun

+1

我對建議感謝 – Selim

+0

好的嵌套滾動條:D – Maroun

回答

2

的問題是這裏的myImageButton構造:

parent = parent; 

當地父JFrame參考分配給自己。隨後在paintComponent中,類成員變量parentnull產生NPE。你想

this.parent = parent; 

此外,我有什麼可以改善?

  • 不要使用null佈局,始終使用layout manager
  • JButton組件已經提供使用以下方法,通過自定義按鈕提供的功能:setBordersetPressedIconsetRollOverIcon
  • 關注的Java命名約定。上課的時間與大寫字母MyImageButton
+0

非常感謝你,我清理drawString的不必要的屬性時,必須意外刪除那部分。 – Selim

1

它看起來像你正試圖集中在按鈕圖標上的文字。該API處理此問題:

button.setHorizontalTextPosition(JButton.CENTER); 
button.setVerticalTextPosition(JButton.CENTER); 

API還處理不同的圖標。檢查方法名稱中帶有「圖標」的任何方法的API。

+0

嘿不幸的是,不工作,但ive找到了一個解決方案: setLayout(new BoxLayout(this,BoxLayout.X_AXIS)); this.add(Box.createHorizo​​ntalGlue()); this.add(label);
this.add(Box。createHorizo​​ntalGlue()); – Selim

+0

@Selim,我想你錯過了這一點。沒有必要創建一個自定義的JButton。按鈕將使用上述代碼將文本放置在圖標上。 – camickr

+0

如果您的意思是調用超類的setText(string s)方法:文本將不會以這種方式顯示 - 可能是因爲圖像 – Selim