Java 调整添加的绘制组件的大小和奇怪的摆动行为

Java 调整添加的绘制组件的大小和奇怪的摆动行为,java,swing,Java,Swing,这个问题困扰了我好几天。我正在制作一个特殊的绘画程序。我制作了一个JPanel,并添加了使用paint(..)方法绘制的定制jComponents。 问题是,每当我调整窗口大小时,所有添加的组件都会“消失”(或只是不绘制),因此我最终会得到一个空框架 在使用这种方法时,我还注意到一些奇怪的挥杆行为。我已经在描述这个问题的代码中添加了注释 package simple; import java.awt.*; import java.awt.event.*; import java.util.Ar

这个问题困扰了我好几天。我正在制作一个特殊的绘画程序。我制作了一个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();
        }
    }
}
谢谢:)


顺便说一句:我只是想说这个网站太棒了。我在使用谷歌时经常来这里,现在我终于决定建立一个帐户。

你的问题是布局问题。加:

System.out.println(getSize());
查看JComponent的绘制方法,以查看调整GUI大小时发生的情况

发生这种情况是因为“调整大小”正在调用布局管理器操作

要解决这个问题,不要使用
setBounds(…)
来调整组件的大小,而是使用布局管理器。如果希望布局管理器尊重JComponent的特定大小,还可以重写它的getPreferredSize方法。最后,不要使用
paint
方法进行绘制,而是使用
paintComponent
方法。教程将解释原因

此外,如果您绝对需要使用绝对定位来定位某些内容,则容器必须使用空布局:

  // The panel to which my SimpleCanvas objects are added
  paintArea = new JPanel(null);
编辑
如果我在做类似于上面的程序的事情,我不确定是否会向JPanel添加新组件,而是简单地让绘图JPanel保存一个形状列表,然后使用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();
         }
      });
   }
}
import java.awt.BasicStroke;
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.RenderingHints;
导入java.awt.Shape;
导入java.awt.Stroke;
导入java.awt.event.MouseAdapter;
导入java.awt.event.MouseEvent;
导入java.awt.geom.Ellipse2D;
导入java.util.ArrayList;
导入java.util.List;
导入javax.swing.*;
公共类SimpleFrame2扩展了JPanel{
私有静态最终颜色椭圆\u颜色=Color.LIGHT\u灰色;
私有静态最终颜色椭圆\填充\颜色=Color.blue;
专用静态最终整型预调W=600;
专用静态最终int PREF_H=500;
公共静态最终整数椭圆_宽度=100;
公共静态最终整数椭圆高度=50;
专用静态最终行程椭圆_行程=新基本行程(2f);
私有列表形状=新的ArrayList();
公共SimpleFrame2(){
addMouseListener(新的MouseAdapter(){
@凌驾
公共无效鼠标按下(MouseEvent mEvt){
double x=mEvt.getX()-椭圆宽度/2;
双y=mEvt.getY()-椭圆高度/2;
双w=椭圆宽度;
双h=椭圆高度;
添加(新的椭圆2d.Double(x,y,w,h));
重新油漆();
}
});
}
@凌驾
受保护组件(图形g){
超级组件(g);
图形2d g2=(图形2d)g;
//画光滑的边
g2.setRenderingHint(RenderingHints.KEY_抗锯齿,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.设定行程(椭圆_行程);
用于(形状:形状){
g2.设置颜色(椭圆填充颜色);
g2.填充(形状);
g2.设置颜色(椭圆颜色);
g2.绘制(形状);
}
}
@凌驾
公共维度getPreferredSize(){
返回新维度(PREF_W,PREF_H);
}
私有静态void createAndShowGui(){
JFrame=新的JFrame(“SimpleFrame2”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(新的SimpleFrame2());
frame.pack();
frame.setLocationRelativeTo(空);
frame.setVisible(true);
}
公共静态void main(字符串[]args){
SwingUtilities.invokeLater(新的Runnable(){
公开募捐{
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();
         }
      });
   }
}
import java.awt.BasicStroke;
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.Point;
导入java.awt.Rectangle;
导入java.awt.RenderingHints;
导入java.awt.Stroke;
导入java.awt.event.*;
导入java.awt.geom.*;
导入java.util.ArrayList;
导入java.util.List;
导入javax.swing.*;
@抑制警告(“串行”)
公共类SimpleFrame3扩展了JPanel{
私有静态最终颜色椭圆\u颜色=Color.LIGHT\u灰色;
私有静态最终颜色椭圆\填充\颜色=Color.blue;
专用静态最终整型预调W=600;
专用静态最终int PREF_H=500;
公共静态最终整数椭圆_宽度=100;
公共静态最终整数椭圆高度=50;
专用静态最终行程椭圆_行程=新基本行程(2f);
private List rects=new ArrayList();
公共SimpleFrame3(){
MyMouseAdapter MyMouseAdapter=新的MyMouseAdapter();
addMouseListener(myMouseAdapter);
addMouseMotionListener(myMouseAdapter);
}
@凌驾
受保护组件(图形g){
超级组件(g);
图形2d g2=(图形2d)g;
//画光滑的边
g2.setRenderingHint(RenderingHints.KEY_抗锯齿,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.设定行程(椭圆_行程);
for(矩形形状rect:rects){
g2.设置颜色(椭圆填充颜色);
g2.填充(rect);
g2.设置颜色(椭圆颜色);
g2.绘制(rect);
}
}
@凌驾
公共维度getPreferredSize(){
返回新维度(PREF_W,PREF_H);
}
类MyMouseAdapter扩展了MouseAdapter{
私有矩形形状selectedRect=null;
私有点deltaPt=null;
@凌驾
公共无效鼠标按下(MouseEvent mEvt){
if(mEvt.getButton()!=MouseEvent.BUTTON1){
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();
         }
      });
   }
}