Java:在 ActionListener 中使用图形组件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21421150/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java: Using graphics component within an ActionListener
提问by robert825
I have two separate class and driver files, and in the class file I create the paint method:
我有两个单独的类和驱动程序文件,在类文件中我创建了paint方法:
public void paint(Graphics g){
g.drawLine(......
....
//along with all of my other draw commands
}
Further down in the code, I create a JButton and within this button's action listener I don't know how to use a Graphics object to create more graphics in the JFrame. Should I be adding something to my driver to make this happen, or is there a way to use these graphics within my action listener? Thank you, and any help is appreciated.
在代码的更深处,我创建了一个 JButton,在这个按钮的动作侦听器中,我不知道如何使用 Graphics 对象在 JFrame 中创建更多图形。我应该向我的驱动程序添加一些东西来实现这一点,还是有办法在我的动作侦听器中使用这些图形?谢谢,任何帮助表示赞赏。
采纳答案by Paul Samsotha
You need to draw everything within the paint
method. The actionPerformed
should only change the state of something alreadyin the paint
method, and then call repaint
. For example
您需要在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);
}
Then in your actionPerformed
, you can change the state of drawWorld
to true
and call repaint()
.
然后在 your 中actionPerformed
,您可以更改drawWorld
totrue
和 call的状态repaint()
。
public void actionPerformed(ActionEvent e) {
drawWorld = true;
repaint();
}
So as you can see, everything should be drawn in the paintComponent
method. You can just hide and paint renderings, and make them "visible"from a action command. You should already have predefined what could posibly be drawn. Then just change the state of it rendering
如您所见,所有内容都应在paintComponent
方法中绘制。您可以隐藏和绘制渲染,并通过操作命令使它们“可见”。您应该已经预定义了可能绘制的内容。然后只需更改它渲染的状态
And as @MadPrgrammer pointed out, you should not be painting on top-level containers like JFrame
. Instead paint on a custom JPanel
or JComponent
and override the paintComponent
method, instead of JFrame
and paint
正如@MadPrgrammer 指出的那样,您不应该在像JFrame
. 而是绘制自定义JPanel
或JComponent
并覆盖paintComponent
方法,而不是JFrame
和paint
Here's an example where I draw a new square every time the button is pressed. If look at the code, you will see that in the paintComponent
method, I loop through a list of Square
s and draw them, and in the actionPerformed
all I do is add a new Square
to the List
and call repaint()
这是一个示例,每次按下按钮时我都会绘制一个新方块。如果查看代码,您会看到在paintComponent
方法中,我遍历了一个Square
s列表并绘制了它们,而actionPerformed
我所做的就是向s中添加一个新Square
的List
并调用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<Square> 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();
}
});
}
}
回答by MadProgrammer
It's difficult to be 100%, but it would seem as you don't understand how custom painting is performed in Swing.
很难做到 100%,但似乎您不了解如何在 Swing 中执行自定义绘画。
Start by taking a look at Performing Custom Paintingand Painting in AWT and Swing.
首先查看在 AWT 和 Swing中执行自定义绘画和绘画。
Essentially, painting is arranged by the Repaint Manager, which decides what and when something should be painted. It then calls (through a chain of methods) the paint
method of the components it thinks need to be updated, passing it a reference to a Graphics
context that should be used to actually paint on.
本质上,绘画是由重绘管理器安排的,它决定什么以及什么时候应该绘画。然后它调用(通过一系列方法)paint
它认为需要更新的组件的方法,将它传递给Graphics
应该用于实际绘制的上下文的引用。
Basically, when ever your paint method is called, you should create paint the current state of your painting.
基本上,当你的paint方法被调用时,你应该创建paint你的绘画的当前状态。
You should avoid overriding paint
and instead use paintComponent
from classes the extend JComponent
您应该避免覆盖paint
,而是paintComponent
从类中使用扩展JComponent
回答by Radiodef
Your question is a little on the vague side as to what you are actually wondering about but generally speaking:
您的问题对于您实际想知道的内容有点含糊,但总的来说:
- We don't override
paint
in Swing, we overridepaintComponent
.
- 我们不会
paint
在 Swing 中覆盖,我们会覆盖paintComponent
.
If you are already aware of this, you may be overriding paint
because you are doing it on a JFrame and you found that JFrame does not have a paintComponent
method. You shouldn't override paint
on a JFrame. Instead, create a JPanel or something to put inside the frame and override paintComponent
on the panel.
如果您已经意识到这一点,您可能会覆盖,paint
因为您是在 JFrame 上执行此操作,并且您发现 JFrame 没有paintComponent
方法。您不应该覆盖paint
JFrame。相反,创建一个 JPanel 或其他东西放在框架内并覆盖paintComponent
在面板上。
- Question about the ActionListener.
- 关于 ActionListener 的问题。
It sounds like you are wanting to do painting outside of paintComponent
in which case probably the best way is to do painting to a separate Image. Then you paint the Image on to the panel in paintComponent
. You can also put an Image in a JLabel as an ImageIcon. Here is a very simple drawing program using MouseListener that demonstrates this (taken from here):
听起来您想在外面进行绘画,paintComponent
在这种情况下,最好的方法可能是对单独的图像进行绘画。然后将图像绘制到面板上paintComponent
。您还可以将图像作为 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 has already linked to the articles that I was going to link to.
@MadProgrammer 已经链接到我要链接到的文章。