布尔值不保持值

时间:2015-02-17 17:44:32

标签: java swing graphics boolean clear

我有一个用户绘制线条的应用程序。有一个JButton btnClear,当用户点击时,必须清除图纸,以便用户可以重新绘制。我在btnClear上使用ActionListener来了解它何时被单击。我设置了一个布尔值Clear,以便在paintComponent()中执行正确的IF语句。但是,boolean Clear在paintComponent()中保持一个False值,尽管我在repaint()之前将它设置为True。为什么会这样?

注意:我尝试将框架的背景设置为红色,以便在paintComponent()中测试布尔值。

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Line2D;
import javax.swing.*;

public class Clipping extends JPanel implements MouseListener, ActionListener
{
    static JFrame frame;
    static JComboBox cboDraw;
    static JButton btnClear;
    static JButton btnClip;

    double x1, y1, x2, y2;
    boolean FirstPoint;
    boolean Clear = false;

    public static void main(String[] args) 
    {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() 
            {
                CreateFrame();
            }
        });
    }

    private static void CreateFrame()
    {
        frame = new JFrame("Clipping");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new Clipping());
        frame.setSize(500,500);
        frame.setVisible(true);
    }

    public Clipping()
    {
        setLayout(new BorderLayout());

        JToolBar toolbar = new JToolBar(JToolBar.VERTICAL);
        PopulateToolBar(toolbar);
        add(toolbar, BorderLayout.WEST);

        addMouseListener(this);
        cboDraw.addMouseListener(this);
        btnClip.addActionListener(this);
        btnClear.addActionListener(this);

    }

    private static void PopulateToolBar(JToolBar toolbar)
    {
        String[] cboList = {"Line", "Polygon"};
        cboDraw = new JComboBox(cboList);
        cboDraw.setMaximumSize(new Dimension(70,30));
        btnClip = new JButton("Set clip area");
        btnClear = new JButton("Clear");

        toolbar.add(cboDraw);
        toolbar.addSeparator();
        toolbar.add(btnClip);
        toolbar.addSeparator();
        toolbar.add(btnClear);

        cboDraw.setAlignmentX(Component.CENTER_ALIGNMENT);
        btnClip.setAlignmentX(Component.CENTER_ALIGNMENT);
        btnClear.setAlignmentX(Component.CENTER_ALIGNMENT);

        toolbar.setMargin(new Insets(10,10,10,10));
        toolbar.setFloatable(false);
        toolbar.setBackground(Color.black);
    }

    public void paintComponent(Graphics g)
    {
        Graphics2D g2 = (Graphics2D) g;
        if (cboDraw.getSelectedIndex() == 0) //draw line
        {
            g2.draw(new Line2D.Double(x1, y1, x2, y2));
        }
        else if (Clear == true)
        {
            frame.setBackground(Color.red); //ONLY FOR TESTING PURPOSE
        }
    }

    public void mousePressed(MouseEvent e)
    {
        if (e.getSource() != cboDraw) //to prevent line coordinates from being saved when selecting from combobox
        {
            if (cboDraw.getSelectedIndex() == 0) //user wants to draw line
            {
                if (FirstPoint == false) //first coordinates
                {
                    x1 = e.getX();
                    y1 = e.getY();
                    FirstPoint = true;
                }
                else //second coordinates
                {
                    x2 = e.getX();
                    y2 = e.getY();
                    repaint();
                    FirstPoint = false;
                }
            }
        }
    }

    public void actionPerformed(ActionEvent e) 
    {
        if (e.getSource() == btnClear)
        {
            Clear = true;
            repaint();
            Clear = false;
        }
    }

    public void mouseClicked(MouseEvent e) {}
    public void mouseReleased(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
}

3 个答案:

答案 0 :(得分:0)

您没有在paintComponent方法覆盖中调用super.paintComponent(g)方法。首先调用它,否则,清除将无效。

请注意,在您当前的代码中,这对您不起作用,因为您没有正确绘制,因为您没有指定,迭代并绘制所有需要在其中绘制的行你的paintComponent方法。解决这个问题的方法是通过以下两种方式之一:

  • 创建List<Line2D>,例如ArrayList<Line2D>,将其填入MouseListener / MouseMotionListener代码,然后在paintComponent方法中遍历此List,绘制每一行。如果您执行此操作,则清除按钮的操作就是通过clear()清除列表并调用repaint()。不需要布尔值。
  • 或者您可以将线条绘制到BufferedImage上,然后通过g.drawImage(...)方法在paintComponent方法中绘制BufferedImage。如果这样做,请在绘图前始终检查图像是否为null。然后在鼠标监听代码中,您将绘制到此图像。在清除按钮操作中,您将创建一个新的BufferedImage,或清除当前的BufferedImage。

还要从paintComponent中删除setBackground(...)调用,因为它们实际上不应该在那里。

例如使用行的ArrayList:

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import java.util.List;

import javax.swing.*;

@SuppressWarnings("serial")
public class DrawPanelViaArrayList extends JPanel {
   private static final int PREF_W = 500;
   private static final int PREF_H = PREF_W;
   private static final Color LINES_COLOR = Color.black;
   private static final Color DRAW_LINE_COLOR = Color.pink;
   private static final Stroke STROKE = new BasicStroke(3f);
   private List<Line2D> lineList = new ArrayList<>();
   private int x1 = 0;
   private int y1 = 0;
   private int x2 = 0;
   private int y2 = 0;


   public DrawPanelViaArrayList() {
      MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
      addMouseListener(myMouseAdapter);
      addMouseMotionListener(myMouseAdapter);
      add(new JButton(new ClearAction("Clear")));
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D) g;

      // for smooth graphics
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

      // first draw the temporary line to show the user
      // where he's drawing
      if (x1 != x2 && y1 != y2) {
         g2.setColor(DRAW_LINE_COLOR);
         g2.drawLine(x1, y1, x2, y2);
      }

      // then draw all the lines held in the linesList.
      Stroke oldStroke = g2.getStroke();
      g2.setColor(LINES_COLOR);
      g2.setStroke(STROKE); // draw thicker lines
      for (Line2D line2d : lineList) {
         g2.draw(line2d);
      }
      g2.setStroke(oldStroke); // reset stroke
   }

   @Override
   public Dimension getPreferredSize() {
      if (isPreferredSizeSet()) {
         return super.getPreferredSize();
      }
      return new Dimension(PREF_W, PREF_H);
   }

   private class MyMouseAdapter extends MouseAdapter {
      @Override
      public void mousePressed(MouseEvent e) {
         x1 = e.getPoint().x;
         y1 = e.getPoint().y;
      }

      @Override
      public void mouseReleased(MouseEvent e) {
         x2 = e.getPoint().x;
         y2 = e.getPoint().y; 
         Line2D line = new Line2D.Double(x1, y1, x2, y2);
         // add line to ArrayList
         lineList.add(line);
         x1 = x2 = y1 = y2 = 0;
         repaint();
      }

      @Override
      public void mouseDragged(MouseEvent e) {
         x2 = e.getPoint().x;
         y2 = e.getPoint().y; 
         // draw temporary line
         repaint();
      }
   }

   private class ClearAction extends AbstractAction {
      public ClearAction(String name) {
         super(name);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         lineList.clear();
         repaint();
      }
   }

   private static void createAndShowGui() {
      JFrame frame = new JFrame("Foo");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new DrawPanelViaArrayList());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

那是什么,一个BufferedImage版本

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;

import javax.swing.*;

@SuppressWarnings("serial")
public class DrawPanelViaBufferedImage extends JPanel {
   private static final int PREF_W = 500;
   private static final int PREF_H = PREF_W;
   private static final Color LINES_COLOR = Color.black;
   private static final Color DRAW_LINE_COLOR = Color.pink;
   public static final Color CLEAR_COLOR = new Color(0, 0, 0, 0);
   public static final Stroke STROKE = new BasicStroke(3f);
   private int x1 = 0;
   private int y1 = 0;
   private int x2 = 0;
   private int y2 = 0;
   private BufferedImage img = new BufferedImage(PREF_W, PREF_W, BufferedImage.TYPE_INT_ARGB);


   public DrawPanelViaBufferedImage() {
      MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
      addMouseListener(myMouseAdapter);
      addMouseMotionListener(myMouseAdapter);
      add(new JButton(new ClearAction("Clear")));

      // if the GUI is to be re-sizeable, then consider adding a 
      // ComponentListener here, and resizing the BufferedImage in it
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D) g;

      // for smooth graphics
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

      // first draw the temporary line to show the user
      // where he's drawing
      if (x1 != x2 && y1 != y2) {
         g2.setColor(DRAW_LINE_COLOR);
         g2.drawLine(x1, y1, x2, y2);
      }

      // then draw the BufferedImage if not null
      if (img != null) {
         g2.drawImage(img, 0, 0, null);
      }
   }

   // size of our GUI
   @Override
   public Dimension getPreferredSize() {
      if (isPreferredSizeSet()) {
         return super.getPreferredSize();
      }
      return new Dimension(PREF_W, PREF_H);
   }

   private class MyMouseAdapter extends MouseAdapter {
      @Override
      public void mousePressed(MouseEvent e) {
         x1 = e.getPoint().x;
         y1 = e.getPoint().y;
      }

      @Override
      public void mouseReleased(MouseEvent e) {
         x2 = e.getPoint().x;
         y2 = e.getPoint().y; 
         Line2D line = new Line2D.Double(x1, y1, x2, y2);

         // draw to the BufferedImage
         Graphics2D g2 = img.createGraphics();
         g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
         g2.setStroke(STROKE);
         g2.setColor(LINES_COLOR);
         g2.draw(line);
         g2.dispose();
         x1 = x2 = y1 = y2 = 0;
         repaint();
      }

      @Override
      public void mouseDragged(MouseEvent e) {
         x2 = e.getPoint().x;
         y2 = e.getPoint().y; 
         repaint();
      }
   }

   private class ClearAction extends AbstractAction {
      public ClearAction(String name) {
         super(name);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         Graphics2D g2 = img.createGraphics();
         g2.setBackground(CLEAR_COLOR);
         g2.clearRect(0, 0, getWidth(), getHeight());
         g2.dispose();
         repaint();
      }
   }

   private static void createAndShowGui() {
      JFrame frame = new JFrame("Foo");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new DrawPanelViaBufferedImage());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

答案 1 :(得分:0)

你应该{J} setBackground(Color.red);在你的JPanel上调用它而不是JFrame

答案 2 :(得分:0)

我认为您的actionPerformedmousePressed都是同时执行的。如果mousePressed是来源,if mousePressed内的btnClear()条件也会满足repaint。因此,无论如何都会调用{{1}}方法,并且您看不到任何更改。