Swing:paintComponenet不会绘制到JPanel

时间:2016-03-15 18:05:26

标签: java swing panel paint paintcomponent

我正在创建一个绘制形状的GUI界面。

我决定在JPanel上使用 paintComponent(),而不是在JFrame上使用 paint()。这是因为,当在框架上绘画时,按钮不会出现,直到我将它们蒙上它们。

我最近做出的更改/更新(下面更新的代码):

  1. 我在artPanel JPanel类中实现了MouseListener和MouseMotionListener。这似乎解决了我的一些问题。但是有一些问题:
  2. 您可以下载我的java文件 here,以便您更轻松地识别问题。
  3. 我无法弄清楚的问题:

    1. “线路”按钮无法正确创建线路。我一直在使用mouseListener方法,但我不能让它工作。我希望它只需在单击并拖动鼠标时画一条线。
    2. 其他按钮正确绘制形状。 HOWEVER ...当我制作新形状时,形状不会停留在面板上。例如,我做了一个圆圈。然后,当我再做一个圆圈时,第一个圆圈消失。我希望他们都能一直留在画布上。
    3. 除了这两个,它的效果还不错。它看起来像是一张照片 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 个答案:

答案 0 :(得分: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的{​​{1}}(这是您未指定约束时的默认值)。只能将一个组件添加到BorderLayout的给定位置。只添加了最后一个面板,这是你的whitePanel,所以你永远不会看到面板的自定义绘画。

不知道您的确切布局要求是什么,因此除了使用不同的布局管理器或使用具有不同布局管理器的嵌套面板之外,我无法建议解决方案。

此外,在进行自定义绘制时,您应该重写BorderLayout方法以返回大小,以便布局管理器可以完成其工作。

不要打电话给你的班级“Panel”,已经有一个名字的AWT课程,所以这会造成混乱。您的班级名称应该更具描述性。

  

我决定在JPanel上使用paintComponent(),而不是在JFrame上使用paint()。

你永远不应该覆盖框架上的油漆。你应该覆盖JPanel的paintComponent()。阅读Custom Painting上Swing教程中的部分,了解更多信息和工作示例。

编辑:

  

然后,当我再做一个圆圈时,第一个圆圈消失。我希望他们都能一直留在画布上。

阅读Custom Painting Approaches,当你想要在同一个面板上绘制多个对象时,它会显示两种绘画方式。您选择哪种方法取决于您的确切要求。