Java:在ActionListener中使用图形组件

我有两个单独的类和驱动程序文件,在类文件中我创建了paint方法:

public void paint(Graphics g){ g.drawLine(...... .... //along with all of my other draw commands } 

在代码中,我创建了一个JButton,在这个按钮的动作监听器中,我不知道如何使用Graphics对象在JFrame中创建更多图形。 我应该向我的驱动程序添加一些内容以实现这一点,还是有办法在我的动作监听器中使用这些图形? 谢谢,任何帮助表示赞赏。

您需要在paint方法中绘制所有内容。 actionPerformed只应该改变paint方法中已有的东西的状态,然后调用repaint 。 例如

 boolean drawHello = true; boolean drawWorld = false; protected void paintComponent(Graphics g) { super.paintCompoent(g); if (drawHello) g.drawString("Hello", 50, 50); if (drawWorld) g.drawString("World", 10, 10); } 

然后在actionPerformed ,您可以将drawWorld的状态drawWorldtrue并调用repaint()

 public void actionPerformed(ActionEvent e) { drawWorld = true; repaint(); } 

如您所见,应该在paintComponent方法中绘制所有内容。 您可以隐藏和绘制渲染图,并使其从动作命令中“可见” 。 您应该已经预定了可以绘制的内容。 然后只需更改渲染的状态即可

正如@MadPrgrammer所指出的那样,你不应该在像JFrame这样的顶级容器上绘画。 而是在自定义JPanelJComponent并覆盖paintComponent方法,而不是JFramepaint

这是一个示例,每次按下按钮时我都会绘制一个新的方块。 如果查看代码,你会看到在paintComponent方法中,我遍历一个Square s列表并绘制它们,并且在actionPerformed我所做的就是在List添加一个新的Square并调用repaint()

在此处输入图像描述

 import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.List; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingUtilities; public class AddSquares { private int R = 0; private int G = 0; private int B = 0; private int xLoc = 0; private int yLoc = 0; List squares = new ArrayList<>(); private JButton addSquare = new JButton("Add Square"); private RectsPanel panel = new RectsPanel(); public AddSquares() { addSquare.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { Color color = new Color(R, G, B); squares.add(new Square(xLoc, yLoc, color)); panel.repaint(); R += 10; G += 20; B += 30; xLoc += 20; yLoc += 20; } }); JFrame frame = new JFrame("Draw Squares"); frame.add(panel, BorderLayout.CENTER); frame.add(addSquare, BorderLayout.SOUTH); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setVisible(true); } private class RectsPanel extends JPanel { @Override protected void paintComponent(Graphics g) { super.paintComponent(g); for (Square square : squares) { square.drawSquare(g); } } @Override public Dimension getPreferredSize() { return new Dimension(250, 250); } } private class Square { int x = 0; int y = 0; Color color; public Square(int x, int y, Color color) { this.x = x; this.y = y; this.color = color; } public void drawSquare(Graphics g) { g.setColor(color); g.fillRect(x, y, 75 ,75); } } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { AddSquares addSquares = new AddSquares(); } }); } } 

很难100%,但看起来你不明白在Swing中如何进行自定义绘画。

首先来看看在AWT和Swing中执行自定义绘画和绘画 。

从本质上讲,绘画是由重绘经理安排的,它决定什么时候应该画什么。 然后它(通过一系列方法)调用它认为需要更新的组件的paint方法,向它传递一个应该用于实际绘制的Graphics上下文的引用。

基本上,当你调用paint方法时,你应该创建绘画当前绘画状态。

您应该避免覆盖paint ,而是使用扩展JComponent类中的paintComponent

关于你实际想知道的问题,你的问题有点模糊,但一般来说:

  • 我们不会在Swing中覆盖paint ,我们覆盖paintComponent

如果你已经意识到这一点,你可能会重写paint因为你是在JFrame上进行的,并且你发现JFrame没有paintComponent方法。 您不应该覆盖JFrame上的paint 。 相反,创建一个JPanel或其他东西放在框架内并覆盖面板上的paintComponent

  • 有关ActionListener的问题。

听起来你想要在paintComponent之外进行绘画,在这种情况下,最好的方法可能是绘制到单独的Image。 然后将图像绘制到paintComponent的面板上。 您还可以将Image作为ImageIcon放在JLabel中。 这是一个非常简单的绘图程序,使用MouseListener来演示这个(取自这里 ):

 import javax.swing.*; import java.awt.*; import java.awt.image.*; import java.awt.event.*; class PaintAnyTime { public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { new PaintAnyTime(); } }); } final BufferedImage image = ( new BufferedImage(500, 500, BufferedImage.TYPE_INT_ARGB) ); final JFrame frame = new JFrame(); final JLabel label = new JLabel(new ImageIcon(image)); final MouseAdapter drawer = new MouseAdapter() { Graphics2D g2D; @Override public void mousePressed(MouseEvent me) { g2D = image.createGraphics(); g2D.setColor(Color.BLACK); } @Override public void mouseDragged(MouseEvent me) { g2D.fillRect(me.getX(), me.getY(), 3, 3); label.repaint(); } @Override public void mouseReleased(MouseEvent me) { g2D.dispose(); g2D = null; } }; PaintAnyTime() { label.setPreferredSize( new Dimension(image.getWidth(), image.getHeight()) ); label.addMouseListener(drawer); label.addMouseMotionListener(drawer); frame.add(label); frame.pack(); frame.setResizable(false); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } } 

@MadProgrammer已经链接到我要链接到的文章。