我正在 java 中制作一个简单的绘图程序,我可以绘图,但是当我最小化 window 或调整大小时,我绘制的内容就会消失。我怎样才能让他们留下来?
I am making a simple paint program in java, I can draw but when I minimize the window or resize what I painted goes away. How do I get them to stay?
这是我目前所拥有的,我尝试创建绘图函数只是为了测试它是否可行。调色板只是另一个 gui window,一旦我首先解决了这个保存问题,它就会有颜色选项
import csc260final.Palette;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JOptionPane;
/**
*
* @author Jared Hughes
*/
public class Canvas extends javax.swing.JFrame {
/**
* Creates new form Canvas
*/
Draw line;
private int curX, curY, oldX, oldY;
public Graphics2D g2;
Palette palette;
public Canvas() {
initComponents();
palette = new Palette();
palette.setVisible(true);
}
public void draw(){
g2 = (Graphics2D) jPanel1.getGraphics();
g2.setColor(Color.yellow);
g2.setStroke(new BasicStroke(10));
g2.drawLine(oldX, oldY, curX, curY);
}
public void paint(Graphics g){
Graphics2D g2 = (Graphics2D)g;
super.paint(g);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jPanel1 = new javax.swing.JPanel();
jButton1 = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jPanel1.setBackground(new java.awt.Color(255, 255, 255));
jPanel1.setPreferredSize(new java.awt.Dimension(1130, 550));
jPanel1.setRequestFocusEnabled(false);
jPanel1.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
public void mouseDragged(java.awt.event.MouseEvent evt) {
jPanel1MouseDragged(evt);
}
public void mouseMoved(java.awt.event.MouseEvent evt) {
jPanel1MouseMoved(evt);
}
});
jPanel1.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
jPanel1MouseClicked(evt);
}
public void mouseEntered(java.awt.event.MouseEvent evt) {
jPanel1MouseEntered(evt);
}
public void mouseExited(java.awt.event.MouseEvent evt) {
jPanel1MouseExited(evt);
}
public void mousePressed(java.awt.event.MouseEvent evt) {
jPanel1MousePressed(evt);
}
public void mouseReleased(java.awt.event.MouseEvent evt) {
jPanel1MouseReleased(evt);
}
});
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 1130, Short.MAX_VALUE)
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 550, Short.MAX_VALUE)
);
jButton1.setText("jButton1");
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jButton1)
.addGap(94, 94, 94))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 28, Short.MAX_VALUE)
.addComponent(jButton1)
.addContainerGap())
);
pack();
}// </editor-fold>
private void jPanel1MousePressed(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:
// save x and y when mouse is pressed
curX = evt.getX();
curY = evt.getY();
oldX = curX;
oldY = curY;
}
private void jPanel1MouseDragged(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:
// get x and y when mouse is dragged
curX = evt.getX();
curY = evt.getY();
g2 = (Graphics2D) jPanel1.getGraphics();
g2.setColor(Color.yellow);
g2.setStroke(new BasicStroke(10));
g2.drawLine(oldX, oldY, curX, curY);
oldX = curX;
oldY = curY;
}
private void jPanel1MouseClicked(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:
}
private void jPanel1MouseEntered(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:
}
private void jPanel1MouseMoved(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:
}
private void jPanel1MouseExited(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:
}
private void jPanel1MouseReleased(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:
}
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(Canvas.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(Canvas.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(Canvas.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(Canvas.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new Canvas().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton jButton1;
private javax.swing.JPanel jPanel1;
// End of variables declaration
}
您的 Swing 绘图未正确完成。您不应使用通过在组件上调用 getGraphics()
获得的 Graphics 对象进行绘制。这将 return 一个短暂的 Graphics 对象,冒着消失图形或更糟的风险,一个 NullPointerException。相反,直接或通过在 BufferedImage 上绘制(是的,您可以通过 getGraphics()
获取其 Graphics 对象)间接绘制 JPanel 的 paintComponent(...)
方法,然后在 paintComponent 方法中将 BufferedImage 绘制到 GUI .
有用的Java教程:
- Lesson: Performing Custom Painting: Swing图形入门教程
- Painting in AWT and Swing: Swing 图形高级教程
小吹毛求疵:
- 避免提供与核心 Java 类 冲突的 类 名称,例如
Canvas
。这将有助于防止混淆他人和你未来的自己。
- 在这里发布代码时,如果您努力将其格式化,包括明智地使用空行,我们将不胜感激。您上面的代码有几个大的空白区域,很难遵循。在这里或那里有一个空行是可以的,但是很多,不是那么多。
例如:
import java.awt.BasicStroke;
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.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import javax.swing.*;
@SuppressWarnings("serial")
public class TestDrawingCanvas extends JPanel {
private DrawingCanvas drawingCanvas = new DrawingCanvas();
public TestDrawingCanvas() {
JPanel btnPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING));
btnPanel.add(new JButton(new ClearAction()));
setLayout(new BorderLayout());
add(drawingCanvas, BorderLayout.CENTER);
add(btnPanel, BorderLayout.PAGE_END);
}
private class ClearAction extends AbstractAction {
public ClearAction() {
super("Clear Canvas");
putValue(MNEMONIC_KEY, KeyEvent.VK_C);
}
@Override
public void actionPerformed(ActionEvent e) {
drawingCanvas.clear();
}
}
private static void createAndShowGui() {
TestDrawingCanvas mainPanel = new TestDrawingCanvas();
JFrame frame = new JFrame("Drawing Canvas");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
@SuppressWarnings("serial")
class DrawingCanvas extends JPanel {
private static final int PREF_W = 800;
private static final int PREF_H = 600;
public static final Color LINE_COLOR = Color.YELLOW;
public static final Stroke IMG_STROKE = new BasicStroke(10f);
private Color lineColor = LINE_COLOR;
private BufferedImage image;
public DrawingCanvas() {
setBackground(Color.WHITE);
image = new BufferedImage(PREF_W, PREF_H, BufferedImage.TYPE_INT_ARGB);
MyMouse myMouse = new MyMouse();
addMouseListener(myMouse);
addMouseMotionListener(myMouse);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (image != null) {
g.drawImage(image, 0, 0, this);
}
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
public void setLineColor(Color lineColor) {
this.lineColor = lineColor;
}
public void clear () {
image = new BufferedImage(PREF_W, PREF_H, BufferedImage.TYPE_INT_ARGB);
repaint();
}
private class MyMouse extends MouseAdapter {
private Graphics2D imgG2d;
private Point p1;
@Override
public void mousePressed(MouseEvent e) {
if (e.getButton() != MouseEvent.BUTTON1) {
return;
}
imgG2d = image.createGraphics();
imgG2d.setColor(lineColor);
imgG2d.setStroke(IMG_STROKE);
p1 = e.getPoint();
}
@Override
public void mouseReleased(MouseEvent e) {
drawLine(e);
imgG2d.dispose();
p1 = null;
imgG2d = null;
}
@Override
public void mouseDragged(MouseEvent e) {
drawLine(e);
p1 = e.getPoint();
}
private void drawLine(MouseEvent e) {
if (imgG2d == null || p1 == null) {
return;
}
Point p2 = e.getPoint();
int x1 = p1.x;
int y1 = p1.y;
int x2 = p2.x;
int y2 = p2.y;
imgG2d.drawLine(x1, y1, x2, y2);
repaint();
}
}
}
这是我目前所拥有的,我尝试创建绘图函数只是为了测试它是否可行。调色板只是另一个 gui window,一旦我首先解决了这个保存问题,它就会有颜色选项
import csc260final.Palette;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JOptionPane;
/**
*
* @author Jared Hughes
*/
public class Canvas extends javax.swing.JFrame {
/**
* Creates new form Canvas
*/
Draw line;
private int curX, curY, oldX, oldY;
public Graphics2D g2;
Palette palette;
public Canvas() {
initComponents();
palette = new Palette();
palette.setVisible(true);
}
public void draw(){
g2 = (Graphics2D) jPanel1.getGraphics();
g2.setColor(Color.yellow);
g2.setStroke(new BasicStroke(10));
g2.drawLine(oldX, oldY, curX, curY);
}
public void paint(Graphics g){
Graphics2D g2 = (Graphics2D)g;
super.paint(g);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jPanel1 = new javax.swing.JPanel();
jButton1 = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jPanel1.setBackground(new java.awt.Color(255, 255, 255));
jPanel1.setPreferredSize(new java.awt.Dimension(1130, 550));
jPanel1.setRequestFocusEnabled(false);
jPanel1.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
public void mouseDragged(java.awt.event.MouseEvent evt) {
jPanel1MouseDragged(evt);
}
public void mouseMoved(java.awt.event.MouseEvent evt) {
jPanel1MouseMoved(evt);
}
});
jPanel1.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
jPanel1MouseClicked(evt);
}
public void mouseEntered(java.awt.event.MouseEvent evt) {
jPanel1MouseEntered(evt);
}
public void mouseExited(java.awt.event.MouseEvent evt) {
jPanel1MouseExited(evt);
}
public void mousePressed(java.awt.event.MouseEvent evt) {
jPanel1MousePressed(evt);
}
public void mouseReleased(java.awt.event.MouseEvent evt) {
jPanel1MouseReleased(evt);
}
});
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 1130, Short.MAX_VALUE)
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 550, Short.MAX_VALUE)
);
jButton1.setText("jButton1");
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jButton1)
.addGap(94, 94, 94))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 28, Short.MAX_VALUE)
.addComponent(jButton1)
.addContainerGap())
);
pack();
}// </editor-fold>
private void jPanel1MousePressed(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:
// save x and y when mouse is pressed
curX = evt.getX();
curY = evt.getY();
oldX = curX;
oldY = curY;
}
private void jPanel1MouseDragged(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:
// get x and y when mouse is dragged
curX = evt.getX();
curY = evt.getY();
g2 = (Graphics2D) jPanel1.getGraphics();
g2.setColor(Color.yellow);
g2.setStroke(new BasicStroke(10));
g2.drawLine(oldX, oldY, curX, curY);
oldX = curX;
oldY = curY;
}
private void jPanel1MouseClicked(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:
}
private void jPanel1MouseEntered(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:
}
private void jPanel1MouseMoved(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:
}
private void jPanel1MouseExited(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:
}
private void jPanel1MouseReleased(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:
}
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(Canvas.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(Canvas.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(Canvas.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(Canvas.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new Canvas().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton jButton1;
private javax.swing.JPanel jPanel1;
// End of variables declaration
}
您的 Swing 绘图未正确完成。您不应使用通过在组件上调用 getGraphics()
获得的 Graphics 对象进行绘制。这将 return 一个短暂的 Graphics 对象,冒着消失图形或更糟的风险,一个 NullPointerException。相反,直接或通过在 BufferedImage 上绘制(是的,您可以通过 getGraphics()
获取其 Graphics 对象)间接绘制 JPanel 的 paintComponent(...)
方法,然后在 paintComponent 方法中将 BufferedImage 绘制到 GUI .
有用的Java教程:
- Lesson: Performing Custom Painting: Swing图形入门教程
- Painting in AWT and Swing: Swing 图形高级教程
小吹毛求疵:
- 避免提供与核心 Java 类 冲突的 类 名称,例如
Canvas
。这将有助于防止混淆他人和你未来的自己。 - 在这里发布代码时,如果您努力将其格式化,包括明智地使用空行,我们将不胜感激。您上面的代码有几个大的空白区域,很难遵循。在这里或那里有一个空行是可以的,但是很多,不是那么多。
例如:
import java.awt.BasicStroke;
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.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import javax.swing.*;
@SuppressWarnings("serial")
public class TestDrawingCanvas extends JPanel {
private DrawingCanvas drawingCanvas = new DrawingCanvas();
public TestDrawingCanvas() {
JPanel btnPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING));
btnPanel.add(new JButton(new ClearAction()));
setLayout(new BorderLayout());
add(drawingCanvas, BorderLayout.CENTER);
add(btnPanel, BorderLayout.PAGE_END);
}
private class ClearAction extends AbstractAction {
public ClearAction() {
super("Clear Canvas");
putValue(MNEMONIC_KEY, KeyEvent.VK_C);
}
@Override
public void actionPerformed(ActionEvent e) {
drawingCanvas.clear();
}
}
private static void createAndShowGui() {
TestDrawingCanvas mainPanel = new TestDrawingCanvas();
JFrame frame = new JFrame("Drawing Canvas");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
@SuppressWarnings("serial")
class DrawingCanvas extends JPanel {
private static final int PREF_W = 800;
private static final int PREF_H = 600;
public static final Color LINE_COLOR = Color.YELLOW;
public static final Stroke IMG_STROKE = new BasicStroke(10f);
private Color lineColor = LINE_COLOR;
private BufferedImage image;
public DrawingCanvas() {
setBackground(Color.WHITE);
image = new BufferedImage(PREF_W, PREF_H, BufferedImage.TYPE_INT_ARGB);
MyMouse myMouse = new MyMouse();
addMouseListener(myMouse);
addMouseMotionListener(myMouse);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (image != null) {
g.drawImage(image, 0, 0, this);
}
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
public void setLineColor(Color lineColor) {
this.lineColor = lineColor;
}
public void clear () {
image = new BufferedImage(PREF_W, PREF_H, BufferedImage.TYPE_INT_ARGB);
repaint();
}
private class MyMouse extends MouseAdapter {
private Graphics2D imgG2d;
private Point p1;
@Override
public void mousePressed(MouseEvent e) {
if (e.getButton() != MouseEvent.BUTTON1) {
return;
}
imgG2d = image.createGraphics();
imgG2d.setColor(lineColor);
imgG2d.setStroke(IMG_STROKE);
p1 = e.getPoint();
}
@Override
public void mouseReleased(MouseEvent e) {
drawLine(e);
imgG2d.dispose();
p1 = null;
imgG2d = null;
}
@Override
public void mouseDragged(MouseEvent e) {
drawLine(e);
p1 = e.getPoint();
}
private void drawLine(MouseEvent e) {
if (imgG2d == null || p1 == null) {
return;
}
Point p2 = e.getPoint();
int x1 = p1.x;
int y1 = p1.y;
int x2 = p2.x;
int y2 = p2.y;
imgG2d.drawLine(x1, y1, x2, y2);
repaint();
}
}
}