如何在KeyListener中设置g.setColor()以修改后续绘制的圆和线条颜色?
问题
我编写了一段Java Swing代码,可根据用户点击位置绘制圆并连接线条。默认颜色为黑色,希望用户通过输入r、b、g、l(对应红、蓝、绿、黑)设置后续绘制的圆和线条颜色。已在KeyTyped方法中为对应字符设置if/else语句,请问该方法内需要编写什么代码实现此功能?
原代码如下:
import java.awt.Color; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Point; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.util.ArrayList; import java.util.List; import javax.swing.JFrame; import javax.swing.JPanel; public class Circle extends JPanel implements MouseListener, KeyListener, MouseMotionListener { private List<Point> points; public static void main(String[] args) { EventQueue.invokeLater(() -> new Circle().buildAndDisplayGui()); } public Circle() { points = new ArrayList<>(); setPreferredSize(new Dimension(500, 500)); setBackground(Color.white); addMouseListener(this); } private void buildAndDisplayGui() { JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(this); frame.pack(); frame.setLocationByPlatform(true); frame.setVisible(true); frame.addKeyListener(this); } protected void paintComponent(Graphics g) { super.paintComponent(g); g.setColor(Color.black); int count = points.size(); for (int i = 0; i < count; i++) { Point pt0 = points.get(i); g.fillOval(pt0.x - 10, pt0.y - 11, 20, 20); if (i > 0) { Point pt1 = points.get(i - 1); g.drawLine(pt1.x, pt1.y, pt0.x, pt0.y); } } } @Override public void mouseClicked(MouseEvent e) { //Prints the coordinates of the clicks System.out.println("X: " + e.getX() + " Y: " + e.getY()); Point pt = new Point(e.getX(), e.getY()); points.add(pt); repaint(); } @Override public void mouseEntered(MouseEvent e) { // Do nothing. } @Override public void mouseExited(MouseEvent e) { // Do nothing. } @Override public void mousePressed(MouseEvent e) { // Do nothing. } @Override public void mouseReleased(MouseEvent e) { // Do nothing. } @Override public void mouseDragged(MouseEvent e) { } @Override public void mouseMoved(MouseEvent e) { } @Override public void keyTyped(KeyEvent e) { if (e.getKeyChar() == 'r') { //Sets the color of the next circle and lines to red } else { if (e.getKeyChar() == 'b') { //Sets the color of the next circle and lines to blue } else { if (e.getKeyChar() == 'g') { //Sets the color of the next circle and lines to green } else { if (e.getKeyChar() == 'l') { //Sets the color of the next circle and lines to black } } } } } @Override public void keyPressed(KeyEvent e) { // TODO Auto-generated method stub } @Override public void keyReleased(KeyEvent e) { // TODO Auto-generated method stub } }
当前输出效果:
期望输出效果(用户点击两次后按“r”再点击两次):
解决方案
要实现按按键切换后续绘制颜色的功能,需要补充以下核心逻辑并修改相关代码:
1. 添加颜色管理成员变量
需要新增两个变量:
currentColor:保存当前选中的绘制颜色,默认设为黑色colorList:和点列表points一一对应,记录每个点的绘制颜色
2. 完善keyTyped方法
在每个字符判断分支中,直接给currentColor赋值对应颜色,同时简化嵌套的if结构:
@Override public void keyTyped(KeyEvent e) { if (e.getKeyChar() == 'r') { currentColor = Color.RED; } else if (e.getKeyChar() == 'b') { currentColor = Color.BLUE; } else if (e.getKeyChar() == 'g') { currentColor = Color.GREEN; } else if (e.getKeyChar() == 'l') { currentColor = Color.BLACK; } }
3. 修改鼠标点击逻辑
添加点的同时,把当前颜色同步加入colorList:
@Override public void mouseClicked(MouseEvent e) { System.out.println("X: " + e.getX() + " Y: " + e.getY()); Point pt = new Point(e.getX(), e.getY()); points.add(pt); colorList.add(currentColor); repaint(); }
4. 调整绘制逻辑
在paintComponent中,根据每个点对应的颜色绘制圆和连线:
protected void paintComponent(Graphics g) { super.paintComponent(g); int count = points.size(); for (int i = 0; i < count; i++) { Color color = colorList.get(i); g.setColor(color); Point pt0 = points.get(i); g.fillOval(pt0.x - 10, pt0.y - 11, 20, 20); if (i > 0) { Point pt1 = points.get(i - 1); g.drawLine(pt1.x, pt1.y, pt0.x, pt0.y); } } }
修改后的完整代码
import java.awt.Color; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Point; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.util.ArrayList; import java.util.List; import javax.swing.JFrame; import javax.swing.JPanel; public class Circle extends JPanel implements MouseListener, KeyListener, MouseMotionListener { private List<Point> points; private List<Color> colorList; private Color currentColor; public static void main(String[] args) { EventQueue.invokeLater(() -> new Circle().buildAndDisplayGui()); } public Circle() { points = new ArrayList<>(); colorList = new ArrayList<>(); currentColor = Color.BLACK; setPreferredSize(new Dimension(500, 500)); setBackground(Color.white); addMouseListener(this); } private void buildAndDisplayGui() { JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(this); frame.pack(); frame.setLocationByPlatform(true); frame.setVisible(true); frame.addKeyListener(this); } protected void paintComponent(Graphics g) { super.paintComponent(g); int count = points.size(); for (int i = 0; i < count; i++) { Color color = colorList.get(i); g.setColor(color); Point pt0 = points.get(i); g.fillOval(pt0.x - 10, pt0.y - 11, 20, 20); if (i > 0) { Point pt1 = points.get(i - 1); g.drawLine(pt1.x, pt1.y, pt0.x, pt0.y); } } } @Override public void mouseClicked(MouseEvent e) { System.out.println("X: " + e.getX() + " Y: " + e.getY()); Point pt = new Point(e.getX(), e.getY()); points.add(pt); colorList.add(currentColor); repaint(); } @Override public void mouseEntered(MouseEvent e) {} @Override public void mouseExited(MouseEvent e) {} @Override public void mousePressed(MouseEvent e) {} @Override public void mouseReleased(MouseEvent e) {} @Override public void mouseDragged(MouseEvent e) {} @Override public void mouseMoved(MouseEvent e) {} @Override public void keyTyped(KeyEvent e) { if (e.getKeyChar() == 'r') { currentColor = Color.RED; } else if (e.getKeyChar() == 'b') { currentColor = Color.BLUE; } else if (e.getKeyChar() == 'g') { currentColor = Color.GREEN; } else if (e.getKeyChar() == 'l') { currentColor = Color.BLACK; } } @Override public void keyPressed(KeyEvent e) {} @Override public void keyReleased(KeyEvent e) {} }
效果说明
修改后,初始绘制为黑色;按r键后,后续点击的圆和连线变为红色;按b切换蓝色,g切换绿色,l切回黑色,完全符合期望的输出效果。
内容的提问来源于stack exchange,提问作者user20483070
相关产品推荐
相关产品推荐

