紧接上一篇实现图片渲染链接: 图片渲染(图像编码原理).
可以发现:只前在绘画图片的时候速度非常的慢。那是因为每次只要一获得像素就立即将其绘画出来。
g.setColor(color);
g.fillRect(i, j,1, 1)
在内存中执行代码后,会向GPU请求刷新屏幕,一张图片有成千上万个像素,那么屏幕就会连续刷新很多次,速度非常慢。例如,如果电脑屏幕的刷新率是60赫兹的话,意味着一秒钟屏幕会刷新60次,放到这里来讲的话,一秒钟最多显示60个像素,对于分辨率极高的图片,要加载出来,可想而知等的时间也就会越久。
所以,就要用一种方法一次性将所有的像素画出来。BufferedImage是一个带缓冲区图像类,主要作用是将一幅图片加载到内存中(BufferedImage生成的图片在内存里有一个图像缓冲区,利用这个缓冲区我们可以很方便地操作这个图片)
在请求刷新屏幕之前,现将所有的像素设置完毕,然后一次性将缓冲区的像素全部画出来(刷新一次屏幕)。有两种方法来设置缓冲区。
第一:直接设置缓冲区相应位置像素的RGB值。
实现如下:
//绘画原图改进方法
public BufferedImage paint1(Graphics g,int[][] arrpixel)
{
BufferedImage buffimage=new BufferedImage(arrpixel.length, arrpixel[0].length,BufferedImage.TYPE_INT_RGB);
for(int i=0;i<arrpixel.length;i++)
{
for(int j=0;j<arrpixel[0].length;j++)
{
int value=arrpixel[i][j];
buffimage.setRGB(i, j, value);//一次性将所有像素存储完成
}
}
g.drawImage(buffimage, 0, 0, null);//一次性画完
return buffimage;
}
第二:通过缓冲区获得画笔,将画笔赋相应的RGB值,然后通过fillRect方法来填充矩形小像素。这种方法还可以方便我们实现渲染(如后面的马赛克等)
实现如下:
//原图改进方法
public BufferedImage paint1(Graphics g,int[][] arrpixel)
{
BufferedImage buffimage=new BufferedImage(arrpixel.length, arrpixel[0].length,BufferedImage.TYPE_INT_RGB);
Graphics ng=buffimage.getGraphics();
for(int i=0;i<arrpixel.length;i++)
{
for(int j=0;j<arrpixel[0].length;j++)
{
int value=arrpixel[i][j];
if(i==0&&j==0)
{
System.out.println("arrpixel:"+value);}
ng.setColor(new Color(value));
ng.fillRect(i, j, 1, 1);
}
}
g.drawImage(buffimage, 0, 0, null);
}
之后就可以把其他的渲染方法逐个改进。以下是图片渲染程序的源代码。
public class ImageUI extends JPanel {
String []bt= {
"原图","方形马赛克","灰度","二值化","轮廓检测","油画绘制","拖动原图马赛克","拖动彩色马赛克","截图","放大","缩小","撤回上一步","清空图片"};
ImageListener listener=new ImageListener();//什么时候static final
JFrame nj=new JFrame();//截图确认窗口
public void initUI()
{
JFrame jf=new JFrame();
jf.setSize(1500,780);
jf.setTitle("图片处理");
jf.setDefaultCloseOperation(3);
jf.setLocationRelativeTo(null);
//按钮功能区面板
JPanel jp1=new JPanel();
jp1.setBackground(new Color(0xafeeee));
Dimension dm=new Dimension(200,780);
jp1.setPreferredSize(dm);
Dimension btdm=new Dimension(190,40);
for(int i=0;i<bt.length;i++)
{
JButton jb =new JButton(bt[i]);
jb.setPreferredSize(btdm);
jb.setBackground(Color.white);
Font font= new Font("黑体",Font.BOLD,20);
jb.setFont(font);
jb.setForeground(new Color(0x000080));
jb.setBackground(new Color(0xf0fff0));
jb.addActionListener(listener);
jp1.add(jb);
}
//绘图区jframe默认边框布局
this.setBackground(new Color(0xffffe0));
jf.add(jp1,BorderLayout.EAST);
jf.add(this,BorderLayout.CENTER);
this.addMouseListener(listener);
this.addMouseMotionListener(listener);
this.addKeyListener(listener);
jf.setVisible(true);
//从jp2 获得画笔
Graphics g=jf.getRootPane().getGraphics();
listener.setgraphics(g);
listener.setjpanel(this);
nj.setTitle("提示");
nj.setSize(300, 150);
//nj.setDefaultCloseOperation(3);
//这里弹出窗口点叉不能设置关闭程序,否则主界面也会跟着关闭
nj.setLocationRelativeTo(jf);
nj.setResizable(false);
JLabel txt =new JLabel("是否确认截图",JLabel.CENTER);
Font fnt= new Font("黑体",Font.BOLD,30);
txt.setFont(fnt);
nj.setLayout(new FlowLayout());
nj.add(txt);
Font fnt2=new Font("黑体", Font.CENTER_BASELINE, 15);
JButton bt =new JButton("确认");
bt.addActionListener(listener);
bt.setPreferredSize(new Dimension(100, 30));
bt.setFont(fnt2);
nj.add(bt);
JButton bt2=new JButton("取消");
bt2.addActionListener(listener);
bt2.setPreferredSize(new Dimension(100, 30));
bt2.setFont(fnt2);
nj.add(bt2);
nj.addWindowListener(listener);
}
@Override
public void paint(Graphics g) {
// TODO Auto-generated method stub
super.paint(g);
System.out.println("fresh"+!listener.freshbuff.isEmpty());
if( !listener.freshbuff.isEmpty())
{
BufferedImage top=( BufferedImage)listener.freshbuff.peek();
g.drawImage(top,0,0,top.getWidth(),top.getHeight() ,null);
System.out.println("调用paint");
}
}
public void clear(Graphics g)
{
super.paint(g);
}
public static void main(String[] args) {
new ImageUI().initUI();
}
}
#前提说明:
①如果一个类需要的接口太多,且接口中的方法又有很
多,且大部分无用,而这个类又不需要继承,那么就可以考虑做一个工具类——实现所有的接口。 然后用所需的类继承这个工具类,选择性的重写方法。
这里监听器类为ImageListener,继承监听器工具类ListenerUtils ,选择性重写接口方法:
public class ImageListener extends ListenerUtils
{
//选择性重写
... ...
}
public class ListenerUtils implements ActionListener,MouseListener,MouseMotionListener
,KeyListener,ChangeListener,WindowListener{
@Override
public void stateChanged(ChangeEvent e) {
// TODO Auto-generated method stub
}
... ... ... ... ..
②为了更好得实现返回上一步功能,定义了两个BufferedImage栈,考虑到,窗口改变执行的peek()操作,返回上一步执行的是pop()操作,所以用一个栈不容易将功能正确实现。(读者也可以自己定义不同的数据类型存储BufferedImage,可能会更加方便)
刷新栈:
窗口改变大小实现图片重绘。
public Stack<BufferedImage> freshbuff=new Stack<BufferedImage>();
操作栈:
记录每一次的执行结果,以实现返回上一步功能。
public Stack<BufferedImage> buffstack =new Stack<BufferedImage>();
具体代码如下:
public class ImageListener extends ListenerUtils {
int[][] imgarr;
String btn="";
String path="E:\\java\\eclipse\\eclipse javaee\\workspace\\Yu java\\66.jpg";
private Graphics g;
ImageUtils imageff;
ImageUI jp;
public Stack<BufferedImage> buffstack =new Stack<BufferedImage>();
public Stack<BufferedImage> freshbuff=new Stack<BufferedImage>();
int index;
int p_x,p_y;
int r_x,r_y;
int d_x,d_y;
public void setgraphics(Graphics g)
{
this.g=g;
}
public void setjpanel(ImageUI jp)
{
this.jp=jp;
}
//初始化监听器
ImageListener()
{
imageff=new ImageUtils();
imgarr=imageff.getImagePixel(path);
System.out.println("初始化成功"+imgarr.length);
}
@Override
public void windowClosing(WindowEvent e) {
// TODO Auto-generated method stub
super.windowClosed(e);
jp.paint(g);
}
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
System.out.println("当前"+btn);
//System.out.println("调用actionperformed");
btn=e.getActionCommand();
if(btn.equals("原图"))
{
jp.clear(g);
BufferedImage img= imageff.paint1(g,imgarr);
buffstack.push(img);
freshbuff.push(img);
System.out.println("栈顶"+buffstack.peek().getWidth());
System.out.println("栈内元素数"+buffstack.size());
}
else if(btn.equals("方形马赛克"))
{
jp.clear(g);
imageff.paint2(g, freshbuff,buffstack);
}
else if(btn.equals("灰度"))
{
jp.clear(g);
imageff.paint3(g, freshbuff,buffstack);
}
else if(btn.equals("二值化"))
{
jp.clear(g);
imageff.paint4(g, freshbuff,buffstack);
}
else if(btn.equals("轮廓检测"))
{
jp.clear(g);
imageff.paint5(g, freshbuff,buffstack);
}
else if(btn.equals("油画绘制"))
{
jp.clear(g);
imageff.paint6(g, freshbuff,buffstack);
}
else if(btn.equals("放大"))
{
jp.clear(g);
imageff.piant7(g, freshbuff,buffstack);
jp.paint(g);
}
else if(btn.equals("缩小"))
{
jp.clear(g);
imageff.paint8(g,freshbuff,buffstack );
jp.paint(g);
}
else if(btn.equals("清空图片"))
{
jp.clear(g);
imageff.withdraw(g,jp,buffstack,freshbuff);
}
else if (btn.equals("撤回上一步"))
{
jp.clear(g);
freshbuff.push(imageff.backward(buffstack,g));
}
else if(btn.equals("确认"))
{
jp.clear(g);
imageff.paint12(g, freshbuff, buffstack,p_x,p_y,r_x,r_y);
System.out.println("截图完成");
jp.nj.dispose();
}
else if(btn.equals("取消"))
{
jp.nj.dispose();
jp.paint(g);
}
}
@Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
super.mousePressed(e);
p_x=e.getX();
p_y=e.getY();
d_x=e.getX();
d_y=e.getY();
}
@Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
super.mouseReleased(e);
r_x=e.getX();
r_y=e.getY();
if(btn.equals("截图"))
{
Graphics2D g2d=(Graphics2D)g;
g2d.setStroke(new BasicStroke(2.5f, BasicStroke.CAP_BUTT,
BasicStroke.JOIN_ROUND, 3.5f, new float[] {
10, 5 }, 0f));
g2d.setColor(Color.GREEN);
g2d.drawRect(Math.min(p_x, r_x), Math.min(p_y, r_y),Math.abs(r_x-p_x) ,Math.abs(r_y-p_y));
jp.nj.setVisible(true);
}
}
@Override
public void mouseDragged(MouseEvent e) {
// TODO Auto-generated method stub
super.mouseDragged(e);
int x=e.getX();
int y=e.getY();
if(btn.equals("拖动原图马赛克"))
{
if(Math.abs(x-d_x)>10||Math.abs(y-d_y)>10)
{
imageff.paint9(g,freshbuff,buffstack,x,y);
d_x=x;d_y=y;
}
}
if(btn.equals("拖动彩色马赛克"))
{
if(Math.abs(x-d_x)>10||Math.abs(y-d_y)>10)
{
imageff.paint10(g,freshbuff,buffstack,x,y);
d_x=x;d_y=y;
}
}
}
@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
super.keyPressed(e);
}
}
图片的渲染代码:
#说明
这里定义一个当前类的布尔全局变量flag,用来判断在返回上一步这个操作中,应该是对操作栈buffstack执行pop()操作还是peek()。例如:因为操作栈中栈顶还存着当前画图结果,如果栈中元素>1的话,得执行两次pop()方法才能返回上一步,这样就得按两次按钮才能实现理想效果。flag等于true表示当前渲染过后的图片还在操作栈中。就得执行两次pop。
public class ImageUtils {
boolean flag=true;
String name="";
//读取文件,获得图片像素
public int[][] getImagePixel(String path)
{
//读取文件的数据
File file =new File(path);
//imageIO操作将图片文件的输入输出,
//读取文件数据
BufferedImage buffimage=null;
try {
buffimage=ImageIO.read(file);
}catch (IOException e) {
e.printStackTrace();
System.err.println("图像读取失败");
}
//获取缓冲图片的大小,初始化保存像素值得二维数组
int w=buffimage.getWidth();
int h=buffimage.getHeight();
int [][]arrPixel=new int[w][h];
for(int i=0;i<w;i++)
{
for(int j=0;j<h;j++)
{
int pixel=buffimage.getRGB(i, j);
arrPixel[i][j]=pixel;
}
}
return arrPixel;
}
//清空图片
public void withdraw(Graphics g,ImageUI jp,Stack<BufferedImage> buff,Stack<BufferedImage> freshbuff)
{
jp.clear(g);
buff.clear();
freshbuff.clear();
flag=true;
}
//原图方法
public BufferedImage paint1(Graphics g,int[][] arrpixel)
{
BufferedImage buffimage=new BufferedImage(arrpixel.length, arrpixel[0].length,BufferedImage.TYPE_INT_RGB);
Graphics ng=buffimage.getGraphics();
for(int i=0;i<arrpixel.length;i++)
{
for(int j=0;j<arrpixel[0].length;j++)
{
int value=arrpixel[i][j];
if(i==0&&j==0)
{
System.out.println("arrpixel:"+value);}
ng.setColor(new Color(value));
ng.fillRect(i, j, 1, 1);
//buffimage.setRGB(i, j, value);//一次性将所有像素存储完成
}
}
g.drawImage(buffimage, 0, 0, null);
flag=true;
return buffimage;
}
//方形马赛克改进算法
public void paint2(Graphics g,Stack<BufferedImage> freshbuff,Stack<BufferedImage> stackbuff)
{
if(!freshbuff.isEmpty())
{
BufferedImage buff=freshbuff.peek();
int newwidth=buff.getWidth();
int newheight=buff.getHeight();
BufferedImage buffimage=new BufferedImage(newwidth,newheight,BufferedImage.TYPE_INT_RGB);
Graphics ng=buffimage.getGraphics();
for(int i=0;i<newwidth;i+=10)
{
for(int j=0;j<newheight;j+=10)
{
int rgb=buff.getRGB(i, j);
ng.setColor(new Color(rgb));
ng.fillRect(i, j, 10, 10);
}
}
g.drawImage(buffimage, 0, 0, null);
flag=true;
freshbuff.push(buffimage);
stackbuff.push(buffimage);
}
}
//灰度方法
public void paint3(Graphics g,Stack<BufferedImage> freshbuff,Stack<BufferedImage> stackbuff)
{
if(!freshbuff.isEmpty())
{
BufferedImage buff=freshbuff.peek();
int newwidth=buff.getWidth();
int newheight=buff.getHeight();
BufferedImage buffimage=new BufferedImage(newwidth,newheight,BufferedImage.TYPE_INT_RGB);
for(int i=0;i<buff.getWidth();i++)
{
for(int j=0;j<buff.getHeight();j++)
{
int value =buff.getRGB(i, j);
int red=(value>>16)&0xFF;
int green=(value>>8)&0xFF;
int blue=(value>>0)&0xFF;
int gray =(red+green+blue)/3;
int newvalue=(gray<<16)+(gray<<8)+(gray<<0);
buffimage.setRGB(i, j, newvalue);//一次性将所有像素存储完成
}
}
g.drawImage(buffimage, 0, 0, null);
flag=true;
freshbuff.push(buffimage);
stackbuff.push(buffimage);
}
}
//二值化方法
public void paint4(Graphics g,Stack<BufferedImage> freshbuff,Stack<BufferedImage> stackbuff)
{
if(!freshbuff.isEmpty())
{
BufferedImage buff=freshbuff.peek();
int newwidth=buff.getWidth();
int newheight=buff.getHeight();
BufferedImage buffimage=new BufferedImage(newwidth,newheight,BufferedImage.TYPE_INT_RGB);
for(int i=0;i<newwidth;i++)
{
for(int j=0;j<newheight;j++)
{
int value =buff.getRGB(i, j);
int red=(value>>16)&0xFF;
int green=(value>>8)&0xFF;
int blue=(value>>0)&0xFF;
int gray=(int)(red*0.4+green*0.5+blue*0.6);
// int newvalue=(gray<<16)+(gray<<8)+(gray<<0);
if(gray<150)
{
buffimage.setRGB(i, j, Color.black.getRGB());
}
else
{
buffimage.setRGB(i, j, Color.white.getRGB());
}
}
}
g.drawImage(buffimage, 0, 0, null);
flag=true;
freshbuff.push(buffimage);
stackbuff.push(buffimage);
}
}
//轮廓检测
//相邻之间的像素点进行比较
public void paint5(Graphics g ,Stack<BufferedImage> freshbuff,Stack<BufferedImage> stackbuff)
{
if(!freshbuff.isEmpty())
{
BufferedImage buff=freshbuff.peek();
int newwidth=buff.getWidth();
int newheight=buff.getHeight();
BufferedImage buffimage=new BufferedImage(newwidth,newheight,BufferedImage.TYPE_INT_RGB);
for(int i=0;i<newwidth-2;i++)
{
for(int j=0;j<newheight-2;j++)
{
int value =buff.getRGB(i, j);
int red=(value>>16)&0xFF;
int green=(value>>8)&0xFF;
int blue=(value>>0)&0xFF;
int valuen=buff.getRGB(i+2, j+2);
int redn=(valuen>>16)&0xFF;
int greenn=(valuen>>8)&0xFF;
int bluen=(valuen>>0)&0xFF;
//int gray =(red+green+blue)/3;
int gray =(int)(red*0.41+green*0.28+blue*0.31);
int grayn =(int)(redn*0.41+greenn*0.28+bluen*0.31);
if(Math.abs(gray-grayn)>15){
buffimage.setRGB(i, j, Color.pink.getRGB());
}else{
buffimage.setRGB(i, j, Color.white.getRGB());
}
}
}
g.drawImage(buffimage, 0, 0, null);
flag=true;
freshbuff.push(buffimage);
stackbuff.push(buffimage);
}
}
//油画算法
public void paint6(Graphics g ,Stack<BufferedImage> freshbuff,Stack<BufferedImage> stackbuff)
{
if(!freshbuff.isEmpty())
{
BufferedImage buff=freshbuff.peek();
int newwidth=buff.getWidth();
int newheight=buff.getHeight();
BufferedImage buffimage=new BufferedImage(newwidth,newheight,BufferedImage.TYPE_INT_RGB);
Random random = new Random();
int size=random.nextInt(5);
for(int i=0;i<newwidth;i+=3)
{
for(int j=0;j<newheight;j+=3)
{
int pixel=buff.getRGB(i, j);
int h=i,m=j;
for(int k=0;k<3;k++)
{
for(int p=0;p<3;p++)
{
if(h<newwidth&&m<newheight)
buffimage.setRGB(h,m++,pixel);
}
h++;
m=j+size;
}
}
}
g.drawImage(buffimage, 0, 0, null);
flag=true;
freshbuff.push(buffimage);
stackbuff.push(buffimage);
}
}
//截图
public void paint12(Graphics g,Stack<BufferedImage> freshbuff,Stack<BufferedImage> stackbuff,int px,int py,int rx,int ry)
{
if(!freshbuff.isEmpty())
{
BufferedImage buff=freshbuff.peek();
int newwidth=Math.abs(px-rx);
int newheight=Math.abs(py-ry);
BufferedImage buffimage=new BufferedImage(newwidth, newheight, BufferedImage.TYPE_INT_RGB);
int minx=Math.min(rx, px);
int maxx=Math.max(rx, px);
int miny=Math.min(ry, py);
int maxy=Math.max(ry, py);
System.out.println("minx"+minx+"maxx"+maxx+"miny"+miny+"maxy"+maxy);
int h=0,m=0;
for(int i=minx;i<=maxx;i++)
{
for(int j=miny;j<=maxy;j++)
{
int rgb=buff.getRGB(i, j);
if(h<newwidth&&m<newheight)
{
buffimage.setRGB(h, m++, rgb);
}
}
h++;
m=0;
}
g.drawImage(buffimage, 0, 0, null);
flag=true;
freshbuff.push(buffimage);
stackbuff.push(buffimage);
}
}
//放大
public void piant7(Graphics g,Stack<BufferedImage> freshbuff,Stack<BufferedImage> stackbuff)
{
if(!freshbuff.isEmpty())
{
BufferedImage buff=freshbuff.peek();
int newwidth=buff.getWidth()+(int)((buff.getWidth()*20)/100);
int newheight=buff.getHeight()+(int)((buff.getHeight()*20)/100);
BufferedImage buffimage=new BufferedImage(newwidth, newheight, BufferedImage.TYPE_INT_RGB);
Graphics ng=buffimage.getGraphics();
ng.drawImage(buff,0,0, newwidth, newheight, null);
g.drawImage(buffimage,0,0, null);
flag=true;
freshbuff.push(buffimage);
stackbuff.push(buffimage);
}
}
//缩小
public void paint8(Graphics g,Stack<BufferedImage> freshbuff,Stack<BufferedImage> stackbuff)
{
if(!freshbuff.isEmpty())
{
BufferedImage buff=freshbuff.peek();
int newwidth=(int)((buff.getWidth()*80)/100);
int newheight=(int)((buff.getHeight()*80)/100);
BufferedImage buffimage=new BufferedImage(newwidth, newheight,BufferedImage.TYPE_INT_RGB );
Graphics ng=buffimage.getGraphics();
ng.drawImage(buff, 0,0,newwidth, newheight, null);//一定要注明起点0,0
g.drawImage(buffimage,0,0, null);
flag=true;
freshbuff.push(buffimage);
stackbuff.push(buffimage);
}
}
//拖动马赛克
public void paint9(Graphics g,Stack<BufferedImage> freshbuff,Stack<BufferedImage> stackbuff,int x,int y)
{
if(!stackbuff.isEmpty())
{
BufferedImage buff= stackbuff.peek();
BufferedImage buffimage=new BufferedImage(buff.getWidth(), buff.getHeight(), BufferedImage.TYPE_INT_RGB);
if(buff.getWidth()<x||buff.getHeight()<y)
return;
int rgb=buff.getRGB(x, y);
for(int i=0;i<buff.getWidth();i++)
{
for(int j=0;j<buff.getHeight();j++)
{
int RGB=buff.getRGB(i, j);
buffimage.setRGB(i,j , RGB);
}
}
for(int i=x;i<x+20;i++)
{
for(int j=y;j<y+20;j++)
{
if(i<buffimage.getWidth()&&j<buffimage.getHeight())
buffimage.setRGB(i, j, rgb);
}
}
g.drawImage(buffimage, 0, 0,buffimage.getWidth(),buffimage.getHeight(), null);
freshbuff.push(buffimage);
stackbuff.push(buffimage);
System.out.println("stack"+stackbuff.size());
flag=true;
}
}
//拖动彩色马赛克
public void paint10(Graphics g,Stack<BufferedImage> freshbuff,Stack<BufferedImage> stackbuff,int x,int y)
{
if(!stackbuff.isEmpty())
{
BufferedImage buff= stackbuff.peek();
if(buff.getWidth()<x||buff.getHeight()<y)
return;
BufferedImage buffimage=new BufferedImage(buff.getWidth(), buff.getHeight(), BufferedImage.TYPE_INT_RGB);
for(int i=0;i<buff.getWidth();i++)
{
for(int j=0;j<buff.getHeight();j++)
{
int RGB=buff.getRGB(i, j);
buffimage.setRGB(i,j , RGB);
}
}
Random ram=new Random();
int rgb=ram.nextInt(0xffffff);
Graphics ng=buffimage.getGraphics();
ng.setColor(new Color(rgb));
ng.fillOval(x, y, 20, 20);
g.drawImage(buffimage, 0, 0,buffimage.getWidth(),buffimage.getHeight(), null);
freshbuff.push(buffimage);
stackbuff.push(buffimage);
System.out.println("stack"+stackbuff.size());
flag=true;
}
}
//返回上一步
public BufferedImage backward(Stack<BufferedImage> buff,Graphics g)
{
BufferedImage top=null;
if(!buff.isEmpty())
System.out.println("stack"+buff.size());
{
if(buff.size()==1)
{
top=buff.peek();
g.drawImage(top,0,0,top.getWidth(),top.getHeight(),null);
}
else
{
if(flag==true&&buff.size()>1)
{
top=buff.pop();
if(buff.size()==1)
{
top=buff.peek();
g.drawImage(top,0,0,top.getWidth(),top.getHeight(),null);
}
else
{
top=buff.pop();
g.drawImage(top,0,0,top.getWidth(),top.getHeight(),null);
}
}
if(flag==false&&buff.size()>1)
{
top=buff.pop();
g.drawImage(top,0,0,top.getWidth(),top.getHeight(),null);
}
}
}
flag=false;
System.out.println("stack"+buff.size());
return top;
}
}
图片处理 2021-07-21 23-18-15
由于录屏问题,弹出界面没显示,截屏如下