调整添加的绘制组件和奇怪的挥动行为 [英] Resizing added painted components and strange swing behaviors

查看:114
本文介绍了调整添加的绘制组件和奇怪的挥动行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个问题困扰了我好几天。我正在制作一个特殊的油漆程序。我制作了一个JPanel,并添加了使用paint(..)方法绘制的自定义jComponents。
问题是,每当我调整窗口大小时,所有添加的组件都会消失(或者只是不画画),所以我最终得到一个空框架。

I have this problem bothering me for days. I'm making a special paint program. I made a JPanel, and added custom jComponents which are painted using the paint(..) method. The problem is, whenever I resize the window, all the added components "disappear" (or just don't paint) so I end up with a empty frame.

此外,我注意到使用此方法时出现一些奇怪的挥杆行为。我在描述此问题的代码中添加了注释。

Also i noticed some strange behaviors of swing when using this method. I have added comments to the code describing this problem.

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类

And here is the SimpleCanvas class

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:只是想说这个网站太棒了。我在使用谷歌时来到这里很多,现在我终于决定开个账户了。

BTW: Just wanted to say this site is amazing. I came here a lot while using Google, and now I finally decided to make an account.

推荐答案

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

Your problem is a layout problem. Add:

System.out.println(getSize());

到您的JComponent的绘制方法,看看在调整GUI大小时会发生什么。

to your JComponent's paint method to see what happens when you resize the GUI.

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

This is happening because the resize is invoking the layout manager actions.

要解决此问题,请不要使用 setBounds(...)来调整组件大小,而是使用布局管理器。如果希望布局管理器遵守特定的大小,也可以覆盖JComponent的getPreferredSize方法。最后,不要使用 paint 方法绘制,而是使用 paintComponent 方法绘制。教程将解释原因。

To solve this, don't use setBounds(...) to size components but rather the layout managers. Also override your JComponent's getPreferredSize method if you want the layout managers to respect a specific size for it. Finally, don't paint with the paint method but rather the paintComponent method. The tutorials will explain why.

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

Also, if you absolutely need to position something using absolute positioning, then the container must use a null layout:

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

编辑


如果我在做类似的事情你上面的程序,我不确定我是否会向JPanel添加新组件,而只是让绘图JPanel保持一个Shapes列表,然后使用for循环在其paintComponent方法中绘制形状。例如:

Edit
If I were doing something like your program above, I'm not sure that I'd add new components to a JPanel but rather would simply have the drawing JPanel hold a list of Shapes and then have the shapes drawn in its paintComponent method using a for loop. For example:

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

拖动形状

Edit 2
with dragging of shapes

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();
         }
      });
   }
}

这篇关于调整添加的绘制组件和奇怪的挥动行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆