2014-10-30 3 views
0

У меня есть combobox, в котором я могу выбрать рисование прямоугольника, круга или от руки. Если я выбираю рисовать круг, он отлично рисует. Если я затем переключаюсь на рисование прямоугольника, он рисует круг внутри прямоугольника. То же самое происходит, если я сначала выберу прямоугольник, а затем круг. (См рисунок ниже)Как избавиться от круга внутри прямоугольника при переключении между объектами

Мои вопросы:

  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 (класс 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; 
    } 
} 

ответ

3

Есть множество вещей происходит ...

  1. Перекрытие paint из JFrame
  2. Не называя super.paint перед выполнением пользовательской картины.
  3. Добавление нового MosueListener КАЖДЫЙ раз, когда вы изменить форму

Вместо этого создайте пользовательский компонент, простираясь от чего-то, как JPanel и переопределить это paintComponent метод. Используйте этот компонент, чтобы ваша основная поверхность рисования (ваши элементы управления должны содержаться в другом компоненте).

Убедитесь, что вы называете super.paintComponent перед выполнением каких-либо пользовательских живописи, так что вы не разорвать цепь краски

См Performing Custom Painting и Painting in AWT and Swing для получения более подробной информации

Создать SINGLE MouseListener и зарегистрировать его на панель. Когда использование выбирает другую форму, измените переменную состояния внутри панели (через сеттер), которая сообщает MouseListener, что она должна делать, когда пользователь начинает рисовать.

Обновлено ...

Создайте пользовательский класс, который наследуется от JPanel ...

public static class ShapePane extends JPanel { 

} 

Override классы 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 (вы можете просто создать экземпляр на этот раз), добавить элементы управления к нему

Создать Insta nce из JFrame, добавьте к нему пользовательский класс и панель управления (убедитесь, что они правильно установлены, чтобы они не перекрывали друг друга).

Используйте соответствующие прослушиватели для управления, чтобы определить тип формы, которую пользователь хочет нарисовать, и установить свойство currentShapeType соответственно ...

+0

Спасибо за ваш ответ, но, к сожалению, я не понимаю, что вы имеете в виду. 1. Вы имеете в виду, что я НЕ должен переопределять краску? Если я удалю @Override ничего изменений, проблема остается. 2. Где именно в коде следует удалить вызов super.paint? 3. Вы хотите сказать, что я не должен добавлять новый MouseListerner каждый раз? Как я могу зарегистрировать mouselistener на панели? Как выглядит код? Кроме того, я не уверен, что понимаю, что вы подразумеваете, создавая пользовательский компонент, расширяя JPanel и переопределяя компонент paintcom? Еще раз спасибо за ваше время. Я ценю это. – user2939293

+0

Начните с чтения связанных уроков. Во-вторых, каждый раз, когда вы выбираете тип фигуры из combobox, вы создаете новый экземпляр «MouseListener», добавляющий его к вашему фрейму. Это означает, что, если я выберу круг, прямоугольник, круг, теперь есть три прослушивателя мыши, каждый из которых будет уведомлен о появлении события мыши ... – MadProgrammer

+0

Благодарим вас за разъяснение о мышеловке. Это прояснилось. Как бы код выглядел, чтобы создать один одиночный mouselistener, и где я его положу? Я прочитаю ссылку, еще раз спасибо. – user2939293

Смежные вопросы