Java 如何让用户在画布内绘制并保存图像?
我正在尝试实现一个徒手绘制的Java小程序,它允许用户在画布上绘制一些东西(画布不是优先级,它可以是其他任何东西,只要我可以在之后保存图像(需要保存它,因为我必须在按下按钮后在不同的位置显示它,欢迎任何其他解决方案))。我找到了一个代码,它允许我画画,但现在我在画布内画画时遇到了麻烦。。。我已经花了几天的时间没有结果了。以下是我目前掌握的代码及其描述:Java 如何让用户在画布内绘制并保存图像?,java,swing,canvas,jframe,drawing,Java,Swing,Canvas,Jframe,Drawing,我正在尝试实现一个徒手绘制的Java小程序,它允许用户在画布上绘制一些东西(画布不是优先级,它可以是其他任何东西,只要我可以在之后保存图像(需要保存它,因为我必须在按下按钮后在不同的位置显示它,欢迎任何其他解决方案))。我找到了一个代码,它允许我画画,但现在我在画布内画画时遇到了麻烦。。。我已经花了几天的时间没有结果了。以下是我目前掌握的代码及其描述: import java.awt.*; import java.awt.event.*; import java.awt.event.Ac
import java.awt.*;
import java.awt.event.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.*;
import java.applet.*;
public class paintMozApplet extends Applet implements ActionListener
{
int xPressed,yPressed;
int xReleased,yReleased;
int xDragged,yDragged;
private GridLayout gL;
private JPanel buttons;
private JPanel panel;
private Button clear, createMoz;
private Label result_here;
private javax.swing.JPanel drawing;
private JPanel moz;
private Canvas canvas;
private draw draw;
public paintMozApplet()
{
draw = new draw();
gL = new GridLayout(1, 0);
buttons = new JPanel();
drawing = new JPanel();
moz = new JPanel();
canvas = new Canvas();
clear = new Button("clear");
createMoz = new Button("Create Moz");
buttons.add(clear);
buttons.add(createMoz);
result_here = new Label("Result here!");
moz.add(result_here);
drawing.add(canvas);
clear.addActionListener(this);
//canvas.add(draw);
//canvas.addMouseMotionListener(this);
canvas.setPreferredSize(new Dimension(200, 200));
canvas.setBackground(Color.green);
add(drawing);
add(buttons);
add(moz);
add(draw);
setPreferredSize(new Dimension(1000, 1000));
setSize(1000, 1000);
setLayout(gL);
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==clear)
{
//setOpaque(false);
repaint();
}
}
}
class draw extends JFrame implements MouseListener, MouseMotionListener, ActionListener {
int xPressed,yPressed;
int xReleased,yReleased;
int xDragged,yDragged;
private JButton clear;
public draw()
{
setPreferredSize(new Dimension(1200, 500));
setBounds(0, 0, 480, 500);
clear=new JButton("CLEAR");
add(clear);
clear.setBounds(540, 5, 100, 25);
clear.addActionListener(this);
addMouseListener(this);
addMouseMotionListener(this);
}
protected void paintComponent(Graphics g)
{
g.drawLine(xPressed,yPressed,xDragged,yDragged);
xPressed=xDragged;
yPressed=yDragged;
}
@Override
public void mouseDragged(MouseEvent arg0) {
Graphics g = getGraphics();
g.drawLine(xPressed, yPressed, arg0.getX(), arg0.getY());
xDragged = arg0.getX();
yDragged = arg0.getY();
repaint();
}
@Override
public void mouseMoved(MouseEvent arg0) {
}
@Override
public void mouseClicked(MouseEvent arg0) {
}
@Override
public void mouseEntered(MouseEvent arg0) {
}
@Override
public void mouseExited(MouseEvent arg0) {
}
@Override
public void mousePressed(MouseEvent arg0) {
xPressed = arg0.getX();
yPressed = arg0.getY();
}
@Override
public void mouseReleased(MouseEvent arg0) {
}
@Override
public void actionPerformed(ActionEvent e) {
}
}
所以我的想法是创建两个类,一个用来画画,另一个用来创建画画的地方和其他所有东西。我已经尝试了很多东西,但现在我在这里,不知道如何在我的画布上校准draw类,以便它只在那里绘制。之前,我把所有东西都放在一个类中,并在画布上调用鼠标事件。结果是,它只在我点击画布时才绘制,但如果我不放开鼠标并将其从画布中拖出,实际的绘图也会从画布中消失。它也没有在画布上绘制,但在applet的背景上,至少看起来是这样
我真的希望我解释了我的自我理解,并且我确信,这可以很容易地解决,因为在线上有很多解决方案,但我似乎找不到一个能按照我的意愿工作的解决方案。我建议以
缓冲图像
作为绘画表面,从这个方法开始
import java.awt.*;
import java.awt.RenderingHints.Key;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;
public class BasicPaint {
/** Reference to the original image. */
private BufferedImage originalImage;
/** Image used to make changes. */
private BufferedImage canvasImage;
/** The main GUI that might be added to a frame or applet. */
private JPanel gui;
/** The color to use when calling clear, text or other
* drawing functionality. */
private Color color = Color.WHITE;
/** General user messages. */
private JLabel output = new JLabel("You DooDoodle!");
private BufferedImage colorSample = new BufferedImage(
16,16,BufferedImage.TYPE_INT_RGB);
private JLabel imageLabel;
private int activeTool;
public static final int SELECTION_TOOL = 0;
public static final int DRAW_TOOL = 1;
public static final int TEXT_TOOL = 2;
private Point selectionStart;
private Rectangle selection;
private boolean dirty = false;
private Stroke stroke = new BasicStroke(
3,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND,1.7f);
private RenderingHints renderingHints;
public JComponent getGui() {
if (gui==null) {
Map<Key, Object> hintsMap = new HashMap<RenderingHints.Key,Object>();
hintsMap.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
hintsMap.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
hintsMap.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
renderingHints = new RenderingHints(hintsMap);
setImage(new BufferedImage(320,240,BufferedImage.TYPE_INT_RGB));
gui = new JPanel(new BorderLayout(4,4));
gui.setBorder(new EmptyBorder(5,3,5,3));
JPanel imageView = new JPanel(new GridBagLayout());
imageView.setPreferredSize(new Dimension(480,320));
imageLabel = new JLabel(new ImageIcon(canvasImage));
JScrollPane imageScroll = new JScrollPane(imageView);
imageView.add(imageLabel);
imageLabel.addMouseMotionListener(new ImageMouseMotionListener());
imageLabel.addMouseListener(new ImageMouseListener());
gui.add(imageScroll,BorderLayout.CENTER);
JToolBar tb = new JToolBar();
tb.setFloatable(false);
JButton colorButton = new JButton("Color");
colorButton.setMnemonic('o');
colorButton.setToolTipText("Choose a Color");
ActionListener colorListener = new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
Color c = JColorChooser.showDialog(
gui, "Choose a color", color);
if (c!=null) {
setColor(c);
}
}
};
colorButton.addActionListener(colorListener);
colorButton.setIcon(new ImageIcon(colorSample));
tb.add(colorButton);
setColor(color);
final SpinnerNumberModel strokeModel =
new SpinnerNumberModel(3,1,16,1);
JSpinner strokeSize = new JSpinner(strokeModel);
ChangeListener strokeListener = new ChangeListener() {
@Override
public void stateChanged(ChangeEvent arg0) {
Object o = strokeModel.getValue();
Integer i = (Integer)o;
stroke = new BasicStroke(
i.intValue(),
BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND,
1.7f);
}
};
strokeSize.addChangeListener(strokeListener);
strokeSize.setMaximumSize(strokeSize.getPreferredSize());
JLabel strokeLabel = new JLabel("Stroke");
strokeLabel.setLabelFor(strokeSize);
strokeLabel.setDisplayedMnemonic('t');
tb.add(strokeLabel);
tb.add(strokeSize);
tb.addSeparator();
ActionListener clearListener = new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
int result = JOptionPane.OK_OPTION;
if (dirty) {
result = JOptionPane.showConfirmDialog(
gui, "Erase the current painting?");
}
if (result==JOptionPane.OK_OPTION) {
clear(canvasImage);
}
}
};
JButton clearButton = new JButton("Clear");
tb.add(clearButton);
clearButton.addActionListener(clearListener);
gui.add(tb, BorderLayout.PAGE_START);
JToolBar tools = new JToolBar(JToolBar.VERTICAL);
tools.setFloatable(false);
JButton crop = new JButton("Crop");
final JRadioButton select = new JRadioButton("Select", true);
final JRadioButton draw = new JRadioButton("Draw");
final JRadioButton text = new JRadioButton("Text");
tools.add(crop);
tools.add(select);
tools.add(draw);
tools.add(text);
ButtonGroup bg = new ButtonGroup();
bg.add(select);
bg.add(text);
bg.add(draw);
ActionListener toolGroupListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
if (ae.getSource()==select) {
activeTool = SELECTION_TOOL;
} else if (ae.getSource()==draw) {
activeTool = DRAW_TOOL;
} else if (ae.getSource()==text) {
activeTool = TEXT_TOOL;
}
}
};
select.addActionListener(toolGroupListener);
draw.addActionListener(toolGroupListener);
text.addActionListener(toolGroupListener);
gui.add(tools, BorderLayout.LINE_END);
gui.add(output,BorderLayout.PAGE_END);
clear(colorSample);
clear(canvasImage);
}
return gui;
}
/** Clears the entire image area by painting it with the current color. */
public void clear(BufferedImage bi) {
Graphics2D g = bi.createGraphics();
g.setRenderingHints(renderingHints);
g.setColor(color);
g.fillRect(0, 0, bi.getWidth(), bi.getHeight());
g.dispose();
imageLabel.repaint();
}
public void setImage(BufferedImage image) {
this.originalImage = image;
int w = image.getWidth();
int h = image.getHeight();
canvasImage = new BufferedImage(w,h,BufferedImage.TYPE_INT_ARGB);
Graphics2D g = this.canvasImage.createGraphics();
g.setRenderingHints(renderingHints);
g.drawImage(image, 0, 0, gui);
g.dispose();
selection = new Rectangle(0,0,w,h);
if (this.imageLabel!=null) {
imageLabel.setIcon(new ImageIcon(canvasImage));
this.imageLabel.repaint();
}
if (gui!=null) {
gui.invalidate();
}
}
/** Set the current painting color and refresh any elements needed. */
public void setColor(Color color) {
this.color = color;
clear(colorSample);
}
private JMenu getFileMenu(boolean webstart){
JMenu file = new JMenu("File");
file.setMnemonic('f');
JMenuItem newImageItem = new JMenuItem("New");
newImageItem.setMnemonic('n');
ActionListener newImage = new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
BufferedImage bi = new BufferedImage(
360, 300, BufferedImage.TYPE_INT_ARGB);
clear(bi);
setImage(bi);
}
};
newImageItem.addActionListener(newImage);
file.add(newImageItem);
if (webstart) {
//TODO Add open/save functionality using JNLP API
} else {
//TODO Add save functionality using J2SE API
file.addSeparator();
ActionListener openListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
if (!dirty) {
JFileChooser ch = getFileChooser();
int result = ch.showOpenDialog(gui);
if (result==JFileChooser.APPROVE_OPTION ) {
try {
BufferedImage bi = ImageIO.read(
ch.getSelectedFile());
setImage(bi);
} catch (IOException e) {
showError(e);
e.printStackTrace();
}
}
} else {
// TODO
JOptionPane.showMessageDialog(
gui, "TODO - prompt save image..");
}
}
};
JMenuItem openItem = new JMenuItem("Open");
openItem.setMnemonic('o');
openItem.addActionListener(openListener);
file.add(openItem);
ActionListener saveListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JFileChooser ch = getFileChooser();
int result = ch.showSaveDialog(gui);
if (result==JFileChooser.APPROVE_OPTION ) {
try {
File f = ch.getSelectedFile();
ImageIO.write(BasicPaint.this.canvasImage, "png", f);
BasicPaint.this.originalImage = BasicPaint.this.canvasImage;
dirty = false;
} catch (IOException ioe) {
showError(ioe);
ioe.printStackTrace();
}
}
}
};
JMenuItem saveItem = new JMenuItem("Save");
saveItem.addActionListener(saveListener);
saveItem.setMnemonic('s');
file.add(saveItem);
}
if (canExit()) {
ActionListener exit = new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
System.exit(0);
}
};
JMenuItem exitItem = new JMenuItem("Exit");
exitItem.setMnemonic('x');
file.addSeparator();
exitItem.addActionListener(exit);
file.add(exitItem);
}
return file;
}
private void showError(Throwable t) {
JOptionPane.showMessageDialog(
gui,
t.getMessage(),
t.toString(),
JOptionPane.ERROR_MESSAGE);
}
JFileChooser chooser = null;
public JFileChooser getFileChooser() {
if (chooser==null) {
chooser = new JFileChooser();
FileFilter ff = new FileNameExtensionFilter("Image files", ImageIO.getReaderFileSuffixes());
chooser.setFileFilter(ff);
}
return chooser;
}
public boolean canExit() {
boolean canExit = false;
SecurityManager sm = System.getSecurityManager();
if (sm==null) {
canExit = true;
} else {
try {
sm.checkExit(0);
canExit = true;
} catch(Exception stayFalse) {
}
}
return canExit;
}
public JMenuBar getMenuBar(boolean webstart){
JMenuBar mb = new JMenuBar();
mb.add(this.getFileMenu(webstart));
return mb;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(
UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
// use default
}
BasicPaint bp = new BasicPaint();
JFrame f = new JFrame("DooDoodle!");
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(bp.getGui());
f.setJMenuBar(bp.getMenuBar(false));
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
public void text(Point point) {
String text = JOptionPane.showInputDialog(gui, "Text to add", "Text");
if (text!=null) {
Graphics2D g = this.canvasImage.createGraphics();
g.setRenderingHints(renderingHints);
g.setColor(this.color);
g.setStroke(stroke);
int n = 0;
g.drawString(text,point.x,point.y);
g.dispose();
this.imageLabel.repaint();
}
}
public void draw(Point point) {
Graphics2D g = this.canvasImage.createGraphics();
g.setRenderingHints(renderingHints);
g.setColor(this.color);
g.setStroke(stroke);
int n = 0;
g.drawLine(point.x, point.y, point.x+n, point.y+n);
g.dispose();
this.imageLabel.repaint();
}
class ImageMouseListener extends MouseAdapter {
@Override
public void mousePressed(MouseEvent arg0) {
// TODO Auto-generated method stub
if (activeTool==BasicPaint.SELECTION_TOOL) {
selectionStart = arg0.getPoint();
} else if (activeTool==BasicPaint.DRAW_TOOL) {
// TODO
draw(arg0.getPoint());
} else if (activeTool==BasicPaint.TEXT_TOOL) {
// TODO
text(arg0.getPoint());
} else {
JOptionPane.showMessageDialog(
gui,
"Application error. :(",
"Error!",
JOptionPane.ERROR_MESSAGE);
}
}
@Override
public void mouseReleased(MouseEvent arg0) {
if (activeTool==BasicPaint.SELECTION_TOOL) {
selection = new Rectangle(
selectionStart.x,
selectionStart.y,
arg0.getPoint().x,
arg0.getPoint().y);
}
}
}
class ImageMouseMotionListener implements MouseMotionListener {
@Override
public void mouseDragged(MouseEvent arg0) {
reportPositionAndColor(arg0);
if (activeTool==BasicPaint.SELECTION_TOOL) {
selection = new Rectangle(
selectionStart.x,
selectionStart.y,
arg0.getPoint().x-selectionStart.x,
arg0.getPoint().y-selectionStart.y);
} else if (activeTool==BasicPaint.DRAW_TOOL) {
draw(arg0.getPoint());
}
}
@Override
public void mouseMoved(MouseEvent arg0) {
reportPositionAndColor(arg0);
}
}
private void reportPositionAndColor(MouseEvent me) {
String text = "";
if (activeTool==BasicPaint.SELECTION_TOOL) {
text += "Selection (X,Y:WxH): " +
(int)selection.getX() +
"," +
(int)selection.getY() +
":" +
(int)selection.getWidth() +
"x" +
(int)selection.getHeight();
} else {
text += "X,Y: " + (me.getPoint().x+1) + "," + (me.getPoint().y+1);
}
output.setText(text);
}
}
import java.awt.*;
导入java.awt.RenderingHints.Key;
导入java.awt.event.*;
导入java.awt.image.buffereImage;
导入java.io.File;
导入java.io.IOException;
导入java.util.HashMap;
导入java.util.Map;
导入javax.imageio.imageio;
导入javax.swing.*;
导入javax.swing.border.*;
导入javax.swing.event.ChangeEvent;
导入javax.swing.event.ChangeListener;
导入javax.swing.filechooser.FileFilter;
导入javax.swing.filechooser.FileNameExtensionFilter;
公共类基本点{
/**参考原始图像*/
私有缓冲区图像原始图像;
/**用于进行更改的图像*/
私有缓冲区图像画布图像;
/**可能添加到框架或小程序的主GUI*/
私有JPanel gui;
/**调用clear、text或其他时要使用的颜色
*绘图功能*/
私有颜色=Color.WHITE;
/**一般用户消息*/
私有JLabel输出=新JLabel(“你乱画!”);
private BuffereImage colorSample=新BuffereImage(
16,16,BuffereImage.TYPE_INT_RGB);
专用JLabel图像标签;
私有int-activeTool;
公共静态最终整数选择工具=0;
公共静态最终整数绘制工具=1;
公共静态最终整型文本工具=2;
私人点选择启动;
私有矩形选择;
私有布尔脏=假;
私人行程行程=新的基本行程(
3,基本行程。CAP_ROUND,基本行程。JOIN_ROUND,1.7f);
私有渲染提示渲染提示;
公共JComponent getGui(){
if(gui==null){
Map hintsMap=newhashmap();
hintsMap.put(RenderingHints.KEY\u RENDERING,RenderingHints.VALUE\u RENDER\u QUALITY);
hintsMap.put(renderinghits.KEY\u抖动,renderinghits.VALUE\u抖动\u启用);
hintsMap.put(renderinghits.KEY\u TEXT\u抗锯齿,renderinghits.VALUE\u TEXT\u antialas\u ON);
renderingHints=新的renderingHints(hintsMap);
setImage(新的BufferedImage(320240,BufferedImage.TYPE_INT_RGB));
gui=新JPanel(新边界布局(4,4));
新订单(新的空订单(5,3,5,3));
JPanel imageView=新的JPanel(新的GridBagLayout());
setPreferredSize(新维度(480320));
imageLabel=new JLabel(new ImageIcon(canvasImage));
JScrollPane imageScroll=新的JScrollPane(imageView);
添加(imageLabel);
addMouseMotionListener(新的ImageMouseMotionListener());
addMouseListener(新的ImageMouseListener());
添加(imageScroll,BorderLayout.CENTER);
JToolBar tb=新的JToolBar();
tb.可设置浮动(假);
JButton colorButton=新JButton(“颜色”);
colorButton.set助记符('o');
setToolTiptText(“选择颜色”);
ActionListener colorListener=新建ActionListener(){
已执行的公共无效操作(操作事件arg0){
颜色c=JColorChooser.showDialog(
gui,“选择颜色”,颜色);
如果(c!=null){
setColor(c);
}
}
};
addActionListener(colorListener);
colorButton.setIcon(新图像图标(colorSample));
tb.add(彩色按钮);
设置颜色(颜色);
最终喷丝头编号模型冲程模型=
新喷丝头型号(3,1,16,1);
JSpinner-strokeSize=新的JSpinner(strokeModel);
ChangeListener StrokListener=新的ChangeListener(){
@凌驾
公共无效状态已更改(ChangeEvent arg0){
对象o=strokeModel.getValue();
整数i=(整数)o;
冲程=新的基本冲程(
i、 intValue(),
BasicStroke.CAP_ROUND,
基本行程,
1.7f);
}
};
addChangeListener(strokListener);
strokeSize.setMaximumSize(strokeSize.getPreferredSize());
JLabel strokeLabel=新JLabel(“行程”);
strokeLabel.setLabelFor(strokeSize);
strokeLabel.setdisplayednemonic('t');
tb.add(strokeLabel);