2014-10-30 28 views
0

我有一个组合框,可以选择绘制矩形,圆形或徒手画。 如果我选择绘制一个圆圈,它会完美绘制它。如果我然后切换绘制一个矩形,它会在矩形内绘制一个圆。如果我先选择绘制一个矩形然后再绘制一个圆形,也会发生同样的情况。 (见下图)在对象之间切换时如何摆脱矩形内的圆圈

我的问题是:

  1. 我怎么能不绘制矩形内出现的圆圈一个圆圈和矩形之间切换?

  2. 如何在拖动鼠标时显示矩形/圆圈。我的意思是,直到我释放鼠标点击,线条才能显示出来。

  3. 它为什么不自由地绘画?

enter image description here

这是我的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"); 
    } 
} 

在类Rectangle(类圆形的外观相同):

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

回答

3

有东西要去上众多...

  1. 重写paintJFrame
  2. 执行自喷漆前不调用super.paint
  3. 添加你改变造型

取而代之的是新的MosueListener时,都会创建一个自定义组件,从像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... 
    } 

} 

添加一个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属性...

+0

谢谢您的回答,但不幸的是我不明白您的意思。 1.你的意思是我不应该重写颜料?如果我删除@Override Nothing Changes,则问题依然存在。 2.在代码中究竟应该删除对super.paint的调用? 3.你的意思是我不应该每次都添加一个新的MouseListerner?我怎样才能将mouselistener注册到面板上?直到代码看起来如何? 此外,我不知道我明白你的意思,通过创建一个自定义的组件,扩展JPanel和重写paintcomponent? 再次感谢您的时间。我很感激。 – user2939293 2014-10-30 21:03:50

+0

首先阅读链接教程。其次,每次从组合框中选择一个形状类型时,都会创建一个将“MouseListener”添加到您的框架中的新实例。这意味着如果我选择圆形,矩形,圆形,现在有三个鼠标侦听器,每个鼠标事件都会在鼠标事件发生时得到通知... – MadProgrammer 2014-10-30 21:10:07

+0

感谢您解释有关mouselistener的问题。它清除了事情。代码如何看起来像创建一个单一的mouselistener,我把它放在哪里? 我会阅读链接,再次感谢。 – user2939293 2014-10-30 21:19:56