2012-11-25 82 views
1

有人可以解釋爲什麼當我將鼠標懸停在他們應該在的位置時,我的組件只能被繪製嗎?組件只能在盤旋時繪製

我設置了一個無邊界的框架,可以在任何地方拖動,我試圖在右上角創建一個退出按鈕,但直到我將鼠標懸停在它上面時纔會繪製出來。我爲JFrame繪製一幅背景圖像,然後繪製我的按鈕並將整個東西設置爲可見。

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

public class GUI extends JFrame 
{ 
    private Image Background = null; 
    private static Point Offset = new Point(); 

    public GUI() { 
     this.setUndecorated(true); 
     this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
     AddListeners(); 
     SetCustomTheme(); 
     LoadBackground(); 
     Layout(); 
     pack(); 
     this.setSize(300, 300); 
     this.setVisible(true); 
    } 

    private void Layout() { 
     GroupLayout Info = new GroupLayout(this.getContentPane()); 
     this.getContentPane().setLayout(Info); 
     JButton Button = new JButton(); 

     Info.setHorizontalGroup(
      Info.createSequentialGroup() 
       .addComponent(Button) 
     ); 

     Info.setVerticalGroup(
      Info.createParallelGroup() 
       .addComponent(Button) 
     ); 
    } 

    private void SetCustomTheme() { 
     try { 
      UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel"); 
     } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
     } 
    } 

    private void LoadBackground() { 
     try { 
      Background = ImageIO.read(getClass().getResource("Images/meh.png")); 
     } catch (Exception Ex) { 

     } 
    } 

    private void SetCustomIcon() { 
     Image Icon = Toolkit.getDefaultToolkit().getImage("Images/lol.jpg"); 
     setIconImage(Icon); 
    } 

    private void AddListeners() { 
     this.addMouseListener(new MouseAdapter() { 
      @Override public void mousePressed(MouseEvent e) { 
       Offset.x = e.getX(); 
       Offset.y = e.getY(); 
      } 
      }); 

     this.addMouseMotionListener(new MouseMotionAdapter() { 
      @Override public void mouseDragged(MouseEvent e) { 
       Point p = getLocation(); 
       setLocation(p.x + e.getX() - Offset.x, p.y + e.getY() - Offset.y); 
      } 
      }); 
    } 

    @Override public void paint(Graphics g) { 
     g.drawImage(Background, 0,0,this.getWidth(),this.getHeight(), null); 
    } 
} 

回答

3
  1. 與UI交互必須從事件指派線程
  2. 您應該避免從頂層容器延伸,像JFrame,而是使用JPanel代替內執行。
  3. 未能兌現paint鏈契約是防止從開始畫
  4. 覆蓋執行風俗畫的首選方法,任子組件被paintComponent

你可能想通過

嘗試類似這樣的事情;

public class BadPaint01 { 

    public static void main(String[] args) { 
     new BadPaint01(); 
    } 

    public BadPaint01() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
       } 

       JFrame frame = new JFrame(); 
       Image Icon = Toolkit.getDefaultToolkit().getImage("Images/lol.jpg"); 
       frame.setIconImage(Icon); 
       frame.setUndecorated(true); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(new GUI()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public static class GUI extends JPanel { 

     private Image Background = null; 
     private static Point Offset = new Point(); 

     public GUI() { 
      AddListeners(); 
      SetCustomTheme(); 
      LoadBackground(); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(300, 300); 
     } 

     private void Layout() { 
      GroupLayout Info = new GroupLayout(this); 
      setLayout(Info); 
      JButton Button = new JButton(); 

      Info.setHorizontalGroup(
        Info.createSequentialGroup() 
        .addComponent(Button)); 

      Info.setVerticalGroup(
        Info.createParallelGroup() 
        .addComponent(Button)); 
     } 

     private void SetCustomTheme() { 
      try { 
       UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel"); 
      } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
      } 
     } 

     private void LoadBackground() { 
      try { 
       Background = ImageIO.read(getClass().getResource("Images/meh.png")); 
      } catch (Exception Ex) { 
      } 
     } 

     private void AddListeners() { 
      this.addMouseListener(new MouseAdapter() { 
       @Override 
       public void mousePressed(MouseEvent e) { 
        Offset.x = e.getX(); 
        Offset.y = e.getY(); 
       } 
      }); 

      this.addMouseMotionListener(new MouseMotionAdapter() { 
       @Override 
       public void mouseDragged(MouseEvent e) { 
        Point p = getLocation(); 
        setLocation(p.x + e.getX() - Offset.x, p.y + e.getY() - Offset.y); 
       } 
      }); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); //To change body of generated methods, choose Tools | Templates. 
      g.drawImage(Background, 0, 0, this.getWidth(), this.getHeight(), null); 
     } 
    } 
} 

您也可能想通過Code Conventions for the Java Programming Language已閱讀,你不會無視他們交朋友;)

+0

那麼爲什麼Netbeans從JFrame而不是JPanel擴展? :S – Brandon

+0

因爲這不是一個無效的操作,只是一個不好的建議。有時候你可能想爲JFrame添加額外的功能,但是在你的情況下你並沒有增加任何價值。另外,在頂層容器上繪畫是一個壞主意,因爲1-它們不是雙緩衝的,2-幀的頂部有一個「JRootPane」,它包含內容窗格,所以任何繪畫都要完成在你的情況下,在你的情況下是不可取的,因爲根窗格會隱藏你的工作(如果你實際上正確地使用了繪製機制。) – MadProgrammer

+0

Java將允許你從任何線程更新UI組件,但是這被認爲是不好的做法,開發者和API之間有一個理解合同,而你可以打破這個合同,期望事情真的很快變成梨形。 – MadProgrammer

1

如果我記得很清楚,ToolKit.getImage返回Image這可能無法完全裝入。當你將鼠標懸停在它上面時,它可能已經在後臺加載。 而是做到這一點(類似你行背景):

ImageIcon Icon = new ImageIcon(ImageIO.read(getClass().getResource("Images/lol.png"))); 
setIconImage(Icon); 

(爲了更好地理解你可能想搜索MediaTracker,我相信是用來確保,該圖像是完全加載)