【问题标题】:Boolean not keeping value布尔值不保持值
【发布时间】:2015-02-17 17:44:32
【问题描述】:

我有一个用户画线的应用程序。有一个JButton btnClear,当用户点击时,必须清除绘图,以便用户重新绘制。我在 btnClear 上使用 ActionListener 来了解它何时被点击。我设置了一个布尔值 Clear,以便在 paintComponent() 中执行正确的 IF 语句。然而,布尔 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) {}
}

【问题讨论】:

    标签: java swing graphics boolean


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      我认为您的actionPerformedmousePressed 都是同时执行的。在mousePressed 中,如果btnClear() 是源,则mousePressed 内的if 条件也满足。所以repaint 方法还是被调用了,你看不到任何变化。

      【讨论】:

        【解决方案3】:

        您没有在您的paintComponent 方法覆盖中调用super.paintComponent(g) 方法。先调用这个,否则 clear 不起作用。

        请注意,在您当前的代码中,这对您不起作用,因为您没有指定、迭代和绘制 所有 需要在其中绘制的线条,因此绘制不正确你的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();
                 }
              });
           }
        }
        

        【讨论】:

        • 使用 super.paintComponent(g),当我画一条线时,它会清除已经存在的线(用户必须能够画尽可能多的线)。
        • @Phantom:然后您需要创建 Line2D 的 ArrayList 或绘制到由 clear 清除的 BufferedImage。
        • @Phantom:有关使用 Line2D 的 ArrayList 的示例,请参阅上面的代码。
        • @Phantom:请参阅编辑以回答,希望能澄清我上面所说的内容。
        猜你喜欢
        • 1970-01-01
        • 2021-07-22
        • 2020-09-26
        • 1970-01-01
        • 1970-01-01
        • 2013-03-31
        • 2022-08-18
        • 2017-04-08
        • 1970-01-01
        相关资源
        最近更新 更多