千里冰封
JAVA 浓香四溢
posts - 151,comments - 2801,trackbacks - 0

刚才把截屏程序放出去之后,收到了朋友BeanSoft 的建议,刚来这里就能认识他,很高兴,现在又改进了一下,改进的地方如下

1,修复了选择选区后,再改变大小时,当把右侧的边框拖过左侧或者左侧的边框拖到右侧或者上面的边框拖过下面,只会显示一条边框的BUG.
2,在没有截屏的时候,会有一条提示的字符串跟着鼠标走.
3,在点了截屏之后,主窗口会先隐藏起来,截完图后才会弹出来
4,去掉了截屏时的自定义鼠标显示,因为这样的话,源代码编译之后,运行会出问题,因为别人的电脑上没有我那个鼠标的图片.
5,增加了可保存的图片格式,现在可保存(JPG,GIF,PNG,BMP)格式

源代码附上,可以直接自己编译,打成JAR包.我这里也提供一下可执行JAR包的下载.


点击下载可执行的JAR包
/*
 * CaptureScreen.java
 *
 * Created on 2007年8月30日, 下午12:46
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 
*/


package hadeslee.swing;

/**
 *
 * 
@author lbf
 
*/

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import javax.imageio.*;
import java.awt.image.*;
public class CaptureScreen extends JFrame implements ActionListener{
    
private JButton start,cancel,save;
    
private JPanel c;
    
private BufferedImage get;
    
/** Creates a new instance of CaptureScreen */
    
public CaptureScreen() {
        
super("屏幕截取软件(第二版)");
        initWindow();
    }

    
private void initWindow(){
        start
=new JButton("开始截取");
        cancel
=new JButton("退出");
        save
=new JButton("保存");
        save.setEnabled(
false);
        save.addActionListener(
this);
        start.addActionListener(
this);
        cancel.addActionListener(
this);
        JPanel buttonJP
=new JPanel();
        c
=new JPanel(new BorderLayout());
        JLabel jl
=new JLabel("屏幕截取",JLabel.CENTER);
        JLabel jl1
=new JLabel("作者:千里冰封",JLabel.CENTER);
        jl.setFont(
new Font("黑体",Font.BOLD,40));
        jl1.setFont(
new Font("宋体",Font.BOLD,20));
        jl.setForeground(Color.RED);
        jl1.setForeground(Color.BLUE);
        c.add(jl,BorderLayout.CENTER);
        c.add(jl1,BorderLayout.SOUTH);
        buttonJP.add(start);
        buttonJP.add(save);
        buttonJP.add(cancel);
        
this.getContentPane().add(c,BorderLayout.CENTER);
        
this.getContentPane().add(buttonJP,BorderLayout.SOUTH);
        
this.setSize(300,300);
        
this.setLocationRelativeTo(null);
        
this.setVisible(true);
        
this.setAlwaysOnTop(true);
        
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    
private void updates(){
        
this.setVisible(true);
        
if(get!=null){
            save.setEnabled(
true);
            ImageIcon ii
=new ImageIcon(get);
            JLabel jl
=new JLabel(ii);
            c.removeAll();
            c.add(
new JScrollPane(jl),BorderLayout.CENTER);
            SwingUtilities.updateComponentTreeUI(
this);
        }

    }

    
private void doStart(){
        
try{
            
this.setVisible(false);
            Thread.sleep(
500);//睡500毫秒是为了让主窗完全不见
            Robot ro=new Robot();
            Toolkit tk
=Toolkit.getDefaultToolkit();
            Dimension di
=tk.getScreenSize();
            Rectangle rec
=new Rectangle(0,0,di.width,di.height);
            BufferedImage bi
=ro.createScreenCapture(rec);
            JFrame jf
=new JFrame();
            Temp temp
=new Temp(jf,bi,di.width,di.height);
            jf.getContentPane().add(temp,BorderLayout.CENTER);
            jf.setUndecorated(
true);
            jf.setSize(di);
            jf.setVisible(
true);
            jf.setAlwaysOnTop(
true);
        }
 catch(Exception exe){
            exe.printStackTrace();
        }

    }
 
    
private void doSave(){
        
try{
            JFileChooser jfc
=new JFileChooser(".");
            jfc.addChoosableFileFilter(
new JPGfilter());
            jfc.addChoosableFileFilter(
new PNGfilter());
            jfc.addChoosableFileFilter(
new GIFfilter());
            jfc.addChoosableFileFilter(
new BMPfilter());
            
int i=jfc.showSaveDialog(this);
            
if(i==JFileChooser.APPROVE_OPTION){
                File file
=jfc.getSelectedFile();
                String about
="PNG";
                String ext
=file.toString().toLowerCase();
                javax.swing.filechooser.FileFilter ff
=jfc.getFileFilter();
                
if(ff instanceof JPGfilter){
                    
if(!ext.endsWith(".jpg")){
                        String ns
=ext+".jpg";
                        file
=new File(ns);
                        about
="JPG";
                    }

                }
 else if(ff instanceof PNGfilter){
                    
if(!ext.endsWith(".png")){
                        String ns
=ext+".png";
                        file
=new File(ns);
                        about
="PNG";
                    }

                }
else if(ff instanceof BMPfilter){
                    
if(!ext.endsWith(".bmp")){
                        String ns
=ext+".bmp";
                        file
=new File(ns);
                        about
="BMP";
                    }

                }
else if(ff instanceof GIFfilter){
                    
if(!ext.endsWith(".gif")){
                        String ns
=ext+".gif";
                        file
=new File(ns);
                        about
="GIF";
                    }

                }

                
if(ImageIO.write(get,about,file)){
                    JOptionPane.showMessageDialog(
this,"保存成功!");
                }
 else
                    JOptionPane.showMessageDialog(
this,"保存失败!");
            }

        }
 catch(Exception exe){
            exe.printStackTrace();
        }

    }

    
public void actionPerformed(ActionEvent ae){
        
if(ae.getSource()==start){
            doStart();
        }
 else if(ae.getSource()==cancel){
            System.exit(
0);
        }
 else if(ae.getSource()==save){
            doSave();
        }

    }

    
//保存BMP格式的过滤器
    private class BMPfilter extends javax.swing.filechooser.FileFilter{
        
public BMPfilter(){
            
        }

        
public boolean accept(File file){
            
if(file.toString().toLowerCase().endsWith(".bmp")||
                    file.isDirectory())
{
                
return true;
            }
 else
                
return false;
        }

        
public String getDescription(){
            
return "*.BMP(BMP图像)";
        }

    }

    
//保存JPG格式的过滤器
    private class JPGfilter extends javax.swing.filechooser.FileFilter{
        
public JPGfilter(){
            
        }

        
public boolean accept(File file){
            
if(file.toString().toLowerCase().endsWith(".jpg")||
                    file.toString().toLowerCase().endsWith(
".jpeg")||
                    file.isDirectory())
{
                
return true;
            }
 else
                
return false;
        }

        
public String getDescription(){
            
return "*.JPG,*.JPEG(JPG,JPEG图像)";
        }

    }

    
//保存GIF格式的过滤器
    private class GIFfilter extends javax.swing.filechooser.FileFilter{
        
public GIFfilter(){
            
        }

        
public boolean accept(File file){
            
if(file.toString().toLowerCase().endsWith(".gif")||
                    file.isDirectory())
{
                
return true;
            }
 else
                
return false;
        }

        
public String getDescription(){
            
return "*.GIF(GIF图像)";
        }

    }

    
    
//保存PNG格式的过滤器
    private class PNGfilter extends javax.swing.filechooser.FileFilter{
        
public boolean accept(File file){
            
if(file.toString().toLowerCase().endsWith(".png")||
                    file.isDirectory())
{
                
return true;
            }
 else
                
return false;
        }

        
public String getDescription(){
            
return "*.PNG(PNG图像)";
        }

    }

    
//一个暂时类,用于显示当前的屏幕图像
    private class Temp extends JPanel implements MouseListener,MouseMotionListener{
        
private BufferedImage bi;
        
private int width,height;
        
private int startX,startY,endX,endY,tempX,tempY;
        
private JFrame jf;
        
private Rectangle select=new Rectangle(0,0,0,0);//表示选中的区域
        private Cursor cs=new Cursor(Cursor.CROSSHAIR_CURSOR);//表示一般情况下的鼠标状态
        private States current=States.DEFAULT;// 表示当前的编辑状态
        private Rectangle[] rec;//表示八个编辑点的区域
        
//下面四个常量,分别表示谁是被选中的那条线上的端点
        public static final int START_X=1;
        
public static final int START_Y=2;
        
public static final int END_X=3;
        
public static final int END_Y=4;
        
private int currentX,currentY;//当前被选中的X和Y,只有这两个需要改变
        private Point p=new Point();//当前鼠标移的地点
        private boolean showTip=true;//是否显示提示.如果鼠标左键一按,则提示不再显了
        public Temp(JFrame jf,BufferedImage bi,int width,int height){
            
this.jf=jf;
            
this.bi=bi;
            
this.width=width;
            
this.height=height;
            
this.addMouseListener(this);
            
this.addMouseMotionListener(this);
            initRecs();
        }

        
private void initRecs(){
            rec
=new Rectangle[8];
            
for(int i=0;i<rec.length;i++){
                rec[i]
=new Rectangle();
            }

        }

        
public void paintComponent(Graphics g){
            g.drawImage(bi,
0,0,width,height,this);
            g.setColor(Color.RED);
            g.drawLine(startX,startY,endX,startY);
            g.drawLine(startX,endY,endX,endY);
            g.drawLine(startX,startY,startX,endY);
            g.drawLine(endX,startY,endX,endY);
            
int x=startX<endX?startX:endX;
            
int y=startY<endY?startY:endY;
            select
=new Rectangle(x,y,Math.abs(endX-startX),Math.abs(endY-startY));
            
int x1=(startX+endX)/2;
            
int y1=(startY+endY)/2;
            g.fillRect(x1
-2,startY-2,5,5);
            g.fillRect(x1
-2,endY-2,5,5);
            g.fillRect(startX
-2,y1-2,5,5);
            g.fillRect(endX
-2,y1-2,5,5);
            g.fillRect(startX
-2,startY-2,5,5);
            g.fillRect(startX
-2,endY-2,5,5);
            g.fillRect(endX
-2,startY-2,5,5);
            g.fillRect(endX
-2,endY-2,5,5);
            rec[
0]=new Rectangle(x-5,y-5,10,10);
            rec[
1]=new Rectangle(x1-5,y-5,10,10);
            rec[
2]=new Rectangle((startX>endX?startX:endX)-5,y-5,10,10);
            rec[
3]=new Rectangle((startX>endX?startX:endX)-5,y1-5,10,10);
            rec[
4]=new Rectangle((startX>endX?startX:endX)-5,(startY>endY?startY:endY)-5,10,10);
            rec[
5]=new Rectangle(x1-5,(startY>endY?startY:endY)-5,10,10);
            rec[
6]=new Rectangle(x-5,(startY>endY?startY:endY)-5,10,10);
            rec[
7]=new Rectangle(x-5,y1-5,10,10);
            
if(showTip){
                g.setColor(Color.CYAN);
                g.fillRect(p.x,p.y,
170,20);
                g.setColor(Color.RED);
                g.drawRect(p.x,p.y,
170,20);
                g.setColor(Color.BLACK);
                g.drawString(
"请按住鼠标左键不放选择截图区",p.x,p.y+15);
            }

        }

        
//根据东南西北等八个方向决定选中的要修改的X和Y的座标
        private void initSelect(States state){
            
switch(state){
                
case DEFAULT:
                    currentX
=0;
                    currentY
=0;
                    
break;
                
case EAST:
                    currentX
=(endX>startX?END_X:START_X);
                    currentY
=0;
                    
break;
                
case WEST:
                    currentX
=(endX>startX?START_X:END_X);
                    currentY
=0;
                    
break;
                
case NORTH:
                    currentX
=0;
                    currentY
=(startY>endY?END_Y:START_Y);
                    
break;
                
case SOUTH:
                    currentX
=0;
                    currentY
=(startY>endY?START_Y:END_Y);
                    
break;
                
case NORTH_EAST:
                    currentY
=(startY>endY?END_Y:START_Y);
                    currentX
=(endX>startX?END_X:START_X);
                    
break;
                
case NORTH_WEST:
                    currentY
=(startY>endY?END_Y:START_Y);
                    currentX
=(endX>startX?START_X:END_X);
                    
break;
                
case SOUTH_EAST:
                    currentY
=(startY>endY?START_Y:END_Y);
                    currentX
=(endX>startX?END_X:START_X);
                    
break;
                
case SOUTH_WEST:
                    currentY
=(startY>endY?START_Y:END_Y);
                    currentX
=(endX>startX?START_X:END_X);
                    
break;
                
default:
                    currentX
=0;
                    currentY
=0;
                    
break;
            }

        }

        
public void mouseMoved(MouseEvent me){
            doMouseMoved(me);
            initSelect(current);
            
if(showTip){
                p
=me.getPoint();
                repaint();
            }

        }

        
//特意定义一个方法处理鼠标移动,是为了每次都能初始化一下所要选择的地区
        private void doMouseMoved(MouseEvent me){
            
if(select.contains(me.getPoint())){
                
this.setCursor(new Cursor(Cursor.MOVE_CURSOR));
                current
=States.MOVE;
            }
 else{
                States[] st
=States.values();
                
for(int i=0;i<rec.length;i++){
                    
if(rec[i].contains(me.getPoint())){
                        current
=st[i];
                        
this.setCursor(st[i].getCursor());
                        
return;
                    }

                }

                
this.setCursor(cs);
                current
=States.DEFAULT;
            }

        }

        
public void mouseExited(MouseEvent me){
            
        }

        
public void mouseEntered(MouseEvent me){
            
        }

        
public void mouseDragged(MouseEvent me){
            
int x=me.getX();
            
int y=me.getY();
            
if(current==States.MOVE){
                startX
+=(x-tempX);
                startY
+=(y-tempY);
                endX
+=(x-tempX);
                endY
+=(y-tempY);
                tempX
=x;
                tempY
=y;
            }
else if(current==States.EAST||current==States.WEST){
                
if(currentX==START_X){
                    startX
+=(x-tempX);
                    tempX
=x;
                }
else{
                    endX
+=(x-tempX);
                    tempX
=x;
                }

            }
else if(current==States.NORTH||current==States.SOUTH){
                
if(currentY==START_Y){
                    startY
+=(y-tempY);
                    tempY
=y;
                }
else{
                    endY
+=(y-tempY);
                    tempY
=y;
                }

            }
else if(current==States.NORTH_EAST||current==States.NORTH_EAST||
                    current
==States.SOUTH_EAST||current==States.SOUTH_WEST){
                
if(currentY==START_Y){
                    startY
+=(y-tempY);
                    tempY
=y;
                }
else{
                    endY
+=(y-tempY);
                    tempY
=y;
                }

                
if(currentX==START_X){
                    startX
+=(x-tempX);
                    tempX
=x;
                }
else{
                    endX
+=(x-tempX);
                    tempX
=x;
                }

                
            }
else{
                startX
=tempX;
                startY
=tempY;
                endX
=me.getX();
                endY
=me.getY();
            }

            
this.repaint();
        }

        
public void mousePressed(MouseEvent me){
            showTip
=false;
            tempX
=me.getX();
            tempY
=me.getY();
        }

        
public void mouseReleased(MouseEvent me){
            
if(me.isPopupTrigger()){
                
if(current==States.MOVE){
                    showTip
=true;
                    p
=me.getPoint();
                    startX
=0;
                    startY
=0;
                    endX
=0;
                    endY
=0;
                    repaint();
                }
 else{
                    jf.dispose();
                    updates();
                }

                
            }

        }

        
public void mouseClicked(MouseEvent me){
            
if(me.getClickCount()==2){
                
//Rectangle rec=new Rectangle(startX,startY,Math.abs(endX-startX),Math.abs(endY-startY));
                Point p=me.getPoint();
                
if(select.contains(p)){
                    
if(select.x+select.width<this.getWidth()&&select.y+select.height<this.getHeight()){
                        get
=bi.getSubimage(select.x,select.y,select.width,select.height);
                        jf.dispose();
                        save.setEnabled(
true);
                        updates();
                    }
else{
                        
int wid=select.width,het=select.height;
                        
if(select.x+select.width>=this.getWidth()){
                            wid
=this.getWidth()-select.x;
                        }

                        
if(select.y+select.height>=this.getHeight()){
                            het
=this.getHeight()-select.y;
                        }

                        get
=bi.getSubimage(select.x,select.y,wid,het);
                        jf.dispose();
                        save.setEnabled(
true);
                        updates();
                    }

                    
                }

            }

        }

    }

    
    
public static void main(String args[]){
        
new CaptureScreen();
    }

}

enum States{
    NORTH_WEST(
new Cursor(Cursor.NW_RESIZE_CURSOR)),//表示西北角
    NORTH(new Cursor(Cursor.N_RESIZE_CURSOR)),
    NORTH_EAST(
new Cursor(Cursor.NE_RESIZE_CURSOR)),
    EAST(
new Cursor(Cursor.E_RESIZE_CURSOR)),
    SOUTH_EAST(
new Cursor(Cursor.SE_RESIZE_CURSOR)),
    SOUTH(
new Cursor(Cursor.S_RESIZE_CURSOR)),
    SOUTH_WEST(
new Cursor(Cursor.SW_RESIZE_CURSOR)),
    WEST(
new Cursor(Cursor.W_RESIZE_CURSOR)),
    MOVE(
new Cursor(Cursor.MOVE_CURSOR)),
    DEFAULT(
new Cursor(Cursor.DEFAULT_CURSOR));
    
private Cursor cs;
    States(Cursor cs)
{
        
this.cs=cs;
    }

    
public Cursor getCursor(){
        
return cs;
    }

}




尽管千里冰封
依然拥有晴空

你我共同品味JAVA的浓香.
posted on 2007-08-30 14:40 千里冰封 阅读(3421) 评论(14)  编辑  收藏 所属分类: JAVASE

FeedBack:
# re: JAVA截屏程序(第二版)
2007-08-30 17:26 | JAVA面试题
速度真快,崇拜中。。。。  回复  更多评论
  
# re: JAVA截屏程序(第二版)
2007-08-30 17:30 | BeanSoft
支持到死, 呵呵.  回复  更多评论
  
# re: JAVA截屏程序(第二版)[未登录]
2007-08-30 18:25 | Samuel
哈哈!不错啊!!
我上午刚发现的问题这么快就解决了。。

优化了很多。
佩服!

1、希望增加拷贝剪切图到剪贴板上去的功能,。这样就可以直接拷贝word中。而不需要另存文件来考取。

2、希望增加tabpanel来显示每次截取的图。并支持对选中的tabpanel中拷贝到剪贴板。。

慢慢完善功能,一不小心就做一个成熟的软件来。

功能一定要小巧,不能过去庞大,否则就操作就不是很方便了。。  回复  更多评论
  
# re: JAVA截屏程序(第二版)
2007-08-30 21:44 | Pande
挺有意思的方法,可是能实现的抓取方式太有限了,要做强还得用native的API  回复  更多评论
  
# re: JAVA截屏程序(第二版)
2007-08-30 23:09 | BeanSoft
是呀, 上次有人用 SWT 做了个 Native 的, 可惜, 不带源码唉... 关于 Robot 类和截屏, 理论上可以做远程控制了, 参考:
http://gro.clinux.org/forum/forum.php?forum_id=2597

Java 远程控制 1.0 测试版发布  回复  更多评论
  
# re: JAVA截屏程序(第二版)
2007-08-31 09:49 | Bruce
public static void main(String args[]){
new CaptureScreen();
}
}
enum States{
NORTH_WEST(new Cursor(Cursor.NW_RESIZE_CURSOR)),//表示西北角
NORTH(new Cursor(Cursor.N_RESIZE_CURSOR)),
NORTH_EAST(new Cursor(Cursor.NE_RESIZE_CURSOR)),
EAST(new Cursor(Cursor.E_RESIZE_CURSOR)),
SOUTH_EAST(new Cursor(Cursor.SE_RESIZE_CURSOR)),
SOUTH(new Cursor(Cursor.S_RESIZE_CURSOR)),
SOUTH_WEST(new Cursor(Cursor.SW_RESIZE_CURSOR)),
WEST(new Cursor(Cursor.W_RESIZE_CURSOR)),
MOVE(new Cursor(Cursor.MOVE_CURSOR)),
DEFAULT(new Cursor(Cursor.DEFAULT_CURSOR));
private Cursor cs;
States(Cursor cs){
this.cs=cs;
}
老大,我的这个在我这里编译不通过。。。。是咱回事?  回复  更多评论
  
# re: JAVA截屏程序(第二版)
2007-08-31 10:46 | 千里冰封
@Bruce
可能你那里用的JDK是低于1.5的

这是枚举,是JDK1.5新加的功能,你换JDK1.5或者以上的版本试一下吧.现在用JDK1.4的已经很少了  回复  更多评论
  
# re: JAVA截屏程序(第二版)[未登录]
2007-08-31 11:11 | jerry
private States current=States.DEFAULT;// 表示当前的编辑状态

这里执行的时候似乎有点问题,是什么原因?  回复  更多评论
  
# re: JAVA截屏程序(第二版)
2007-08-31 11:13 | 千里冰封
@jerry
一开始的时候,是默认的状态,这个枚举就是列举了一些鼠标的外观样式和当前鼠标的状态.以确实是拖动还是画图还是改变大小等等操作  回复  更多评论
  
# re: JAVA截屏程序(第二版)
2007-09-13 15:09 | jht
# re: JAVA截屏程序(第二版)
2008-04-25 16:22 | chw
最好把 运行脚本也一块打包,否则下了你的jar包后还得自己写个bat来运行。  回复  更多评论
  
# re: JAVA截屏程序(第二版)
2008-06-03 13:56 | wiloon
老大,,!你好像只考虑了任务栏在屏幕下方的情况.  回复  更多评论
  
# re: JAVA截屏程序(第二版)
2008-07-29 12:26 | stonebow
我想问一下,如果对于视频播放中画面的获得应该怎样操作呢?谢谢  回复  更多评论
  
# re: JAVA截屏程序(第二版)
2012-07-03 11:58 | andyyu
我想问一下,现在的这个程序只能截取屏幕内的图像。如何进行桌面意外的部分的截屏。  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: