2016-03-15 4 views
1

Я создаю интерфейс GUI, который рисует фигуры.Swing: paintComponenet не будет рисовать JPanel

я решил использовать paintComponent() на JPanel, вместо того, чтобы использовать краску() на JFrame. Это связано с тем, что при рисовании на рамке кнопки не появлялись, пока я не перепутал их.

ПЕРЕМЕНЫ/ОБНОВЛЕНИЯ, что я сделал недавно (обновленный код ниже):

  1. Я реализовал MouseListener и MouseMotionListener в моем классе artPanel JPanel. Похоже, что это позволило решить некоторые из моих проблем. Но есть несколько проблем:
  2. Вы можете загрузить мой java-файлhere, так что вам легче определить проблемы.

ПРОБЛЕМЫ, что я не могу понять:

  1. Кнопка Line не создает линию должным образом. Я играю с помощью методов mouseListener, но я не могу заставить это работать. Я хочу, чтобы он просто рисовал линию, когда мышь нажата и перетаскивается.
  2. Другие кнопки правильно рисуют фигуры. HOWEVER ... Формы не остаются на панели, когда я делаю новую форму. Например, я делаю круг. Затем, как только я делаю другой круг, первый исчезает. Я хочу, чтобы все они всегда оставались на холсте.

Другие, чем эти два, работают очень хорошо. Фото того, как он выглядит, это here.

public class Shapes extends JFrame implements ActionListener, WindowListener{ 

    /** 
    * Instance variables are created for the shape's sizes, window height and width. 
    */ 
    int currentX, currentY; 
    int previousX, previousY; 
    int topLeftX, topLeftY; 
    int bottomRightX, bottomRightY; 
    int height, width; 
    public final int WINDOW_WIDTH = 900; 
    public final int WINDOW_HEIGHT = 700; 

    /** 
    * String shape is created for the type of shape. 
    */ 
    public String shape = "Shape"; 

    /** 
    * Color is set to null, because no color is pressed yet. 
    */ 
    public Color color = null; 

    /** 
    * MouseReleased is false because no mouse has been released yet. 
    */ 
    public boolean mouseReleased = false; 

    private class artPanel extends JPanel implements MouseListener, MouseMotionListener{ 

     public artPanel(){ 
     /** 
     * Listeners are added to the GUI (for the mouse clicks, and for the window exit). 
     */ 
     addMouseListener(this); 
     addMouseMotionListener(this); 
     } 

     /** 
     * mouseDragged method is overridden. 
     * Previous X and Y variables are set to the current X and Y values. 
     * Then, the current X and Y values are set to the position where the mouse is dragged. 
     * The width and height is then calculated, while using the absolute value. 
     * Repaint method is invoked. 
     */ 
     @Override 
     public void mouseDragged(MouseEvent e) { 

      previousX = currentX; 
      previousY = currentY; 

      currentX = bottomRightX = e.getX(); 
      currentY = bottomRightY = e.getY(); 

      width = Math.abs(topLeftX - bottomRightX); 
      height = Math.abs(topLeftY - bottomRightY); 

      repaint(); 
     } 

     /** 
     * mouseClicked method is overridden. 
     */ 
     @Override 
     public void mouseClicked(MouseEvent e) { 

     } 

     /** 
     * mouseEntered method is overridden. 
     */ 
     @Override 
     public void mouseEntered(MouseEvent e) { 

     } 

     /** 
     * mouseExited method is overridden. 
     */ 
     @Override 
     public void mouseExited(MouseEvent e) { 

     } 

     /** 
     * mousePressed method is overridden, current X and Y variables are set to the position where the mouse is pressed. 
     */ 
     @Override 
     public void mousePressed(MouseEvent e) { 
      topLeftX = currentX = e.getX(); 
      topLeftY = currentY = e.getY(); 

     } 

     /** 
     * mouseReleased method is overridden. 
     * Bottom Right X and Y variables are set to the position where the mouse is pressed. 
     * Width and height is set using the absolute value of the difference. 
     * Repaint method is invoked. 
     */ 
     @Override 
     public void mouseReleased(MouseEvent e) { 
      bottomRightX = e.getX(); 
      bottomRightY = e.getY(); 

      width = Math.abs(topLeftX - bottomRightX); 
      height = Math.abs(topLeftY - bottomRightY); 

      mouseReleased = true; 

      repaint(); 
     } 




     /** 
     * mouseMoved method is overridden. 
     */ 
     @Override 
     public void mouseMoved(MouseEvent e) { 

     } 

     /** 
     * Paint method is created with parameter g for implementing graphics. 
     */ 
     public void paintComponent(Graphics g){ 
      super.paintComponent(g); 

      /** 
      * If the color is not null (has been changed), then the color is set to the user's c 
      */ 
      if(color != null) 
       g.setColor(color); 

      /** 
      * If the shape is a line (line button clicked), then the line is drawn. 
      */ 
      if(shape.equals("Line")){ 
       g.drawLine(previousX, previousY, currentX, currentY); 
      } 

      /** 
      * If the shape is a circle (circle button clicked), then the circle is drawn. 
      * The mouseReleased is set to false so that it draws it when it is dragged. 
      */ 
      else if(shape.equals("Circle") && mouseReleased){ 
       g.drawOval(topLeftX, topLeftY, width, height); 
       mouseReleased = false; 
      } 

      /** 
      * If the shape is a Rectangle (rectangle button clicked), then the rectangle is drawn. 
      * The mouseReleased is set to false so that it draws it when it is dragged. 
      */ 
      else if(shape.equals("Rectangle") && mouseReleased){ 
       g.drawRect(topLeftX, topLeftY, width, height); 
       mouseReleased = false; 
      } 

      /** 
      * If the shape is an Arc (arc button clicked), then the arc is drawn. 
      * The mouseReleased is set to false so that it draws it when it is dragged. 
      */ 
      else if(shape.equals("Arc") && mouseReleased){ 
       g.drawArc(topLeftX, topLeftY, width, height, 0, 90); 
       mouseReleased = false; 
      } 
     } 

    } 


    /** 
    * Constructor for creating the GUI 
    */ 
    public Shapes(){ 
     /** 
     * Super is invoked, title is set 
     */ 
     super("Draw Geometric Shapes"); 
     /** 
     * Size is set using the instance variables, does nothing on close as default. 
     */ 
     setSize(WINDOW_WIDTH, WINDOW_HEIGHT); 
     setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); 

     /** 
     * Layout is set to borderlayout for the frame. 
     */ 
     setLayout(new BorderLayout()); 

     /** 
     * A panel for the buttons is created, uses a flowlayout. 
     */ 
     JPanel buttons = new JPanel(); 
     buttons.setLayout(new FlowLayout()); 

     /** 
     * Button for the color is created. 
     */ 
     JButton colorChooser = new JButton("Color"); 
     colorChooser.addActionListener(this); 
     buttons.add(colorChooser); 

     /** 
     * Button for making a line is created. 
     */ 
     JButton line = new JButton("Line"); 
     line.addActionListener(this); 
     buttons.add(line); 

     /** 
     * Button for making a circle is created. 
     */ 
     JButton circle = new JButton("Circle"); 
     circle.addActionListener(this); 
     buttons.add(circle); 

     /** 
     * Button for making a rectangle is created. 
     */ 
     JButton rect = new JButton("Rectangle"); 
     rect.addActionListener(this); 
     buttons.add(rect); 

     /** 
     * Button for making an arc is created 
     */ 
     JButton arc = new JButton("Arc"); 
     arc.addActionListener(this); 
     buttons.add(arc); 

     /** 
     * Buttons panel is added to the south part of the border layout (bottom of the frame). 
     */ 
     add(buttons, BorderLayout.SOUTH); 

     addWindowListener(this); 

     artPanel p = new artPanel(); 
     p.setLayout(new FlowLayout()); 
     p.setBackground(Color.WHITE); 

     add(p); 
    } 


    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     /** 
     * New object of type Shapes is created and set to visible. 
     */ 
     Shapes draw_shapes = new Shapes(); 
     draw_shapes.setVisible(true); 
    } 


    /** 
    * actionPerformed is overridden and each button is set to a shape type 
    */ 
    @Override 
    public void actionPerformed(ActionEvent e) { 
     /** 
     * If the button "Color" is clicked, then the color chooser dialog appears. 
     */ 
     if(e.getActionCommand().equals("Color")){ 
      color = JColorChooser.showDialog(this, "Color Chooser", color); 
     } 

     /** 
     * If the button "Line" is clicked, then the shape is set to Line. 
     */ 
     else if(e.getActionCommand().equals("Line")){ 
      if(shape.equalsIgnoreCase("Line")){ 
       shape = "Line"; 
      } 
      else shape = "Line"; 
     } 

     /** 
     * If the button "Circle" is clicked, then the shape is set to circle. 
     */ 
     else if(e.getActionCommand().equals("Circle")){ 
      if(shape.equalsIgnoreCase("Circle")){ 
       shape = "Circle"; 
      } 
      else shape = "Circle"; 
     } 

     /** 
     * If the button "Rectangle" is clicked, then the shape is set to rectangle. 
     */ 
     else if(e.getActionCommand().equals("Rectangle")){ 
      if(shape.equalsIgnoreCase("Rectangle")){ 
       shape = "Rectangle"; 
      } 
      else shape = "Rectangle"; 
     } 

     /** 
     * If the button "Arc" is clicked, then the shape is set to Arc. 
     */ 
     else if(e.getActionCommand().equals("Arc")){ 
      if(shape.equalsIgnoreCase("Arc")){ 
       shape = "Arc"; 
      } 
      else shape = "Arc"; 
     } 
    } 

    } 
} 

Я вырезал остальное, потому что они были методами windowlistener.

+1

Я знаю, что это не имеет ничего общего с вашей ошибкой, но что с 'if (shape.equals (str)) {if (shape.equalsIgnoreCase (str)) shape = str; else shape = str; } 'spammed в вашем методе' actionPerformed', для меня это не имеет смысла. – Maljam

+0

Думаю, это было больше смысла, когда я писал его. Он накладывает форму на нажатие кнопки, затем в методе краски он рисует в соответствии с назначенными фигурами. – pmcg521

+0

Я думаю, что то, что @Maljam указывает на то, что вы делаете то же самое, независимо от того, является ли выражение 'if'' истинным' или 'false'. На самом деле, кажется, что все дерево 'if ... else' можно заменить одним выражением' shape = e.getActionCommand(); '. – Radiodef

ответ

4
add(buttons, BorderLayout.SOUTH); 

Panel p = new Panel(); 
add(p); 

JPanel whitePanel = new JPanel(); 
whitePanel.setBackground(Color.WHITE); 
add(whitePanel); 

Вы код означает, что вы используете менеджер компоновки по умолчанию на панели содержимого фрейма, который является BorderLayout.

Вы пытаетесь добавить «p» и «whitePanel» к CENTER (который является значением по умолчанию, когда вы не указываете ограничение) BorderLayout. Только один компонент может быть добавлен в заданное местоположение BorderLayout. Нарисована только последняя добавленная панель, которая является вашей белой панелью, поэтому вы никогда не увидите пользовательскую картину своей панели.

Не знаю, каковы ваши требования к точной компоновке, поэтому я не могу предложить решение, отличное от использования другого менеджера компоновки, или использовать вложенные панели с разными менеджерами макетов.

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

Не вызывайте свой класс «Панель», это AWT-класс уже называется таким, что вызывает путаницу. Имя вашего класса должно быть более наглядным.

Я решил использовать paintComponent() на JPanel вместо использования paint() на JFrame.

Вы никогда не должны переопределять краску на раме. Вы действительно должны переопределить paintComponent() JPanel. Прочтите раздел из руководства Swing по телефону Custom Painting для получения дополнительной информации и рабочих примеров.

Edit:

Затем, как только я сделать еще один круг, первый один исчезает. Я хочу, чтобы все они всегда оставались на холсте.

Прочитано Custom Painting Approaches, которые показывают 2 способа сделать картину, когда вы хотите, чтобы несколько объектов были на одной панели. Какой подход вы выбираете, зависит от вашего точного требования.

+0

Спасибо за конкретный и подробный ответ. Я сейчас далеко от компьютера, но я буду отвечать любыми обновлениями. – pmcg521

+0

Я обновил свой пост/код, если вам интересно. У меня все еще есть несколько проблем, с которыми я не могу работать. Спасибо за вход. – pmcg521

+0

@ pmcg521, см. Править. – camickr