两个矩形与paintComponent的交点

时间:2014-03-04 00:06:34

标签: java swing intersection

我正在编写一个程序,允许用户在JLabel上绘制矩形,并显示这些矩形的交集和并集。我已经为类设置了GUI,但我很难找到一种方法来集成矩形类中的交集和联合方法。我知道这些方法在与GUI分开使用时有效。

当我尝试运行程序时,我不断获得IndexOutOfBoundsException,并且从gui中清除绘制的矩形。每个矩形的交叉点应在JLabel上以不同的颜色显示。我尝试调试程序,出于某种原因,当我创建两个矩形并将它们存储在我的数组列表中时,会创建许多具有相同特征的矩形对象。

对于union方法,应创建一个包含内部所有矩形的新矩形。

RectangleFrame1:

public class RectangleFrame1 extends JFrame implements ActionListener
{


    JPanel buttonPanel;
    JButton saveImage;
    JButton clearImage;
    JCheckBox intersections;
    JCheckBox union;
    RectangleLabel drawingArea;
    boolean intersect = false;
    boolean uni = false;

    public RectangleFrame1()
    {
        super();
        setTitle("Rectangles");
        setSize(600,600);
        setResizable(false);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        buttonPanel = new JPanel();
        buttonPanel.setBorder(BorderFactory.createLineBorder(Color.black));
        this.add(buttonPanel, BorderLayout.SOUTH);

        intersections = new JCheckBox("Draw Intersections");
        buttonPanel.add(intersections);
        intersections.addActionListener(this);
        intersections.setActionCommand("Intersections");

        union = new JCheckBox("Draw Union");
        buttonPanel.add(union);
        union.addActionListener(this);
        union.setActionCommand("Union");

        saveImage = new JButton("Save Image");
        saveImage.setMargin(new Insets(0,0,0,0));
        buttonPanel.add(saveImage);
        saveImage.addActionListener(this);
        saveImage.setActionCommand("Save Image");

        clearImage = new JButton("Clear Image");
        clearImage.setMargin(new Insets(0,0,0,0));
        buttonPanel.add(clearImage);
        clearImage.addActionListener(this);
        clearImage.setActionCommand("Clear Image");

        drawingArea = new RectangleLabel();
        drawingArea.setBorder(BorderFactory.createLineBorder(Color.blue));
        this.add(drawingArea, BorderLayout.CENTER);
        drawingArea.addMouseListener((MouseListener) drawingArea);
        drawingArea.addMouseMotionListener((MouseMotionListener) drawingArea);

    }

    @Override
    public void actionPerformed(ActionEvent arg0)
    {
        switch(arg0.getActionCommand())
        {
            case "Intersections":
            if(intersections.isSelected())
            {
                intersect = true;
            }
            else
            {
                intersect = false;
            }
            case "Union":
            if(union.isSelected())
            {
                uni = true;
            }
            else
            {
                uni = false;
            }
            case "Clear Image": drawingArea.clearImage();
            case "Save Image": drawingArea.saveImage();
        }

    }

    class RectangleLabel extends JLabel implements MouseListener, MouseMotionListener
    {

        Rectangle rectangle = null;
        int x, y, x2, y2;
        ArrayList<Rectangle> a = new ArrayList();
        int counter;
        public RectangleLabel()
        {
            super();
        }
        @Override
        public void mousePressed(MouseEvent arg0)
        {
            x = arg0.getX();
            y = arg0.getY();

            rectangle = new Rectangle(x, y, 0, 0);
        }

        @Override
        public void mouseDragged(MouseEvent arg0)
        {
            // TODO Auto-generated method stub
            x2 = arg0.getX();
            y2 = arg0.getY();

            if(rectangle.getX() > x2)
            {
                rectangle.setWidth(x-x2);
            }
            if(x2 > rectangle.getX())
            {
                rectangle.setWidth(x2-x);
            }
            if(y > y2)
            {
                rectangle.setHeight(y-y2);
            }
            if(y2 > y)
            {
                rectangle.setHeight(y2-y);
            }

            a.add(rectangle);
            counter++;
            repaint();

        }

        @Override
        public void mouseReleased(MouseEvent arg0)
        {
            repaint();
        }

        @Override
        public void mouseMoved(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 mouseClicked(MouseEvent arg0) {
            // TODO Auto-generated method stub

        }

        @Override
        public void paintComponent(Graphics g)
        {
            super.paintComponent(g);
            if(rectangle != null)
            {
                for(int i = 0; i < a.size(); i++)
                {
                    float thickness = 2;
                    ((Graphics2D) g).setStroke(new BasicStroke(thickness));
                    g.setColor(Color.BLUE);
                    g.drawRect(a.get(i).getX(), a.get(i).getY(), a.get(i).getWidth(), a.get(i).getHeight());
                    g.setColor(Color.gray);
                    g.fillRect(a.get(i).getX(), a.get(i).getY(), a.get(i).getWidth(), a.get(i).getHeight());
                }
            }

            if(intersect == true && counter > 0)
            {
                for(int h = 0; h < counter-1; h++)
                {
                    for(int j = 1; j < counter; j++)
                    {   if(a.get(h).overlaps(a.get(j)))
                        {
                            Rectangle rect = a.get(h).intersect(a.get(j));
                            g.setColor(Color.RED);
                            g.fillRect(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());
                        }
                    }
                }
            }

            if(uni == true && counter > 0)
            {
                for(int h = 0; h < counter - 1; h++)
                {
                    for(int j = 1; j < counter; j++)
                    {
                        Rectangle rect = a.get(h).union(a.get(j));
                        g.setColor(Color.WHITE);
                        g.drawRect(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());

                    }
                }
            }
        }


        public void saveImage()
        {
            BufferedImage image = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_ARGB);
            Graphics2D aaaaa = image.createGraphics();
            aaaaa.setBackground(Color.WHITE);
            aaaaa.clearRect(0, 0, this.getWidth(), this.getHeight());
            this.paintAll(aaaaa);
            try
            {
                File output = new File("rectangle.png");
                ImageIO.write(image, "Rectangles", output);
            }
            catch(IOException ie)
            {

            }
        }
        public void clearImage()
        {
            a.clear();
            repaint();
        }

    }

}

矩形:

public class Rectangle
{


    private int x,y,width,height;

    public Rectangle(int x,int y,int width,int height)
    {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
    }

    public Rectangle(Rectangle a)
    {
        this.x = a.x;
        this.y = a.y;
        this.width = a.width;
        this.height = a.height;
    }

    public String toString()
    {
        return "Start: ("+x+","+y+"), Width: "+width+", Height: "+height+"\n";
    }

    public int getX()
    {
        return x;
    }

    public int getY()
    {
        return y;
    }

    public int getWidth()
    {
        return width;
    }

    public int getHeight()
    {
        return height;
    }

    public void setX(int x)
    {
        this.x = x;
    }

    public void setY(int y)
    {
        this.y = y;
    }

    public void setWidth(int width)
    {
        this.width = width;
    }

    public void setHeight(int height)
    {
        this.height = height;
    }

    public int area()
    {
        return width*height;
    }

    public boolean overlaps(Rectangle a)
    {
        if ((x>a.x+a.width) || (a.x>x+width) || (y>a.y+a.height) || (a.y>y+height))
        {
            return false;
        }
        return true;
    }

    public Rectangle intersect(Rectangle a)
    {
        if (!overlaps(a))
            return null;

        int left,right,top,bottom;

        if (x<a.x)
            left = a.x;
        else
            left = x;

        if (y<a.y)
            bottom = a.y;
        else
            bottom = y;

        if ((x+width)<(a.x+a.width))
            right = x+width;
        else
            right = a.x+a.width;

        if ((y+height)<(a.y+a.height))
            top = y+height;
        else
            top = a.y+a.height;

        return new Rectangle(left,bottom,right-left,top-bottom);
    }

    public Rectangle union(Rectangle a)
    {
        int left,right,top,bottom;

        if (x<a.x)
            left = x;
        else
            left = a.x;

        if (y<a.y)
            bottom = y;
        else
            bottom = a.y;

        if ((x+width)<(a.x+a.width))
            right = a.x+a.width;
        else
            right = x+width;

        if ((y+height)<(a.y+a.height))
            top = a.y+a.height;
        else
            top = y+height;

        return new Rectangle(left,bottom,right-left,top-bottom);
    }
}

1 个答案:

答案 0 :(得分:1)

有很多问题......

mouseDragged事件处理程序正在向Rectangle a添加相同的ArrayList,一遍又一遍地增加counter值它

这不是必需的。您需要做的就是在Rectangle事件中添加mousePressed。调用mouseReleased后,您可以评估Rectangle以检查大小是否大于0x0,如果不是,则将其删除(即删除大小为{Rectangle的任何0x0 {1}})

不要依赖counter变量,因此值太容易与a List的大小错位。相反,请改为依赖a.size

switch中的ActionListener语句正在评估匹配的情况,但也会评估其下方的所有情况。这是switch的一项功能。如果您不想评估以下情况,则需要在每个案例的末尾添加break(或者您希望“中断”处理的位置)。

例如,当您点击Draw Intersections时,它还会评估UnionClear ImageSave Image个案例......

您可以尝试使用类似......

的内容
switch (arg0.getActionCommand()) {
    case "Intersections":
        intersect = intersections.isSelected();
        break;
    case "Union":
        uni = union.isSelected();
        break;
    case "Clear Image":
        drawingArea.clearImage();
        break;
    case "Save Image":
        drawingArea.saveImage();
        break;
}

,而不是...

绘画代码中的逻辑错误......

还有一个带有intersect绘图代码的逻辑区域,它将矩形与自身进行比较,最终绘制整个矩形。

而不是

if (a.get(h).overlaps(a.get(j))) {

您可以考虑使用

if (!a.get(h).equals(a.get(j)) && a.get(h).overlaps(a.get(j))) {

这可能发生在你的联合绘画逻辑中,但我没有真正检查

对我来说很好......

enter image description here

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class RectangleFrame1 extends JFrame implements ActionListener {

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                RectangleFrame1 frame = new RectangleFrame1();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    JPanel buttonPanel;
    JButton saveImage;
    JButton clearImage;
    JCheckBox intersections;
    JCheckBox union;
    RectangleLabel drawingArea;
    boolean intersect = false;
    boolean uni = false;

    public RectangleFrame1() {
        super();
        setTitle("Rectangles");
        setSize(600, 600);
//        setResizable(false);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        buttonPanel = new JPanel();
        buttonPanel.setBorder(BorderFactory.createLineBorder(Color.black));
        this.add(buttonPanel, BorderLayout.SOUTH);

        intersections = new JCheckBox("Draw Intersections");
        buttonPanel.add(intersections);
        intersections.addActionListener(this);
        intersections.setActionCommand("Intersections");

        union = new JCheckBox("Draw Union");
        buttonPanel.add(union);
        union.addActionListener(this);
        union.setActionCommand("Union");

        saveImage = new JButton("Save Image");
        saveImage.setMargin(new Insets(0, 0, 0, 0));
        buttonPanel.add(saveImage);
        saveImage.addActionListener(this);
        saveImage.setActionCommand("Save Image");

        clearImage = new JButton("Clear Image");
        clearImage.setMargin(new Insets(0, 0, 0, 0));
        buttonPanel.add(clearImage);
        clearImage.addActionListener(this);
        clearImage.setActionCommand("Clear Image");

        drawingArea = new RectangleLabel();
        drawingArea.setBorder(BorderFactory.createLineBorder(Color.blue));
        this.add(drawingArea, BorderLayout.CENTER);
        drawingArea.addMouseListener((MouseListener) drawingArea);
        drawingArea.addMouseMotionListener((MouseMotionListener) drawingArea);

    }

    @Override
    public void actionPerformed(ActionEvent arg0) {
        switch (arg0.getActionCommand()) {
            case "Intersections":
                intersect = intersections.isSelected();
                break;
            case "Union":
                uni = union.isSelected();
                break;
            case "Clear Image":
                drawingArea.clearImage();
                break;
            case "Save Image":
                drawingArea.saveImage();
                break;
        }
        repaint();
    }

    class RectangleLabel extends JLabel implements MouseListener, MouseMotionListener {

        Rectangle rectangle = null;
        int x, y, x2, y2;
        ArrayList<Rectangle> a = new ArrayList();

        public RectangleLabel() {
            super();
        }

        @Override
        public void mousePressed(MouseEvent arg0) {
            x = arg0.getX();
            y = arg0.getY();

            rectangle = new Rectangle(x, y, 0, 0);
            a.add(rectangle);
        }

        @Override
        public void mouseDragged(MouseEvent arg0) {
            // TODO Auto-generated method stub
            x2 = arg0.getX();
            y2 = arg0.getY();

            if (rectangle.getX() > x2) {
                rectangle.setWidth(x - x2);
            }
            if (x2 > rectangle.getX()) {
                rectangle.setWidth(x2 - x);
            }
            if (y > y2) {
                rectangle.setHeight(y - y2);
            }
            if (y2 > y) {
                rectangle.setHeight(y2 - y);
            }

            repaint();

        }

        @Override
        public void mouseReleased(MouseEvent arg0) {
            rectangle = null;
            repaint();
        }

        @Override
        public void mouseMoved(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 mouseClicked(MouseEvent arg0) {
            // TODO Auto-generated method stub

        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            for (Rectangle rect : a) {
                float thickness = 2;
                ((Graphics2D) g).setStroke(new BasicStroke(thickness));
                g.setColor(Color.BLUE);
                g.drawRect(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());
                g.setColor(Color.gray);
                g.fillRect(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());
            }

            if (intersect) {
                for (int h = 0; h < a.size() - 1; h++) {
                    for (int j = 1; j < a.size(); j++) {
                        if (!a.get(h).equals(a.get(j)) && a.get(h).overlaps(a.get(j))) {
                            Rectangle rect = a.get(h).intersect(a.get(j));
                            g.setColor(Color.RED);
                            g.fillRect(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());
                        }
                    }
                }
            }

            if (uni) {
                for (int h = 0; h < a.size() - 1; h++) {
                    for (int j = 1; j < a.size(); j++) {
                        if (!a.get(h).equals(a.get(j)) && a.get(h).overlaps(a.get(j))) {
                            Rectangle rect = a.get(h).union(a.get(j));
                            g.setColor(Color.WHITE);
                            g.drawRect(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());

                        }
                    }
                }
            }
        }

        public void saveImage() {
            BufferedImage image = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_ARGB);
            Graphics2D aaaaa = image.createGraphics();
            aaaaa.setBackground(Color.WHITE);
            aaaaa.clearRect(0, 0, this.getWidth(), this.getHeight());
            this.paintAll(aaaaa);
            try {
                File output = new File("rectangle.png");
                ImageIO.write(image, "Rectangles", output);
            } catch (IOException ie) {

            }
        }

        public void clearImage() {
            a.clear();
            repaint();
        }

    }

    public class Rectangle {

        private int x, y, width, height;

        public Rectangle(int x, int y, int width, int height) {
            this.x = x;
            this.y = y;
            this.width = width;
            this.height = height;
        }

        public Rectangle(Rectangle a) {
            this.x = a.x;
            this.y = a.y;
            this.width = a.width;
            this.height = a.height;
        }

        public String toString() {
            return "Start: (" + x + "," + y + "), Width: " + width + ", Height: " + height + "\n";
        }

        public int getX() {
            return x;
        }

        public int getY() {
            return y;
        }

        public int getWidth() {
            return width;
        }

        public int getHeight() {
            return height;
        }

        public void setX(int x) {
            this.x = x;
        }

        public void setY(int y) {
            this.y = y;
        }

        public void setWidth(int width) {
            this.width = width;
        }

        public void setHeight(int height) {
            this.height = height;
        }

        public int area() {
            return width * height;
        }

        public boolean overlaps(Rectangle a) {
            if ((x > a.x + a.width) || (a.x > x + width) || (y > a.y + a.height) || (a.y > y + height)) {
                return false;
            }
            return true;
        }

        public Rectangle intersect(Rectangle a) {
            if (!overlaps(a)) {
                return null;
            }

            int left, right, top, bottom;

            if (x < a.x) {
                left = a.x;
            } else {
                left = x;
            }

            if (y < a.y) {
                bottom = a.y;
            } else {
                bottom = y;
            }

            if ((x + width) < (a.x + a.width)) {
                right = x + width;
            } else {
                right = a.x + a.width;
            }

            if ((y + height) < (a.y + a.height)) {
                top = y + height;
            } else {
                top = a.y + a.height;
            }

            return new Rectangle(left, bottom, right - left, top - bottom);
        }

        public Rectangle union(Rectangle a) {
            int left, right, top, bottom;

            if (x < a.x) {
                left = x;
            } else {
                left = a.x;
            }

            if (y < a.y) {
                bottom = y;
            } else {
                bottom = a.y;
            }

            if ((x + width) < (a.x + a.width)) {
                right = a.x + a.width;
            } else {
                right = x + width;
            }

            if ((y + height) < (a.y + a.height)) {
                top = a.y + a.height;
            } else {
                top = y + height;
            }

            return new Rectangle(left, bottom, right - left, top - bottom);
        }
    }
}