Java 在对象之间切换时如何去掉矩形内的圆

Java 在对象之间切换时如何去掉矩形内的圆,java,swing,Java,Swing,我有一个组合框,在其中我可以选择绘制矩形、圆形或徒手绘制。 如果我选择画一个圆,它会画得很完美。如果我然后切换到绘制一个矩形,它会在矩形内绘制一个圆。如果我先画一个矩形,然后画一个圆,也会发生同样的情况。(见下图) 我的问题是: 如何在绘制圆和矩形之间切换,而不使圆出现在矩形内 如何在拖动鼠标时显示矩形/圆形。我的意思是,在我释放鼠标点击之前,线条如何显示 为什么徒手画画不行 这是我的testclass: import java.awt.*; import java.awt.event.*;

我有一个组合框,在其中我可以选择绘制矩形、圆形或徒手绘制。 如果我选择画一个圆,它会画得很完美。如果我然后切换到绘制一个矩形,它会在矩形内绘制一个圆。如果我先画一个矩形,然后画一个圆,也会发生同样的情况。(见下图)

我的问题是:

  • 如何在绘制圆和矩形之间切换,而不使圆出现在矩形内

  • 如何在拖动鼠标时显示矩形/圆形。我的意思是,在我释放鼠标点击之前,线条如何显示

  • 为什么徒手画画不行

  • 这是我的testclass:

    import java.awt.*; 
    import java.awt.event.*;
    import java.util.*;
    import javax.swing.*;
    
    public class Lab6 extends JFrame implements ActionListener {
        int startX, startY, endX, endY, w, h;
        ArrayList<Shape> shapeList =  new ArrayList<Shape>();
        Container cp = getContentPane();
    
        private JPanel topPanel;
        private JComboBox comboBox;    
        private final String[] boxOptions = new String[] {"Rektangel", "Cirkel", "Frihand"};   
    
    
        public Lab6(String title) {
            super(title);
            this.setLayout(new BorderLayout());
            this.setDefaultCloseOperation(EXIT_ON_CLOSE);
            this.setLocationRelativeTo(null);        
            this.setSize(840, 500);    
            this.initComponents();
            this.setVisible(true);
        }
    
    
        private void initComponents() {
            topPanel = new JPanel(new GridLayout(1,2));     
            topPanel.setPreferredSize(new Dimension(0,40));
    
            comboBox = new JComboBox(boxOptions);
            comboBox.setSelectedIndex(0);          
            comboBox.addActionListener(this);                          
    
            topPanel.add(comboBox);
            this.add(topPanel, BorderLayout.PAGE_START);          
        }
    
        @Override
        public void paint(Graphics g) {
            for (Shape s : shapeList) {
                s.draw(g);
            }
        }
    
        @Override
        public void actionPerformed(ActionEvent e) {
            if (e.getSource().equals(comboBox)) {     
                JComboBox cb = (JComboBox)e.getSource();
                if (cb.getSelectedItem().equals("Rektangel")) {                
                    cp.addMouseListener(new MouseAdapter() {            
                        @Override
                        public void mousePressed(MouseEvent e) {                   
                            startX = e.getX();     
                            startY = e.getY(); 
                        }
                        @Override
                        public void mouseReleased(MouseEvent e) {
                            endX = e.getX();
                            endY = e.getY();
    
                            int width = startX - endX;
                            int height = startY - endY;
                            w = Math.abs(width);
                            h = Math.abs(height);
    
                            Rectangle r =  new Rectangle(startX, startY, w, h);
    
                            shapeList.add(r);
                            repaint();
                        }
                    });                  
                }
                else if (cb.getSelectedItem().equals("Cirkel")) {
    
                    cp.addMouseListener(new MouseAdapter() {            
                        @Override
                        public void mousePressed(MouseEvent e) {                   
                            startX = e.getX();     
                            startY = e.getY(); 
                        }
                        @Override
                        public void mouseReleased(MouseEvent e) {
                            endX = e.getX();
                            endY = e.getY();
    
                            int width = startX - endX;
                            int height = startY - endY;
                            w = Math.abs(width);
                            h = Math.abs(height);
    
                            Circle c =  new Circle(startX, startY, w, h);
    
                            shapeList.add(c);
                            repaint();
                        }
                    });   
                }
                else if (cb.getSelectedItem().equals("Frihand")) {   //I need help with this part
    
                   cp.addMouseListener(new MouseAdapter() {            
                    @Override
                    public void mousePressed(MouseEvent e) {            
                        startX = e.getX();
                        startY = e.getY();
                    }
                    @Override
                    public void mouseDragged(MouseEvent e) {
    
                        FreeHand fh =  new FreeHand(startX, startY, e.getX(), e.getY());
    
                        shapeList.add(fh);
                        repaint();
                    }
                });  
    
                }
            }
        }
    
        public static void main(String args[]) {
            new Lab6("Drawing Program");
        }
    }
    
    课堂上徒手(我需要这部分的帮助):

    在课堂上:

    import java.awt.Graphics;
    import javax.swing.JPanel;
    
    public abstract class Shape extends JPanel {
    
        private int startX, startY, width, height;    
    
        public Shape() {
            this(0, 0, 1, 1);
        }
    
        public Shape(int startX, int startY, int width, int height) {
            this.startX = startX;
            this.startY = startY;
            this.width = width;
            this.height = height;
        }
    
        public abstract void draw(Graphics g);
    
        @Override
        public int getX() {
            return startX;
        }
    
        @Override
        public int getY() {
            return startY;
        }
    
        @Override
        public int getWidth() {
            return width;
        }
    
        @Override
        public int getHeight() {
            return height;
        }
    }
    

    有很多事情正在发生

  • 覆盖
    JFrame
  • 在执行自定义绘制之前,不调用
    super.paint
  • 每次更改形状时添加新的
    MosueListener
  • 相反,创建一个自定义组件,从类似
    JPanel
    的东西扩展,并覆盖它的
    paintComponent
    方法。使用此组件具有基本的绘图表面(控件应包含在另一个组件中)

    确保在执行任何自定义绘制之前调用
    super.paintComponent
    ,以免中断绘制链

    有关详细信息,请参阅和

    创建一个
    鼠标侦听器
    ,并将其注册到面板。当用户选择不同的形状时,更改面板内的状态变量(通过setter),该变量告诉
    MouseListener
    当用户开始绘图时应该做什么

    已更新…

    创建从
    JPanel
    扩展的自定义类

    public static class ShapePane extends JPanel {
    
    }
    
    重写类
    paintComponent
    方法

    public static class ShapePane extends JPanel {
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            // Custom Painting here...
        }
    
    }
    
    为布局管理器提供一些大小调整提示

    public static class ShapePane extends JPanel {
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            // Custom Painting here...
        }
    
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }
    
    }
    
    提供一种可以改变形状类型的方法…这样你就知道该画什么了

    public static class ShapePane extends JPanel {
    
        public enum ShapeType {
    
            CIRCLE,
            RECTANGLE
        }
    
        private ShapeType currentShapeType;
    
        public void setCurrentShapeType(ShapeType currentShapeType) {
            this.currentShapeType = currentShapeType;
        }
    
        public ShapeType getCurrentShapeType() {
            return currentShapeType;
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            // Custom Painting here...
        }
    
    }
    
    向自定义类添加一个
    mouseStener
    ,以创建所需类型的形状

    public static class ShapePane extends JPanel {
    
        public enum ShapeType {
    
            CIRCLE,
            RECTANGLE
        }
    
        private ShapeType currentShapeType;
    
        public ShapePane() {
            addMouseListener(new MouseAdapter() {
    
                private Point clickPoint;
    
                @Override
                public void mousePressed(MouseEvent e) {
                    clickPoint = e.getPoint();
                }
    
                @Override
                public void mouseReleased(MouseEvent e) {
                    Point releasePoint = e.getPoint();
                    int x = Math.min(releasePoint.x, clickPoint.x);
                    int y = Math.min(releasePoint.y, clickPoint.y);
                    int width = Math.abs(clickPoint.x - releasePoint.x);
                    int height = Math.abs(clickPoint.y - releasePoint.y);
                    switch (getCurrentShapeType()) {
                        case CIRCLE:
                            // Make a circle
                            break;
                        case RECTANGLE:
                            // Make a rectangle...
                            break;
                    }
                    repaint();
                }
    
            });
        }
    
        public void setCurrentShapeType(ShapeType currentShapeType) {
            this.currentShapeType = currentShapeType;
        }
    
        public ShapeType getCurrentShapeType() {
            return currentShapeType;
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            // Custom Painting here...
        }
    
    }
    
    填空

    创建另一个
    JPanel
    (这次只需创建一个实例),将控件添加到其中

    创建
    JFrame
    的实例,将自定义类添加到该实例和控制面板(确保它们的布局正确,以免相互覆盖-有关详细信息,请参阅)


    对控件使用适当的侦听器来确定用户想要绘制的形状类型,并相应地设置
    currentShapeType
    属性…

    有许多事情正在进行

  • 覆盖
    JFrame
  • 在执行自定义绘制之前,不调用
    super.paint
  • 每次更改形状时添加新的
    MosueListener
  • 相反,创建一个自定义组件,从类似
    JPanel
    的东西扩展,并覆盖它的
    paintComponent
    方法。使用此组件具有基本的绘图表面(控件应包含在另一个组件中)

    确保在执行任何自定义绘制之前调用
    super.paintComponent
    ,以免中断绘制链

    有关详细信息,请参阅和

    创建一个
    鼠标侦听器
    ,并将其注册到面板。当用户选择不同的形状时,更改面板内的状态变量(通过setter),该变量告诉
    MouseListener
    当用户开始绘图时应该做什么

    已更新…

    创建从
    JPanel
    扩展的自定义类

    public static class ShapePane extends JPanel {
    
    }
    
    重写类
    paintComponent
    方法

    public static class ShapePane extends JPanel {
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            // Custom Painting here...
        }
    
    }
    
    为布局管理器提供一些大小调整提示

    public static class ShapePane extends JPanel {
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            // Custom Painting here...
        }
    
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }
    
    }
    
    提供一种可以改变形状类型的方法…这样你就知道该画什么了

    public static class ShapePane extends JPanel {
    
        public enum ShapeType {
    
            CIRCLE,
            RECTANGLE
        }
    
        private ShapeType currentShapeType;
    
        public void setCurrentShapeType(ShapeType currentShapeType) {
            this.currentShapeType = currentShapeType;
        }
    
        public ShapeType getCurrentShapeType() {
            return currentShapeType;
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            // Custom Painting here...
        }
    
    }
    
    向自定义类添加一个
    mouseStener
    ,以创建所需类型的形状

    public static class ShapePane extends JPanel {
    
        public enum ShapeType {
    
            CIRCLE,
            RECTANGLE
        }
    
        private ShapeType currentShapeType;
    
        public ShapePane() {
            addMouseListener(new MouseAdapter() {
    
                private Point clickPoint;
    
                @Override
                public void mousePressed(MouseEvent e) {
                    clickPoint = e.getPoint();
                }
    
                @Override
                public void mouseReleased(MouseEvent e) {
                    Point releasePoint = e.getPoint();
                    int x = Math.min(releasePoint.x, clickPoint.x);
                    int y = Math.min(releasePoint.y, clickPoint.y);
                    int width = Math.abs(clickPoint.x - releasePoint.x);
                    int height = Math.abs(clickPoint.y - releasePoint.y);
                    switch (getCurrentShapeType()) {
                        case CIRCLE:
                            // Make a circle
                            break;
                        case RECTANGLE:
                            // Make a rectangle...
                            break;
                    }
                    repaint();
                }
    
            });
        }
    
        public void setCurrentShapeType(ShapeType currentShapeType) {
            this.currentShapeType = currentShapeType;
        }
    
        public ShapeType getCurrentShapeType() {
            return currentShapeType;
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            // Custom Painting here...
        }
    
    }
    
    填空

    创建另一个
    JPanel
    (这次只需创建一个实例),将控件添加到其中

    创建
    JFrame
    的实例,将自定义类添加到该实例和控制面板(确保它们的布局正确,以免相互覆盖-有关详细信息,请参阅)


    对控件使用适当的侦听器来确定用户想要绘制的形状类型,并相应地设置
    currentShapeType
    属性…

    有许多事情正在进行

  • 覆盖
    JFrame
  • 在执行自定义绘制之前,不调用
    super.paint
  • 每次更改形状时添加新的
    MosueListener
  • 相反,创建一个自定义组件,从类似
    JPanel
    的东西扩展,并覆盖它的
    paintComponent
    方法。使用此组件具有基本的绘图表面(控件应包含在另一个组件中)

    确保在执行任何自定义绘制之前调用
    super.paintComponent
    ,以免中断绘制链

    有关详细信息,请参阅和

    创建一个
    鼠标侦听器
    ,并将其注册到面板。当用户选择不同的形状时,更改面板内的状态变量(通过setter),该变量告诉
    MouseListener
    当用户开始绘图时应该做什么

    已更新…

    创建从
    JPanel
    扩展的自定义类

    public static class ShapePane extends JPanel {
    
    }
    
    重写类
    paintComponent
    方法

    public static class ShapePane extends JPanel {
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            // Custom Painting here...
        }
    
    }
    
    为布局管理器提供一些大小调整提示

    public static class ShapePane extends JPanel {
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            // Custom Painting here...
        }
    
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }
    
    }
    
    提供一种可以改变形状类型的方法…这样你就知道该画什么了

    public static class ShapePane extends JPanel {
    
        public enum ShapeType {
    
            CIRCLE,
            RECTANGLE
        }
    
        private ShapeType currentShapeType;
    
        public void setCurrentShapeType(ShapeType currentShapeType) {
            this.currentShapeType = currentShapeType;
        }
    
        public ShapeType getCurrentShapeType() {
            return currentShapeType;
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            // Custom Painting here...
        }
    
    }
    
    添加一个