2012-01-17 37 views
3

我有這個問題困擾了我好幾天。我正在製作一個特殊的繪畫程序。我製作了一個JPanel,並添加了使用paint(..)方法繪製的自定義jComponents。 問題是,無論何時調整窗口大小,所有添加的組件都「消失」(或者只是不畫),所以我最終得到了一個空框架。調整添加的塗漆組件和奇怪的揮杆行爲

另外我注意到使用這種方法時擺動的一些奇怪的行爲。我已經向描述這個問題的代碼添加了評論。

package simple; 

import java.awt.*; 
import java.awt.event.*; 
import java.util.ArrayList; 

import javax.swing.*; 

public class SimpleFrame extends JFrame { 
    JPanel paintArea; 
    SimpleCanvas c1; 
    SimpleCanvas c2; 
    ArrayList<SimpleCanvas> list; 

    public static void main(String[] args) { 
     SimpleFrame frame = new SimpleFrame(); 

    } 

    public SimpleFrame() { 
     super("Test"); 
     setSize(600,500); 
     setDefaultCloseOperation(EXIT_ON_CLOSE); 

     //The panel to which my SimpleCanvas objects are added 
     paintArea = new JPanel(); 
     paintArea.setPreferredSize(new Dimension(600, 500)); 
     paintArea.addMouseListener(new paintAreaMouseEvents()); 
     getContentPane().add(paintArea, BorderLayout.CENTER); 

     setVisible(true); 
     paintArea.setVisible(true); 

     //A list to hold all the objects together 
     list = new ArrayList<SimpleCanvas>(10); 

     //The same as in class paintAreaMouseEvent, but doesnt work 
     SimpleCanvas c = new SimpleCanvas(); 
     c.setBounds(60, 100, 100, 50); 
     list.add(c); 
     paintArea.add(list.get(list.size() - 1)); 
     paintArea.repaint(); 
    } 
    //When you click the mouse, it makes an oval 
    class paintAreaMouseEvents extends MouseAdapter { 
     @Override 
     //This does work. 
     public void mouseClicked (MouseEvent me) { 
      SimpleCanvas c = new SimpleCanvas(); 
      c.setBounds(me.getX() - 50, me.getY() - 25, 100, 50); 

      list.add(c); 
      paintArea.add(list.get(list.size() - 1)); 
      paintArea.repaint(); 
     } 
    } 
} 

這裏是SimpleCanvas類

package simple; 

import java.awt.*; 

import javax.swing.JComponent; 

public class SimpleCanvas extends JComponent { 
    public void paint(Graphics g) { 
     super.paint(g); 
     g.setColor(Color.BLUE); 
     g.fillOval(0, 0, 100, 50); 
    } 
} 

謝謝:)

BTW:只想說這個網站是驚人的。我在使用Google的時候來過很多地方,現在我終於決定寫一個賬戶。

回答

6

你的問題是佈局問題。將您的JComponent的paint方法添加到:

System.out.println(getSize()); 

以查看調整GUI大小時會發生的情況。

這是因爲調整大小調用佈局管理器操作。

要解決此問題,請不要使用setBounds(...)來確定組件大小,而是使用佈局管理器。如果您希望佈局管理器尊重它的特定大小,也可以重寫您的JComponent的getPreferredSize方法。最後,不要使用paint方法而是使用paintComponent方法進行繪製。教程將解釋原因。

另外,如果你絕對需要使用絕對定位來定位的東西,然後將容器必須使用空佈局:

// The panel to which my SimpleCanvas objects are added 
    paintArea = new JPanel(null); 

編輯
如果我做這樣你的程序的東西上面,我m不知道我是否將新組件添加到JPanel中,而只是讓圖形JPanel擁有一個Shapes列表,然後使用for循環在其paintComponent方法中繪製形狀。例如:

import java.awt.BasicStroke; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.RenderingHints; 
import java.awt.Shape; 
import java.awt.Stroke; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.geom.Ellipse2D; 
import java.util.ArrayList; 
import java.util.List; 

import javax.swing.*; 

public class SimpleFrame2 extends JPanel { 
    private static final Color ELLIPSE_COLOR = Color.LIGHT_GRAY; 
    private static final Color ELLIPSE_FILL_COLOR = Color.blue; 
    private static final int PREF_W = 600; 
    private static final int PREF_H = 500; 
    public static final int ELLIPSE_WIDTH = 100; 
    public static final int ELLIPSE_HEIGHT = 50; 
    private static final Stroke ELLIPSE_STROKE = new BasicStroke(2f); 
    private List<Shape> shapes = new ArrayList<Shape>(); 

    public SimpleFrame2() { 
     addMouseListener(new MouseAdapter() { 
     @Override 
     public void mousePressed(MouseEvent mEvt) { 
      double x = mEvt.getX() - ELLIPSE_WIDTH/2; 
      double y = mEvt.getY() - ELLIPSE_HEIGHT/2; 
      double w = ELLIPSE_WIDTH; 
      double h = ELLIPSE_HEIGHT; 
      shapes.add(new Ellipse2D.Double(x, y, w, h)); 
      repaint(); 
     } 
     }); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D g2 = (Graphics2D) g; 
     // to draw smooth edges 
     g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
      RenderingHints.VALUE_ANTIALIAS_ON); 
     g2.setStroke(ELLIPSE_STROKE); 
     for (Shape shape : shapes) { 
     g2.setColor(ELLIPSE_FILL_COLOR); 
     g2.fill(shape); 
     g2.setColor(ELLIPSE_COLOR); 
     g2.draw(shape); 
     } 
    } 

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

    private static void createAndShowGui() { 
     JFrame frame = new JFrame("SimpleFrame2"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(new SimpleFrame2()); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGui(); 
     } 
     }); 
    } 
} 

編輯2
與形狀

拖着
import java.awt.BasicStroke; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Point; 
import java.awt.Rectangle; 
import java.awt.RenderingHints; 
import java.awt.Stroke; 
import java.awt.event.*; 
import java.awt.geom.*; 
import java.util.ArrayList; 
import java.util.List; 
import javax.swing.*; 

@SuppressWarnings("serial") 
public class SimpleFrame3 extends JPanel { 
    private static final Color ELLIPSE_COLOR = Color.LIGHT_GRAY; 
    private static final Color ELLIPSE_FILL_COLOR = Color.blue; 
    private static final int PREF_W = 600; 
    private static final int PREF_H = 500; 
    public static final int ELLIPSE_WIDTH = 100; 
    public static final int ELLIPSE_HEIGHT = 50; 
    private static final Stroke ELLIPSE_STROKE = new BasicStroke(2f); 
    private List<RectangularShape> rects = new ArrayList<RectangularShape>(); 

    public SimpleFrame3() { 
     MyMouseAdapter myMouseAdapter = new MyMouseAdapter(); 
     addMouseListener(myMouseAdapter); 
     addMouseMotionListener(myMouseAdapter); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D g2 = (Graphics2D) g; 
     // to draw smooth edges 
     g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
      RenderingHints.VALUE_ANTIALIAS_ON); 
     g2.setStroke(ELLIPSE_STROKE); 
     for (RectangularShape rect : rects) { 
     g2.setColor(ELLIPSE_FILL_COLOR); 
     g2.fill(rect); 
     g2.setColor(ELLIPSE_COLOR); 
     g2.draw(rect); 
     } 
    } 

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

    class MyMouseAdapter extends MouseAdapter { 
     private RectangularShape selectedRect = null; 
     private Point deltaPt = null; 

     @Override 
     public void mousePressed(MouseEvent mEvt) { 
     if (mEvt.getButton() != MouseEvent.BUTTON1) { 
      return; 
     } 

     if (rects.size() > 0) { 
      for (int i = rects.size() - 1; i >= 0; i--) { 
       if (rects.get(i).contains(mEvt.getPoint())) { 
        selectedRect = rects.get(i); 
        rects.remove(selectedRect); 
        rects.add(rects.size(), selectedRect); 
        deltaPt = new Point(mEvt.getX() - selectedRect.getBounds().x, 
         mEvt.getY() - selectedRect.getBounds().y); 
        repaint(); 
        return; 
       } 
      } 
     } 
     double x = mEvt.getX() - ELLIPSE_WIDTH/2; 
     double y = mEvt.getY() - ELLIPSE_HEIGHT/2; 
     double w = ELLIPSE_WIDTH; 
     double h = ELLIPSE_HEIGHT; 
     Ellipse2D ellipse = new Ellipse2D.Double(x, y, w, h); 
     rects.add(ellipse); 
     selectedRect = ellipse; 
     deltaPt = new Point((int)(mEvt.getX() - x), (int)(mEvt.getY() - y)); 
     repaint(); 
     } 

     @Override 
     public void mouseDragged(MouseEvent e) { 
     if (selectedRect != null) { 
      Rectangle bounds = selectedRect.getBounds(); 
      bounds.setLocation(e.getX() - deltaPt.x, e.getY() - deltaPt.y); 
      selectedRect.setFrame(bounds.x, bounds.y, bounds.width, bounds.height); 
      repaint(); 
     } 
     } 

     @Override 
     public void mouseReleased(MouseEvent e) { 
     if (selectedRect != null) { 
      repaint(); 
      selectedRect = null; 
     } 
     } 
    } 

    private static void createAndShowGui() { 
     JFrame frame = new JFrame("SimpleFrame3"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(new SimpleFrame3()); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGui(); 
     } 
     }); 
    } 
} 
+0

非常感謝您!我向jPanel的構造函數中添加了null參數,並解決了我所有的問題。 我想我現在必須學習如何使用LayoutManagers;) 再次,謝謝。 – Charnia 2012-01-17 20:22:37

+0

@Charnia:不客氣。請參閱我的答案的附錄。 – 2012-01-17 22:39:57

+0

感謝您的提示,我一定會牢記在心。問題是我正在編寫一個程序,該程序還允許您通過將另一個mouseEventHandler添加到自定義Canvas類來移動這些形狀,因此您建議的方法將無法工作。 – Charnia 2012-01-18 18:20:11