简体   繁体   中英

How can I set the stroke color at runtime in JAVA?

I'm trying to create an interface where the user can change the color of a line to mark what is background or what is foreground of an image. So far I have coded this:

private class ImageLine extends JComponent 
{

    java.awt.Point p1,p2;
    BufferedImage show;
    ArrayList <Shape> shapes = new ArrayList<Shape>();
    int flag = 0;
    Color color = Color.ORANGE;


    public ImageLine(BufferedImage img)
    {
        show = img;
        setPreferredSize(new Dimension(img.getWidth(), img.getHeight()));
        this.addMouseListener
        (
                new MouseAdapter()
                {
                    @Override
                    public void mousePressed(MouseEvent e)
                    {
                        p1 = e.getPoint();

                    }

                    @Override
                    public void mouseReleased(MouseEvent e)
                    {
                       p2 = e.getPoint();
                       Shape r = createLine(p1.x,p1.y,e.getX(),e.getY());

                       shapes.add(r);
                       repaint();


                    }

                    @Override
                    public void mouseDragged(MouseEvent e)
                    {

                        mouseReleased(e);
                        repaint();

                    }


                }


        );

        this.addKeyListener(

                new KeyAdapter()
                        {


                            @Override
                            public void keyPressed(KeyEvent e)
                            {

                                if(e.getKeyChar() == 'b')
                                {

                                    color = Color.GREEN;
                                    System.out.println("bck");

                                }
                                if(e.getKeyChar() == 'f')
                                {

                                    color = Color.RED;
                                    System.out.println("fgr");


                                }


                            }





                        }







        );

       this.setFocusable(true);


    }


    private Line2D.Float createLine(int x1, int y1, int x2, int y2) 
    {
          return new Line2D.Float(x1,y1 ,x2, y2);
    }    

Until this part everything works fine , my real problem comes when I try to override the paintComponent() method, here actually I dont know exactly how to set the color as the keylistener indicates, in this case if the user press the "b" key the color of the line has to change to green, in the other hand if the user press the "f" key the color of the line has to change to red, also if the user draws differents lines , these lines have to remain shown. I have tried with this code without sucess:

public void paintComponent(Graphics g) {
      Graphics2D g2 = (Graphics2D) g;
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
      g2.setStroke(new BasicStroke(10));
      g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.50f));

      for (Shape s : shapes) {
        //g2.setPaint(Color.BLACK);
        g2.draw(s);
        g2.setPaint(color);
        //g2.fill(s);
      }

      if (p1 != null && p2 != null) {
        g2.setPaint(Color.CYAN);
        Shape r = createLine(p1.x, p1.y, p2.x, p2.y);
        g2.draw(r);
      }
    }

But the result is not what I want, I paint the lines and change the color, but when this happen , the lines I drew before change it´s color automatically to the color selected, and they dont keep it's "original color". Any sugestions? Thanks in advance.

There are a few ways you might be able to achieve this, I kind of like the idea of marrying the Shape and Color together into a single object, but this might present more work as you add more shapes.

Another solution might be to use a Map to simply map the line to a color, for example

线

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class DrawLines {

    public static void main(String[] args) {
        new DrawLines();
    }

    public DrawLines() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private Line2D currentLine;
        private Map<Shape, Color> mapColors;

        private Color currentColor;

        private List<Shape> shapes;

        public TestPane() {

            mapColors = new HashMap<>(25);
            shapes = new ArrayList<>(25);

            InputMap inputMap = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
            ActionMap actionMap = getActionMap();

            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_F, 0), "foreground");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_B, 0), "background");

            actionMap.put("foreground", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    currentColor = Color.GREEN;
                    if (currentLine != null) {
                        mapColors.put(currentLine, currentColor);
                        repaint();
                    }
                }
            });
            actionMap.put("background", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    currentColor = Color.RED;
                    if (currentLine != null) {
                        mapColors.put(currentLine, currentColor);
                        repaint();
                    }
                }
            });

            MouseAdapter ma = new MouseAdapter() {

                private Point p1, p2;

                @Override
                public void mousePressed(MouseEvent e) {
                    p1 = e.getPoint();
                    currentLine = null;
                }

                @Override
                public void mouseReleased(MouseEvent e) {
                    p2 = e.getPoint();
                    if (currentLine == null) {
                        currentLine = createLine(p1.x, p1.y, e.getX(), e.getY());
                    } else {
                        currentLine.setLine(p1, p2);
                    }

                    mapColors.put(currentLine, currentColor);
                    shapes.add(currentLine);
                    repaint();                  
                }

                @Override
                public void mouseDragged(MouseEvent e) {
                    p2 = e.getPoint();
                    if (currentLine == null) {
                        currentLine = createLine(p1.x, p1.y, e.getX(), e.getY());
                    } else {
                        currentLine.setLine(p1, p2);
                    }

                    repaint();
                }

                private Line2D.Float createLine(int x1, int y1, int x2, int y2) {
                    return new Line2D.Float(x1, y1, x2, y2);
                }
            };

            addMouseListener(ma);
            addMouseMotionListener(ma);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            for (Shape shape : shapes) {
                Color color = mapColors.get(shape);
                if (color == null) {
                    color = Color.BLACK;
                }
                g2d.setColor(color);
                g2d.draw(shape);
            }

            if (currentLine != null) {
                Color color = mapColors.get(currentLine);
                if (color == null) {
                    color = currentColor;
                }
                g2d.setColor(color);
                g2d.draw(currentLine);
            }
            g2d.dispose();
        }

    }

}

Also, I avoid using KeyListener and use the key bindings API instead, it's less troublesome

See How to Use Key Bindings for more details

Check out Custom Painting Approaches .

You would want to use the DrawOnImage approach. It uses a ColoredRectangle class to store information of the color and the Rectangle. Then in the paintComponent() method is loops through all the ColoredRectangle classes and paints the Rectangle.

You will need to add logic to change the Color of a selected Rectangle.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM