两个矩形与paintComponent的交点 [英] Intersection of Two Rectangles with paintComponent

查看:151
本文介绍了两个矩形与paintComponent的交点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am writing a program that allows a user to paint rectangles onto a JLabel, and show the intersection and union of these rectangles. I have setup the GUI for the class but am struggling to find a way to integrate the intersection and union methods from the rectangle class. I know these methods work when used separately from the GUI.

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

When I try to run the program I keep getting an IndexOutOfBoundsException and the drawn rectangles are cleared from the gui. The intersections of each rectangle should show up in a different color on the JLabel. I tried to debug the program and for some reason when I create two rectangles and store them in my array list many many rectangle objects of the same characteristics are being created.

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

For the union method, a new rectangle should be create that contains all of the rectangles on the inside.

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


推荐答案

那里有很多问题...

There are a number of problems...

你是 mouseDragged 事件处理程序正在添加相同的 Rectangle a ArrayList ,一遍又一遍,增加 counter 值及其。

You're mouseDragged event handler is adding the same Rectangle to the a ArrayList, over and over again, increasing the counter value along with it.

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

This is not required. All you need to do is add the Rectangle on the mousePressed event. When mouseReleased is called, you could evaluate the Rectangle to check if the size is greater than 0x0 and remove it if it's not (ie remove any Rectangle whose size is 0x0)

不要依赖计数器变量,这个值很容易变得与大小不一致 a 列表。而是依赖 a.size

Don't rely on the counter variable, it's too easy for the value to become misaligned with the size of the a List. Instead, rely on a.size instead.

开关 ActionListener 中的语句正在评估匹配的大小写,以及它下面的所有以下情况。这是开关的一项功能。如果您不想评估以下情况,则需要在每个案例结束时(或者您希望中断处理的位置)添加 break

The switch statement in your ActionListener is evaluating the matching case, but also all the following cases below it. This is a feature of switch. If you don't want to evaluate the following cases, you need to add a break at the end of each case (or where ever you want to "break" the processing).

例如,当您点击绘制交叉点时,它还在评估 Union 清除图像保存图像个案......

For example, when you click Draw Intersections, it is also evaluating Union, Clear Image and Save Image cases...

您可以尝试使用类似的东西......

You could try using something like...

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

而不是......

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

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

There's also a logic area with your intersect paint code, where it is comparing a rectangle with itself, which ends up painting the whole rectangle.

而不是

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

您可以考虑使用

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

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

This is possibly occurring in you union painting logic as well, but I didn't really check that

适用于我......

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

这篇关于两个矩形与paintComponent的交点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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