java Graphics2D 动态设置描边宽度

问题描述 投票:0回答:1

我有 Java Paint 应用程序的代码。 我添加了一个从 1 更改为 20 的滑块,默认大小为 1。此滑块用于动态更改描边大小,因此我创建了一个变量描边大小值和滑块 + 侦听器,新的描边大小会更新并正常工作很好,但它会更新数组中添加的所有形状。即使对于已经绘制的形状也是如此。 我将各个笔画粗细与对象一起保存在多维数组中。 我如何更改它,以便它不会更新数组中的所有形状,并且仅对新创建的形状有效?

我猜这行造成了问题: graphSettings.setStroke(StrokeSizeCounter.next());

谢谢

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import java.awt.event.*;
import java.awt.*;
import java.awt.geom.*;
import java.text.DecimalFormat;
import java.util.*;

@SuppressWarnings("serial")
public class Lesson48 extends JFrame{
    
    JButton brushBut, lineBut, ellipseBut, rectBut, strokeBut, fillBut;
    
    JSlider transSlider;
    
    JLabel transLabel;
    
    DecimalFormat dec = new DecimalFormat("#.##");
    
    JSlider strokeSizeSlider;
    
    JLabel strokeSizeLabel;
    
    Graphics2D graphSettings;
    
    int strokeSize;
    
    //graphSettings.setStroke(new BasicStroke(5f));
    
    int currentAction = 1;
    
    float transparentVal = 1.0f;
    
    Color strokeColor = Color.BLACK, fillColor = Color.BLACK;
    
    public static void main(String[] args) {
        
        new Lesson48();
        
    }
    
    public Lesson48() {
        
        this.setSize(1000, 600);
        this.setTitle("Java Paint");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        JPanel buttonPanel = new JPanel();
        
        Box theBox = Box.createHorizontalBox();
        
        brushBut = makeMeButtons("./src/Brush.png", 1);
        lineBut = makeMeButtons("./src/Line.png", 2);
        ellipseBut = makeMeButtons("./src/Ellipse.png", 3);
        rectBut = makeMeButtons("./src/Rectangle.png", 4);
        
        strokeBut = makeMeColorButton("./src/Stroke.png", 5, true);
        fillBut = makeMeColorButton("./src/Fill.png", 6, false);
        
        theBox.add(brushBut);
        theBox.add(lineBut);
        theBox.add(ellipseBut);
        theBox.add(rectBut);
        theBox.add(strokeBut);
        theBox.add(fillBut);
        
        transLabel = new JLabel("  Transparent: 1");
        
        transSlider = new JSlider(1, 99, 99);
        
        ListenerForSlider lForSlider = new ListenerForSlider();
        
        transSlider.addChangeListener(lForSlider);
        
        theBox.add(transLabel);
        theBox.add(transSlider);
        
        // changing the strokeSize dynamically
        
        strokeSizeLabel = new JLabel("  Stroke: 1");
        
        strokeSizeSlider = new JSlider(1, 20, 1);
        
        ListenerForSlider2 sForSlider = new ListenerForSlider2();
        
        strokeSizeSlider.addChangeListener(sForSlider);
        
        theBox.add(strokeSizeLabel);
        theBox.add(strokeSizeSlider);
        
        buttonPanel.add(theBox);
        
        this.add(buttonPanel, BorderLayout.SOUTH);
        
        this.add(new DrawingBoard(), BorderLayout.CENTER);
        
        this.setVisible(true);
        
    }
    
    public JButton makeMeButtons(String iconFile, final int actionNum) {
        
        JButton theBut = new JButton();
        Icon butIcon = new ImageIcon(iconFile);
        theBut.setIcon(butIcon);
        
        theBut.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                currentAction = actionNum;
            }
            
        });
        
        return theBut;
        
    }
    
    public JButton makeMeColorButton(String iconFile, final int actionNum, final boolean stroke) {
        
        JButton theBut = new JButton();
        Icon butIcon = new ImageIcon(iconFile);
        theBut.setIcon(butIcon);
        
        theBut.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                if(stroke) {
                    strokeColor = JColorChooser.showDialog(null, "Pick a Stroke", Color.BLACK);
                } else {
                    fillColor = JColorChooser.showDialog(null, "Pick a Fill", Color.BLACK);
                }
            }
            
        });
        
        return theBut;
        
    }
    
    private class DrawingBoard extends JComponent{
        
        ArrayList<Shape> shapes = new ArrayList<Shape>();
        ArrayList<Color> shapeFill = new ArrayList<Color>();
        ArrayList<Color> shapeStroke = new ArrayList<Color>();
        
        ArrayList<Float> transPercent = new ArrayList<Float>();
        
        ArrayList<Stroke> shapeStrokeSize = new ArrayList<Stroke>();
        
        Point drawStart, drawEnd;
        
        public DrawingBoard() {
            
            this.addMouseListener(new MouseAdapter() {
                
                public void mousePressed(MouseEvent e) {
                    
                    if(currentAction != 1) {
                    
                    drawStart = new Point(e.getX(), e.getY());
                    drawEnd = drawStart;
                    repaint();
                    }
                }
                
                public void mouseReleased(MouseEvent e) {
                    
                    if(currentAction != 1) {
                        
                        Shape aShape = null;
                        
                        if(currentAction == 2) {
                            aShape = drawLine(drawStart.x, drawStart.y, e.getX(), e.getY());
                        } else
                            
                        if(currentAction == 3) {
                            aShape = drawEllipse(drawStart.x, drawStart.y, e.getX(), e.getY());
                        } else
                            
                        if(currentAction == 4) {
                            aShape = drawRectangle(drawStart.x, drawStart.y, e.getX(), e.getY());
                        }
                        
                        shapes.add(aShape);
                        shapeFill.add(fillColor);
                        shapeStroke.add(strokeColor);
                        
                        transPercent.add(transparentVal);
                        
                        //shapeStrokeSize.add(strokeSize);
                        
                        drawStart = null;
                        drawEnd = null;
                        repaint();
                    }
                    
                }
                
            });
            
            this.addMouseMotionListener(new MouseMotionAdapter() {
                
                public void mouseDragged(MouseEvent e) {
                    
                    if(currentAction == 1) {
                        
                        int x = e.getX();
                        int y = e.getY();
                        
                        Shape aShape = null;
                        
                        strokeColor = fillColor;
                        
                        aShape = drawBrush(x, y, 2, 2);
                        
                        shapes.add(aShape);
                        shapeFill.add(fillColor);
                        shapeStroke.add(strokeColor);
                        
                        transPercent.add(transparentVal);
                        
                        //shapeStrokeSize.add(strokeSize);
                        
                    }
                    
                    drawEnd = new Point(e.getX(), e.getY());
                    repaint();
                }
                
            });
            
        }
        
        public void paint(Graphics g) {
            
            graphSettings = (Graphics2D)g;
            
            graphSettings.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            
            graphSettings.setStroke(new BasicStroke(strokeSize));
            
            Iterator<Color> strokeCounter = shapeStroke.iterator();
            Iterator<Color> fillCounter = shapeFill.iterator();
            
            Iterator<Float> transCounter = transPercent.iterator();
            
            Iterator<Stroke> strokeSizeCounter = shapeStrokeSize.iterator();
            
            for(Shape s : shapes) {
                
                //graphSettings.setStroke(strokeSizeCounter.next());
                //graphSettings.draw(s);
                
                graphSettings.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, transCounter.next()));
                
                graphSettings.setPaint(strokeCounter.next());
                graphSettings.draw(s);
                graphSettings.setPaint(fillCounter.next());
                graphSettings.fill(s);
            }
            
            if(drawStart != null && drawEnd != null) {
                
                graphSettings.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f));
                
                graphSettings.setPaint(Color.LIGHT_GRAY);
                
                Shape aShape = null;
                
                if(currentAction == 2) {
                    aShape = drawLine(drawStart.x, drawStart.y, drawEnd.x, drawEnd.y);
                } else
                    
                if(currentAction == 3) {
                    aShape = drawEllipse(drawStart.x, drawStart.y, drawEnd.x, drawEnd.y);
                } else
                    
                if(currentAction == 4) {
                    aShape = drawRectangle(drawStart.x, drawStart.y, drawEnd.x, drawEnd.y);
                }
                
                graphSettings.draw(aShape);
                
            }
            
        }
        
        private Rectangle2D.Float drawRectangle(int x1, int y1, int x2, int y2){
            
            int x = Math.min(x1, x2);
            int y = Math.min(y1, y2);
            
            int width = Math.abs(x1-x2);
            int height = Math.abs(y1-y2);
            
            return new Rectangle2D.Float(x, y, width, height);
            
        }
        
        private Ellipse2D.Float drawEllipse(int x1, int y1, int x2, int y2){
            
            int x = Math.min(x1, x2);
            int y = Math.min(y1, y2);
            
            int width = Math.abs(x1-x2);
            int height = Math.abs(y1-y2);
            
            return new Ellipse2D.Float(x, y, width, height);
            
        }
        
        private Line2D.Float drawLine(int x1, int y1, int x2, int y2){
            
            return new Line2D.Float(x1, y1, x2, y2);
            
        }
        
        private Ellipse2D.Float drawBrush(int x1, int y1, int brushStrokeWidth, int brushStrokeHeight){
            
            return new Ellipse2D.Float(x1, y1, brushStrokeWidth, brushStrokeHeight);
            
        }
        
    }
    
    private class ListenerForSlider implements ChangeListener{

        public void stateChanged(ChangeEvent e) {
            
            if(e.getSource() == transSlider) {
                
                transLabel.setText("  Transparent: " + dec.format(transSlider.getValue() * .01));
                
                transparentVal = (float) (transSlider.getValue() * .01);
                
            }
            
        }
        
    }
    
    private class ListenerForSlider2 implements ChangeListener{

        public void stateChanged(ChangeEvent e) {
            
            if(e.getSource() == strokeSizeSlider) {
                
                strokeSizeLabel.setText("  Stroke: " + strokeSizeSlider.getValue());
                
                strokeSize = strokeSizeSlider.getValue();
            }
            
        }
        
    }
    
}
java swing graphics2d stroke
1个回答
0
投票

如果这是我的项目,我会绘制到离屏缓冲区(BufferedImage),然后在我的绘画方法中显示该图像。这样,当前笔划宽度将仅用于最新的绘图。我也想:

  • 覆盖paintComponent,而不是paint
  • 在我的重写中调用super的绘画方法
  • 不是画点而是画线
  • 在鼠标侦听器的 mousePressed 方法中创建我的线条起点 (x1, y1)。
  • 在 mouseDragged(鼠标运动侦听器)和 mouseReleased 中的鼠标侦听器中的缓冲图像上创建并绘制一条新线
  • 对鼠标侦听器和鼠标运动侦听器使用 MouseAdapter。
  • 当首次创建当前行时,我会从 mousePressed 上的滑块中提取值
  • 从 mousePressed 上的缓冲图像创建我的 Graphics2D 对象
  • 并将其丢弃在 mouseReleased 上

例如:

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.awt.image.BufferedImage;

public class Lesson48b extends JPanel {
    private static final int BI_WIDTH = 1000;
    private static final int BI_HEIGHT = 600;
    private BufferedImage buffer;
    private JSlider strokeWidthSlider = new JSlider(0, 20, 1);
    private JButton cleaButton = new JButton("Clear");

    public Lesson48b() {
        // give the drawing a white background
        clearImage();

        strokeWidthSlider.setMajorTickSpacing(5);
        strokeWidthSlider.setMinorTickSpacing(1);
        strokeWidthSlider.setPaintTicks(true);
        strokeWidthSlider.setPaintLabels(true);
        strokeWidthSlider.setOpaque(false);
        add(strokeWidthSlider);

        cleaButton.addActionListener(e -> clearImage());
        add(cleaButton);

        MyMouse myMouse = new MyMouse();
        addMouseListener(myMouse);
        addMouseMotionListener(myMouse);
    }

    private void clearImage() {
        buffer = new BufferedImage(BI_WIDTH, BI_HEIGHT, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = buffer.createGraphics();
        g2d.setBackground(Color.WHITE);
        g2d.clearRect(0, 0, BI_WIDTH, BI_HEIGHT);
        g2d.dispose();
        repaint();
    }

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

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (buffer != null) {
            g.drawImage(buffer, 0, 0, this);
        }
    }

    class MyMouse extends MouseAdapter {
        private int x1, y1;
        Graphics2D g2d;

        public void mousePressed(MouseEvent e) {
            // set my x1 and y1 points for drawing.
            x1 = e.getX();
            y1 = e.getY();

            // create a graphics object to draw to
            g2d = buffer.createGraphics();

            // smooth the drawing
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

            // use the current stroke width value from the slider
            int strokeWidth = strokeWidthSlider.getValue();
            g2d.setStroke(new BasicStroke(strokeWidth, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));

            // generate a random color
            float hue = (float) Math.random();
            float saturation = (float) (0.5 * Math.random() + 0.5);
            float brightness = 1f;
            Color randomColr = Color.getHSBColor(hue, saturation, brightness);
            g2d.setColor(randomColr);

            // draw a single point
            g2d.drawLine(x1, y1, x1, y1);
            repaint();
        }

        public void mouseDragged(MouseEvent e) {
            if (g2d == null) {
                return;
            }
            // get the next point
            int x2 = e.getX();
            int y2 = e.getY();

            // draw a connecting line
            g2d.drawLine(x1, y1, x2, y2);

            // reset the points
            x1 = x2;
            y1 = y2;
            repaint();
        }

        public void mouseReleased(MouseEvent e) {
            if (g2d == null) {
                return;
            }
            int x2 = e.getX();
            int y2 = e.getY();

            g2d.drawLine(x1, y1, x2, y2);
            x1 = x2;
            y1 = y2;
            repaint();

            // dispose of the Graphics object
            g2d.dispose();
            g2d = null;
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                Lesson48b mainPanel = new Lesson48b();
                JFrame frame = new JFrame("Java Paint");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(mainPanel);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.