paintComponent 问题 Java - Swing
issues with paintComponent Java - Swing
我正在尝试编写一个 swing gui,我可以通过按下两个不同的 JMenuItem、圆形和矩形在随机位置绘制形状。
我让它工作了,但我用了
Graphics2D gg = (Graphics2D) canvas.getGraphics();
有人建议我使用并覆盖 paintComponent()。所以我几个小时前就开始尝试了:D
我知道有很多关于这个的问题,但我真的读了很多,尝试和搜索但我无法帮助自己..
请查看我的 RandomDrawer Class,我发现我必须在那里实现 paintComponent()(我希望至少如此)。
进一步在下一个方法
public void actionPerformed(ActionEvent e)
我开始知道发生了什么动作,我可以或者我怎样才能告诉他之后画画?还是我的整个方法有缺陷?
这是我的代码。
感谢您的包容,非常感谢。
package plotterpackage;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.Random;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.WindowConstants;
import javax.swing.border.BevelBorder;
import javax.swing.text.JTextComponent;
public class PlotterApp implements ComponentListener {
private JFrame frame;
private JPanel canvas;
private JPanel statusBar;
private JTextField status;
/**
* Public default constructor.
*/
public PlotterApp() {
initialize();
}
/**
* Start of the application.
* @param args command line arguments
*/
public static void main(String[] args) {
PlotterApp app = new PlotterApp();
app.start();
}
/**
* Initialize the application.
*/
protected void initialize() {
frame = new JFrame("Main");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setBounds(50,50, 50+640, 50+480);
frame.setBackground(Color.GREEN);
frame.setJMenuBar(createMenuBar());
frame.getContentPane().add(createContent(), BorderLayout.CENTER);
frame.getContentPane().add(createStatusBar(),BorderLayout.SOUTH);
}
/**
* Start the graphical user interface.
*/
public void start() {
// show the GUI
frame.setVisible(true);
status.setText("Application started");
}
/**-*
* Internal helper to create the main content.
* @return component with application content.
*/
protected JComponent createContent() {
canvas = new JPanel();
canvas.addMouseListener(new Painter());
canvas.addMouseMotionListener(new Painter());
canvas.addComponentListener(this);
canvas.setBackground(new Color(128,218,255));
canvas.setForeground(Color.RED);
canvas.setBorder(new BevelBorder(BevelBorder.LOWERED));
return canvas;
}
/**
* Internal helper to create the statusbar and -fields.
* @return component with status/bar.
*/
protected JComponent createStatusBar() {
FlowLayout layout = new FlowLayout(FlowLayout.LEFT);
layout.setHgap(5);
statusBar = new JPanel(layout);
statusBar.add(new JLabel("Status: "));
status = new JTextField();
status.setPreferredSize(new Dimension(400,25));
status.setEditable(false);
status.setBorder(newBevelBorder(BevelBorder.RAISED,Color.MAGENTA,Color.LIGHT_GRAY));
status.getInsets().set(2, 10, 2, 10);
statusBar.add(status);
return statusBar;
}
/**
* Internal helper to create the frames menubar.
* @return menu bar
*/
protected JMenuBar createMenuBar() {
JMenuBar mb = new JMenuBar();
JMenuItem item;
JMenu menu;
// Action menu
menu = new JMenu("Actions");
mb.add(menu);
item = new JMenuItem("Draw RandomCircle");
item.addActionListener(new RandomDrawer());
menu.add(item);
item = new JMenuItem("Draw RandomRectangle");
item.addActionListener(new RandomDrawer());
menu.add(item);
menu.addSeparator();
item = new JMenuItem("Exit");
item.addActionListener(new AppCloser());
menu.add(item);
// Color menu not used so far
menu = new JMenu("Colors");
mb.add(menu);
// Help menu not used so far
menu = new JMenu("Help");
mb.add(menu);
return mb;
}
class AppCloser implements ActionListener {
/* (non-Javadoc)
* @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("application finished, bye-bye... ");
frame.setVisible(false);
frame.dispose();
System.exit(0);
}
}
class RandomDrawer extends JPanel implements ActionListener {
/* (non-Javadoc)
* @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.BLACK);
g2.drawOval(100, 100, 100, 100);
}
@Override
public void actionPerformed(ActionEvent e) {
Random generator = new Random();
int x = generator.nextInt(100)+100;
int y = generator.nextInt(100)+100;
int w;
if (e.getActionCommand()==("Draw RandomCircle")) {
System.out.printf("x = %d y = %d\n", x, y);
//status.setText(String.format("rnd draw x: y: "));
//gg.setColor(Color.BLACK);
//gg.drawOval(x, y, generator.nextInt(x), generator.nextInt(y));
}
else if (e.getActionCommand()==("Draw RandomRectangle")) {
System.out.printf("x = %d y = %d\n", x, y);
//status.setText(String.format("rnd draw x: y: "));
//Graphics2D gg = (Graphics2D) canvas.getGraphics();
//gg.setColor(Color.BLACK);
//gg.drawRect(x, y, generator.nextInt(x), generator.nextInt(y));
}
}
}
class Painter extends MouseAdapter implements MouseMotionListener {
Point start, end;
int startX, startY, oldX, oldY, oldWidth, oldHeight;
public void mousePressed(MouseEvent e) {
start = e.getPoint();
oldX = startX;
oldY = startY;
startX = e.getX();
startY = e.getY();
status.setText(String.format("Mouse start: " + start));
}
public void mouseDragged(MouseEvent e) {
Graphics2D gc = (Graphics2D)canvas.getGraphics();
gc.setColor(new Color(128, 218, 255));
gc.drawOval(oldX, oldY, oldWidth, oldHeight);
System.out.printf("oldWidth ist = %3d, oldHeight ist = %3d\n", oldWidth, oldHeight);
oldWidth = e.getX();
oldHeight = e.getY();
gc.setColor(Color.BLACK);
gc.drawOval(startX, startY, e.getX(), e.getY());
}
public void mouseReleased(MouseEvent e) {
end = e.getPoint();
status.setText(String.format("Mouse end: " + end));
}
}
@Override
public void componentHidden(ComponentEvent e) {
// TODO Auto-generated method stub
}
@Override
public void componentMoved(ComponentEvent e) {
// TODO Auto-generated method stub
}
@Override
public void componentResized(ComponentEvent e) {
// TODO Auto-generated method stub
}
@Override
public void componentShown(ComponentEvent e) {
// TODO Auto-generated method stub
}
}
您可以将形状放在某种容器中,例如 ArrayList。
在 paintComponent(Graphics g) 中,你应该从该列表中绘制每个形状,在 actionPerformed(ActionEvent e) 中,你应该使用 repaint () 对象上的方法,您在其上绘制。
不要做...
Graphics2D gg = (Graphics2D) canvas.getGraphics();
这不是自定义绘画的方式。 Swing 会在需要绘制某些东西时询问您,您应该重新绘制组件的当前状态。
首先查看 Painting in AWT and Swing and Performing Custom Painting 了解更多详情
基本上,您需要覆盖JPanel
的paintComponent
方法(确保首先调用super.paintComponent
)并绘制组件的当前状态。
您需要以对您的(List
或自定义对象甚至 Image
)最有用的任何形式存储状态
您可以在更改状态后通过调用 repaint
请求 API 更新 UI
我正在尝试编写一个 swing gui,我可以通过按下两个不同的 JMenuItem、圆形和矩形在随机位置绘制形状。 我让它工作了,但我用了
Graphics2D gg = (Graphics2D) canvas.getGraphics();
有人建议我使用并覆盖 paintComponent()。所以我几个小时前就开始尝试了:D 我知道有很多关于这个的问题,但我真的读了很多,尝试和搜索但我无法帮助自己..
请查看我的 RandomDrawer Class,我发现我必须在那里实现 paintComponent()(我希望至少如此)。 进一步在下一个方法
public void actionPerformed(ActionEvent e)
我开始知道发生了什么动作,我可以或者我怎样才能告诉他之后画画?还是我的整个方法有缺陷?
这是我的代码。
感谢您的包容,非常感谢。
package plotterpackage;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.Random;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.WindowConstants;
import javax.swing.border.BevelBorder;
import javax.swing.text.JTextComponent;
public class PlotterApp implements ComponentListener {
private JFrame frame;
private JPanel canvas;
private JPanel statusBar;
private JTextField status;
/**
* Public default constructor.
*/
public PlotterApp() {
initialize();
}
/**
* Start of the application.
* @param args command line arguments
*/
public static void main(String[] args) {
PlotterApp app = new PlotterApp();
app.start();
}
/**
* Initialize the application.
*/
protected void initialize() {
frame = new JFrame("Main");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setBounds(50,50, 50+640, 50+480);
frame.setBackground(Color.GREEN);
frame.setJMenuBar(createMenuBar());
frame.getContentPane().add(createContent(), BorderLayout.CENTER);
frame.getContentPane().add(createStatusBar(),BorderLayout.SOUTH);
}
/**
* Start the graphical user interface.
*/
public void start() {
// show the GUI
frame.setVisible(true);
status.setText("Application started");
}
/**-*
* Internal helper to create the main content.
* @return component with application content.
*/
protected JComponent createContent() {
canvas = new JPanel();
canvas.addMouseListener(new Painter());
canvas.addMouseMotionListener(new Painter());
canvas.addComponentListener(this);
canvas.setBackground(new Color(128,218,255));
canvas.setForeground(Color.RED);
canvas.setBorder(new BevelBorder(BevelBorder.LOWERED));
return canvas;
}
/**
* Internal helper to create the statusbar and -fields.
* @return component with status/bar.
*/
protected JComponent createStatusBar() {
FlowLayout layout = new FlowLayout(FlowLayout.LEFT);
layout.setHgap(5);
statusBar = new JPanel(layout);
statusBar.add(new JLabel("Status: "));
status = new JTextField();
status.setPreferredSize(new Dimension(400,25));
status.setEditable(false);
status.setBorder(newBevelBorder(BevelBorder.RAISED,Color.MAGENTA,Color.LIGHT_GRAY));
status.getInsets().set(2, 10, 2, 10);
statusBar.add(status);
return statusBar;
}
/**
* Internal helper to create the frames menubar.
* @return menu bar
*/
protected JMenuBar createMenuBar() {
JMenuBar mb = new JMenuBar();
JMenuItem item;
JMenu menu;
// Action menu
menu = new JMenu("Actions");
mb.add(menu);
item = new JMenuItem("Draw RandomCircle");
item.addActionListener(new RandomDrawer());
menu.add(item);
item = new JMenuItem("Draw RandomRectangle");
item.addActionListener(new RandomDrawer());
menu.add(item);
menu.addSeparator();
item = new JMenuItem("Exit");
item.addActionListener(new AppCloser());
menu.add(item);
// Color menu not used so far
menu = new JMenu("Colors");
mb.add(menu);
// Help menu not used so far
menu = new JMenu("Help");
mb.add(menu);
return mb;
}
class AppCloser implements ActionListener {
/* (non-Javadoc)
* @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("application finished, bye-bye... ");
frame.setVisible(false);
frame.dispose();
System.exit(0);
}
}
class RandomDrawer extends JPanel implements ActionListener {
/* (non-Javadoc)
* @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.BLACK);
g2.drawOval(100, 100, 100, 100);
}
@Override
public void actionPerformed(ActionEvent e) {
Random generator = new Random();
int x = generator.nextInt(100)+100;
int y = generator.nextInt(100)+100;
int w;
if (e.getActionCommand()==("Draw RandomCircle")) {
System.out.printf("x = %d y = %d\n", x, y);
//status.setText(String.format("rnd draw x: y: "));
//gg.setColor(Color.BLACK);
//gg.drawOval(x, y, generator.nextInt(x), generator.nextInt(y));
}
else if (e.getActionCommand()==("Draw RandomRectangle")) {
System.out.printf("x = %d y = %d\n", x, y);
//status.setText(String.format("rnd draw x: y: "));
//Graphics2D gg = (Graphics2D) canvas.getGraphics();
//gg.setColor(Color.BLACK);
//gg.drawRect(x, y, generator.nextInt(x), generator.nextInt(y));
}
}
}
class Painter extends MouseAdapter implements MouseMotionListener {
Point start, end;
int startX, startY, oldX, oldY, oldWidth, oldHeight;
public void mousePressed(MouseEvent e) {
start = e.getPoint();
oldX = startX;
oldY = startY;
startX = e.getX();
startY = e.getY();
status.setText(String.format("Mouse start: " + start));
}
public void mouseDragged(MouseEvent e) {
Graphics2D gc = (Graphics2D)canvas.getGraphics();
gc.setColor(new Color(128, 218, 255));
gc.drawOval(oldX, oldY, oldWidth, oldHeight);
System.out.printf("oldWidth ist = %3d, oldHeight ist = %3d\n", oldWidth, oldHeight);
oldWidth = e.getX();
oldHeight = e.getY();
gc.setColor(Color.BLACK);
gc.drawOval(startX, startY, e.getX(), e.getY());
}
public void mouseReleased(MouseEvent e) {
end = e.getPoint();
status.setText(String.format("Mouse end: " + end));
}
}
@Override
public void componentHidden(ComponentEvent e) {
// TODO Auto-generated method stub
}
@Override
public void componentMoved(ComponentEvent e) {
// TODO Auto-generated method stub
}
@Override
public void componentResized(ComponentEvent e) {
// TODO Auto-generated method stub
}
@Override
public void componentShown(ComponentEvent e) {
// TODO Auto-generated method stub
}
}
您可以将形状放在某种容器中,例如 ArrayList。 在 paintComponent(Graphics g) 中,你应该从该列表中绘制每个形状,在 actionPerformed(ActionEvent e) 中,你应该使用 repaint () 对象上的方法,您在其上绘制。
不要做...
Graphics2D gg = (Graphics2D) canvas.getGraphics();
这不是自定义绘画的方式。 Swing 会在需要绘制某些东西时询问您,您应该重新绘制组件的当前状态。
首先查看 Painting in AWT and Swing and Performing Custom Painting 了解更多详情
基本上,您需要覆盖JPanel
的paintComponent
方法(确保首先调用super.paintComponent
)并绘制组件的当前状态。
您需要以对您的(List
或自定义对象甚至 Image
)最有用的任何形式存储状态
您可以在更改状态后通过调用 repaint
请求 API 更新 UI