2012-01-17 40 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