2014-10-30 55 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