如何在对象之间切换时摆脱矩形内的圆圈

时间:2014-10-30 20:35:24

标签: java swing

我有一个组合框,我可以选择绘制矩形,圆形或手绘。 如果我选择绘制一个圆圈,它会完美地绘制它。如果我然后切换到绘制一个矩形,它会在矩形内部绘制一个圆圈。如果我首先选择绘制矩形然后再绘制圆圈,也会发生同样的情况。 (见下图)

我的问题是:

  1. 如何在没有圆形出现在矩形内部的情况下,在绘制圆形和矩形之间切换?

  2. 如何在拖动鼠标时显示矩形/圆圈。我的意思是在我释放鼠标之前线条如何显示?

  3. 为什么不用空手画?

  4. enter image description here

    这是我的测试类:

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

    在类Rectangle中(类Circle看起来相同):

    import java.awt.*;
    
    public class Rectangle extends Shape {
    
        public Rectangle(int x, int y, int width, int height) {
            super(x, y, width, height);
        }
    
        public Rectangle() {
            super();
        }
    
        @Override
            public void draw(Graphics g) {  
                Graphics2D g2 = (Graphics2D) g;             
                g2.setColor(Color.RED);                     
                g2.setStroke(new BasicStroke(4));           
                g.drawRect(getX(), getY(), getWidth(), getHeight());       
        }        
    }
    

    在FreeHand课程中(我需要这方面的帮助):

    import java.awt.*;
    
    public class FreeHand extends Shape {
    
        public FreeHand(int x, int y, int width, int height) {
            super(x, y, width, height);
        }
    
        public FreeHand() {
            super();
        }        
    
        @Override
        public void draw(Graphics g) {
            Graphics2D g2 = (Graphics2D) g;             
            g2.setColor(Color.BLUE);                    
            g2.setStroke(new BasicStroke(4));           
            g2.drawLine(getX(), getY(), getWidth(), getHeight());  
        }
    }
    

    课堂形状:

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

1 个答案:

答案 0 :(得分:3)

有很多事情正在发生......

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

    确保在执行任何自定义绘画之前致电super.paintComponent,这样您就不会打破油漆链

    有关详细信息,请参阅Performing Custom PaintingPainting in AWT and Swing

    创建一个单MouseListener并将其注册到面板。当用户选择不同的形状时,更改面板中的状态变量(通过设置器),告诉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...
        }
    
    }
    

    向自定义类添加SINGLE MouseListener以创建所需类型的形状...

    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的实例,向其添加自定义类和控件面板(确保它们的布局正确,以便它们不会相互覆盖 - 请参阅Laying Out Components Within a Container更多细节)

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