2014-01-27 90 views
0

我正在使用Java中的簡單繪圖板工作,並且我有幾個用戶可以使用的工具:鋼筆和橡皮擦。但用於選擇工具的JComboBox不會出現,即使已添加。我聽說定製的油漆會掩蓋任何JComponents。如果這是真的,我怎樣才能使JComboBox始終位於頂端?爲什麼我的JComboBox沒有畫在我的圖畫上?

圖片窗口:

picture of bugged window

這裏是我的代碼:

import java.awt.Color; 
import java.awt.FlowLayout; 
import java.awt.Graphics; 
import java.awt.Image; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseMotionListener; 
import java.util.ArrayList; 

import javax.swing.JComboBox; 
import javax.swing.JFrame; 


public class DrawFrame extends JFrame implements MouseMotionListener, Runnable { 
    private static final long serialVersionUID = 1L; 

    private Image dbi; 
    private Graphics dbg; 

    ArrayList<Integer> px = new ArrayList<Integer>(); 
    ArrayList<Integer> py = new ArrayList<Integer>(); 

    int mx; 
    int my; 

    @SuppressWarnings("rawtypes") 
    JComboBox tool = new JComboBox(); 

    @SuppressWarnings("unchecked") 
    public DrawFrame() { 

     setSize(480, 480); 
     setTitle("ScratchPad _14"); 
     setLayout(new FlowLayout()); 
     setDefaultCloseOperation(EXIT_ON_CLOSE); 
     setResizable(false); 
     setBackground(Color.WHITE); 
     setOpacity(1); 

     tool.addItem("Pen"); 
     tool.addItem("Eraser"); 

     tool.setEnabled(true); 

     add(tool); 

     setVisible(true); 

     addMouseMotionListener(this); 

    } 

    /*@Override 
    public void mouseClicked(MouseEvent arg0) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void mouseEntered(MouseEvent arg0) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void mouseExited(MouseEvent arg0) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void mousePressed(MouseEvent arg0) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void mouseReleased(MouseEvent arg0) { 
     // TODO Auto-generated method stub 

    }*/ 

    public static void main(String[] args) { 
     // TODO Auto-generated method stub 

     DrawFrame df = new DrawFrame(); 
     Thread t = new Thread(df); 

     t.start(); 

    } 

    public void paint(Graphics g) { 

     dbi = createImage(getWidth(), getHeight()); 
     dbg = dbi.getGraphics(); 
     draw(dbg); 
     g.drawImage(dbi, 0, 0, null); 

    } 

    private void draw(Graphics g) { 
     // TODO Auto-generated method stub 

     super.paint(g); 

     g.setColor(getBackground()); 
     g.fillRect(0, 0, getWidth(), getHeight()); 

     g.setColor(Color.BLACK); 
     for (int i = 0; i < px.size(); i++) { 

      g.fillOval(px.get(i), py.get(i), 3, 3); 

     } 

     g.setColor(Color.BLUE); 
     g.drawString("(" + mx + ", " + my + ")", mx + 10, my - 5); 

     repaint(); 

    } 

    @Override 
    public void run() { 
     // TODO Auto-generated method stub 

     while(true) { 

      try { 
       Thread.sleep(5); 
      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 

     } 

    } 

    @Override 
    public void mouseDragged(MouseEvent m) { 
     // TODO Auto-generated method stub 

     int x = m.getX(); 
     int y = m.getY(); 

     mx = x; 
     my = y; 

     px.add(x); 
     py.add(y); 

    } 

    @Override 
    public void mouseMoved(MouseEvent m) { 
     // TODO Auto-generated method stub 

     int x = m.getX(); 
     int y = m.getY(); 

     mx = x; 
     my = y; 

    } 

} 

提前感謝!

回答

2

因爲你叫super.paint,其中描繪的子組件,除其他事項外

super.paint(g); 

然後你充滿使用背景顏色在整個框架...

g.setColor(getBackground()); 
g.fillRect(0, 0, getWidth(), getHeight()); 

擦除是被漆成在它之前...

您應該避免重寫頂級容器paint,如JFrame,除了你在框架裝飾下繪畫的事實,而且它不是雙重緩衝的,這些容器實際上是由一些可以產生最終輸出的複合組件構成的。

取而代之,創建一個自定義組件,從JPanel之類的東西延伸,並覆蓋它的paintComponent方法。將您的自定義繪畫放在這裏

組合框和自定義烤漆面板添加到幀分別

另外,不要從任何paint方法任何可能產生重繪事件(如呼叫repaint),這將建立一個無限循環這將快速消耗你的CPU

看看Performing Custom Painting更多細節

+0

刪除'super.paint(g)'不會顯示任何內容。而框架是雙重緩衝的。 –

+0

永遠不要停止調用super.paint,這不是問題。問題是,'super.paint'繪製了子組件,但是然後你畫了它們,是的,你已經對框架進行了雙重緩衝,但是猜測是什麼,JComponent是雙重緩衝的默認值,讓你不必自己做這件事。一個JFrame由一個JRootPane,JLayeredPane,內容窗格和玻璃窗格組成,並且您剛剛繪製過很多內容。如果你想解決問題,分開你的自定義繪畫和組件 – MadProgrammer

+0

在eclipse中,不是手動雙緩衝會導致繪圖閃爍,屏幕上的項目太多。 –

0

一般情況下,一個通常應該覆蓋JFrame的paint方法。相反,您應該擴展JPanel,並在重寫的paintComponent方法中繪製。

class PaintPanel extends JPanel 
{ 
    public PaintPanel() 
    { 
     setOpaque(false); 
    } 

    @Override 
    protected void paintComponent(Graphics g) 
    { 
     // Paint what you have been painting 
     // in your "draw" method ... 
     ... 
     super.paintComponent(g); 
    } 
} 

通常情況下,super.paintComponent(g)調用應該是這樣的覆蓋方法的第一個呼叫,但因爲你想畫上面,你對你自己的油漆一切組合框,它必須是最後一個。

其他問題:

  • 那是什麼主題呢?
  • 你爲什麼要做手動雙緩衝?
  • 如果你想手動雙緩衝,你不應該重新創建每個油漆通話

略清理,而不是「好」,但,但圖像...至少:

import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.GridLayout; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseMotionListener; 
import java.util.ArrayList; 

import javax.swing.JComboBox; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 


public class DrawFrame extends JFrame implements MouseMotionListener { 
    private static final long serialVersionUID = 1L; 

    ArrayList<Integer> px = new ArrayList<Integer>(); 
    ArrayList<Integer> py = new ArrayList<Integer>(); 

    int mx; 
    int my; 

    @SuppressWarnings("rawtypes") 
    JComboBox tool = new JComboBox(); 

    @SuppressWarnings("unchecked") 
    public DrawFrame() { 

     setSize(480, 480); 
     setTitle("ScratchPad _14"); 
     setLayout(new GridLayout(1,1)); 
     setDefaultCloseOperation(EXIT_ON_CLOSE); 
     setResizable(false); 
     setBackground(Color.WHITE); 
     setOpacity(1); 

     tool.addItem("Pen"); 
     tool.addItem("Eraser"); 

     tool.setEnabled(true); 

     JPanel paintPanel = new PaintPanel(); 
     paintPanel.add(tool); 
     add(paintPanel); 

     setVisible(true); 

     paintPanel.addMouseMotionListener(this); 

    } 
    public static void main(String[] args) { 
     DrawFrame df = new DrawFrame(); 
    } 

    class PaintPanel extends JPanel 
    { 
     public PaintPanel() 
     { 
      setOpaque(false); 
     } 

     @Override 
     protected void paintComponent(Graphics g) 
     { 
      g.setColor(getBackground()); 
      g.fillRect(0, 0, getWidth(), getHeight()); 

      g.setColor(Color.BLACK); 
      for (int i = 0; i < px.size(); i++) { 
       g.fillOval(px.get(i), py.get(i), 3, 3); 
      } 
      g.setColor(Color.BLUE); 
      g.drawString("(" + mx + ", " + my + ")", mx + 10, my - 5); 
      super.paintComponent(g); 
     } 
    } 

    @Override 
    public void mouseDragged(MouseEvent m) { 
     int x = m.getX(); 
     int y = m.getY(); 

     mx = x; 
     my = y; 

     px.add(x); 
     py.add(y); 

     repaint(); 
    } 

    @Override 
    public void mouseMoved(MouseEvent m) { 
     int x = m.getX(); 
     int y = m.getY(); 

     mx = x; 
     my = y; 

    } 

} 
+0

線程和雙緩衝可防止幀允許屏幕上的自定義繪製項目在幀之間閃爍。 –

+0

清理後的代碼是否會導致閃爍? Swing組件默認是雙緩衝的,但是覆蓋JFrame的'paint'當然會破壞所有東西...... – Marco13

+0

因爲我確實這樣做了,所以這可能是@Galen Nare(原始海報) – Marco13

0

該繪圖不應該調用repaint。我已經在mouseDragged中做了這個,延遲了50毫秒。 然後,雙緩衝是默認設置,因此您不會首先收集圖像中的所有更改。 擦除也完成了一個。

因此,代碼變爲:

@Override 
public void paint(Graphics g) { 
    super.paint(g); 
    g.setColor(Color.BLACK); 
    for (int i = 0; i < px.size(); i++) { 
     g.fillOval(px.get(i), py.get(i), 3, 3); 
    } 

    g.setColor(Color.BLUE); 
    g.drawString("(" + mx + ", " + my + ")", mx + 10, my - 5); 
} 

@Override 
public void mouseDragged(MouseEvent m) { 
    ... 
    repaint(50L); 
} 

通常一個介紹一個JPanel繪畫,其中有一個paintComponent覆蓋。

+0

不調用repaint使其跳過幀。 –

+0

@GalenNare然後在mouseMoved中添加一個重繪。這個想法是,如果沒有改變顯示,不要調用重繪。請檢查任務管理器在兩種情況下的CPU使用情況。 –

相關問題