Java绘图应用:动态设置Graphics2D笔触宽度不影响已有图形
问题解决:Java绘图应用中笔触宽度仅对新图形生效
问题说明
开发Java绘图应用时,添加了取值范围1-20、默认值1的滑块动态修改笔触宽度,新宽度能正常更新,但会影响所有已绘制图形。已将每个图形的笔触权重存储在集合中,需要修改代码让新笔触宽度仅对新建图形生效。
修改步骤
- 存储新图形的笔触设置:创建新图形时,将当前
strokeSize转换为BasicStroke对象,存入shapeStrokeSize集合(原代码中相关代码被注释,需启用并修正类型)。 - 绘制时应用对应图形的笔触:移除全局统一设置笔触的代码,在绘制每个图形前,从
shapeStrokeSize中取出该图形对应的笔触设置。 - 修正画笔工具的尺寸:让画笔工具的绘制尺寸跟随当前滑块设置的笔触宽度,而非固定值。
关键代码修改点
1. 存储新图形的笔触
在mouseReleased和mouseDragged方法中,替换原注释代码:
// 存储当前笔触设置为BasicStroke对象 shapeStrokeSize.add(new BasicStroke(strokeSize));
2. 绘制时应用对应笔触
在paint方法中,移除全局笔触设置,并在循环内为每个图形设置对应笔触:
// 移除这行全局统一设置 // graphSettings.setStroke(new BasicStroke(strokeSize)); // 循环内添加该行,为每个图形应用专属笔触 for(Shape s : shapes) { graphSettings.setStroke(strokeSizeCounter.next()); // ...其余绘制代码 }
3. 修正画笔工具的尺寸
在mouseDragged的画笔逻辑中,将固定尺寸改为当前strokeSize:
aShape = drawBrush(x, y, strokeSize, strokeSize);
修改后的完整代码
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; 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(new BasicStroke(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, strokeSize, strokeSize); shapes.add(aShape); shapeFill.add(fillColor); shapeStroke.add(strokeColor); transPercent.add(transparentVal); // 存储当前笔触设置 shapeStrokeSize.add(new BasicStroke(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.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); // 预览时使用当前设置的笔触 graphSettings.setStroke(new BasicStroke(strokeSize)); 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(); } } } }
内容的提问来源于stack exchange,提问作者Petarnan
相关产品推荐
相关产品推荐

