程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 編程綜合問答 >> java代碼-我用Java 寫的一個簡單截圖小工具 但是出現一些在重截時出現bug 跪求大神

java代碼-我用Java 寫的一個簡單截圖小工具 但是出現一些在重截時出現bug 跪求大神

編輯:編程綜合問答
我用Java 寫的一個簡單截圖小工具 但是出現一些在重截時出現bug 跪求大神

/**在這裡貼上我注釋滿滿的代碼 求一語道破 求建議 求批評
沒有貼main 方法 隨便寫個main方法便可運行 */

`
package com.subimaga;

import java.awt.AWTException;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;

import com.sun.awt.AWTUtilities;

public class ScreenCapture extends JFrame implements MouseListener,
MouseMotionListener {

private BufferedImage bufferedImage = null;// 用來存放圖像

// 獲取屏幕的大小
private int width = Toolkit.getDefaultToolkit().getScreenSize().width;
private int height = Toolkit.getDefaultToolkit().getScreenSize().height;

private Point point = new Point(0, height); // 截圖的左上角

private Point point2 = new Point(0, 0);// 截圖右下角

private Point point3 = new Point(0, 0);// 用來處理point 與point2 的關系

// 是畫筆的透明度可控制
private AlphaComposite composite;

boolean isStarCut = false, isEndCut = false;// isStarCut 為開始選區
                                            // isEndCut為截圖結束僅標記結束選區

public ScreenCapture() {
    // 初始化窗口
    this.InitScr();

}

private void InitScr() // 初始化
{
    // 截取整個桌面作為窗口的背景

    try {
        bufferedImage = new Robot().createScreenCapture(new Rectangle(0, 0,
                width, height));
    } catch (AWTException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    // 去掉窗體結構
    this.setUndecorated(true);
    // 設置窗體大小
    this.setSize(width, height);

    // 設置畫筆的透明度
    composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f);

    this.addMouseListener(this);

    this.addMouseMotionListener(this);

    this.setVisible(true);

    this.setAlwaysOnTop(true);

    repaint();

}

public void paint(Graphics g) {

    // 配置截圖環境
    BufferedImage buff = new BufferedImage(width, height,
            BufferedImage.TYPE_4BYTE_ABGR);
    Graphics2D g2 = buff.createGraphics(); // 畫筆一
    Graphics2D g3 = buff.createGraphics(); // 畫筆二 用兩個畫筆主要是因為需要不同的透明度
    g2.drawImage(bufferedImage, 0, 0, null);
    g2.setColor(Color.gray);
    g2.setComposite(composite);
    g2.fillRect(0, 0, width, height);
    // 截圖的工作
    if (isStarCut == true || isEndCut == true) { // 當

        confirmArea(); // 處理坐標的方法

        /**
         * 我實現的原理是 在鋪了全屏截圖的窗口上鋪上一層灰色 透明為0.6 的實心矩形
         * 根據用戶在窗口拖動的坐標再另外截取一張相對應的圖片鋪在上面
         */
        g3.drawImage(bufferedImage.getSubimage(point.x, point.y, Math
                .abs(point2.x - point.x), Math.abs(point2.y - point.y)),
                point.x, point.y, null);
        // 畫出一個綠色的空心矩形
        g3.setColor(Color.green);
        g3.drawRect(point.x, point.y, point2.x - point.x, point2.y
                - point.y);

    }
    // 功能框的顯示
    if (isEndCut == true) { // 當選區結束 才會繪出此框
        action();
        // 背景框
        g2.fillRect(point3.x, point3.y + 5, 200, 30);
        g2.setColor(Color.red);
        // 完成

        g3.drawRect(point3.x, point3.y + 5, 60, 30);
        g3.setColor(Color.white);
        g3.drawString("完成", point3.x + 20, point3.y + 25);
        // 重截
        g2.drawRect(point3.x + 70, point3.y + 5, 60, 30);
        g2.drawString("重截", point3.x + 20 + 70, point3.y + 25);
        // 退出
        g2.drawRect(point3.x + 140, point3.y + 5, 60, 30);
        g2.drawString("退出", point3.x + 20 + 140, point3.y + 25);

    }
    // 雙緩沖
    g.drawImage(buff, 0, 0, this);

}

// 調節功能框位置的方法
public void action()

{
    if (point2.x <= width - 200 && point2.y < height - 35) {
        point3.x = point2.x;
        point3.y = point2.y;
    } else if (point.x >= 200 && point.y >= 35) {

        point3.x = point.x;
        point3.y = point.y - 50;
    }

    else if (point.x <= 200 && point2.x >= width - 200 && point.y >= 35) {

        point3.x = point2.x - 205;
        point3.y = point.y - 50;
    } else if (point.y >= 35 && point2.y <= height - 35
            && point2.x >= width - 200) {
        point3.x = point2.x;
        point3.y = point2.y;

    } else {
        point3.x = point2.x - 205;
        point3.y = point.y;

    }
}

public void confirmArea() {
    int temp;
    point.x = point3.x; // 每一次開始都是和原點坐標比較
    point.y = point3.y;
    if (point2.x < point.x && point2.y < point.y) {
        temp = point.x;
        point.x = point2.x;
        point2.x = temp;
        temp = point.y;
        point.y = point2.y;
        point2.y = temp;

    } else if (point2.x < point.x) {
        temp = point.x;
        point.x = point2.x;
        point2.x = temp;

    } else if (point2.y < point.y) {
        temp = point.y;
        point.y = point2.y;
        point2.y = temp;
    }
}

public void actoinCut(MouseEvent e) // 操作功能框的方法
{
    if (isEndCut) {
        // 完成
        if (e.getX() >= point3.x && e.getX() <= point3.x + 60
                && e.getY() >= point3.y + 5 && e.getY() <= point3.y + 35) {

            // //將截好的圖保存起來 原理是利用點下完成的“按鈕”時的坐標 即是最後一次決定的選區 對圖片進行截圖保存
            try {
                ImageIO.write(bufferedImage.getSubimage(point.x, point.y,
                        Math.abs(point2.x - point.x), Math.abs(point2.y
                                - point.y)), "jpg", new File("D:/D.jpg"));
            } catch (IOException e1) {
                // // TODO Auto-generated catch block
                e1.printStackTrace();
            }
            ;
            System.exit(0); // 保存完畢馬上退出 這裡的保存夠工作有點簡單因為只是用來測試此截圖工具的bug
                            // 具體的功能先不實現先
        }

        // 重截
        else if (e.getX() >= point3.x + 70
                && e.getX() <= point3.x + 70 + 60
                && e.getY() >= point3.y + 5 && e.getY() <= point3.y + 35) {

            isEndCut = false; // 重新截圖 一切進入初始狀態 這個 重截一直搞不好 求大神
            isStarCut = false;
            // 點擊重截後鼠標依然保持手型樣式 所以要恢復默認
            setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
            // 重繪
            repaint();
        }
        // 退出
        else if (e.getX() >= point3.x + 140
                && e.getX() <= point3.x + 140 + 60
                && e.getY() >= point3.y + 5 && e.getY() <= point3.y + 35) {

            System.exit(0);
        }
    }

}

public void mouseClicked(MouseEvent e) {
    // TODO Auto-generated method stub
    if (e.getButton() == MouseEvent.BUTTON3) // 雙擊 右鍵退出程序
    {
        if (e.getClickCount() == 2)
            System.exit(0);
    }
}

@Override
public void mouseEntered(MouseEvent e) {
    // TODO Auto-generated method stub

}

@Override
public void mouseExited(MouseEvent e) {
    // TODO Auto-generated method stub

}

@Override
public void mousePressed(MouseEvent e) {
    // TODO Auto-generated method stub
    // 只有當初始化狀態才生效
    if (isStarCut == false && isEndCut == false
            && e.getButton() == MouseEvent.BUTTON1) {
        point.x = e.getX();
        point.y = e.getY();
        point3.x = e.getX();
        point3.y = e.getY();
        isStarCut = true;

    }
    // 進入重截的條件
    else if (isEndCut) {
        this.actoinCut(e);
    }

}

@Override
public void mouseReleased(MouseEvent e) {
    // TODO Auto-generated method stub
    // 截圖開始生效
    if (isStarCut && isEndCut == false
            && e.getButton() == MouseEvent.BUTTON1) {
        isEndCut = true; // 鼠標一放開馬上標記截圖結束
        isStarCut = false; // 重新標記未開始選區狀態
        repaint();// 重繪

    }

}

@Override
public void mouseDragged(MouseEvent e) {
    // TODO Auto-generated method stub
    // 拖動是改變矩形的坐標點
    if (isStarCut || isEndCut) {

        point2.x = e.getX();
        point2.y = e.getY();
        repaint();

    }
}

public void mouseMoved(MouseEvent e) {
    // TODO Auto-generated method stub
    // 在功能框上顯示手型狀態
    if (isEndCut) {
        // 完成
        if (e.getX() >= point3.x && e.getX() <= point3.x + 60
                && e.getY() >= point3.y + 5 && e.getY() <= point3.y + 35) {
            setCursor(new Cursor(Cursor.HAND_CURSOR));
        }
        // 重截
        else if (e.getX() >= point3.x + 70
                && e.getX() <= point3.x + 70 + 60
                && e.getY() >= point3.y + 5 && e.getY() <= point3.y + 35) {

            setCursor(new Cursor(Cursor.HAND_CURSOR));
        }
        // 退出
        else if (e.getX() >= point3.x + 140
                && e.getX() <= point3.x + 140 + 60
                && e.getY() >= point3.y + 5 && e.getY() <= point3.y + 35) {

            setCursor(new Cursor(Cursor.HAND_CURSOR));
        } else {
            setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
        }

    }

}

}

最佳回答:


int needWh = Math.abs(point2.x - point.x);
int needhg = Math.abs(point2.y - point.y);
if ((isStarCut || isEndCut) && needWh != 0 && needhg != 0) { 

    confirmArea(); // 處理坐標的方法

    //將選擇的矩形圖片截出來
    BufferedImage needScr = bufferedImage.getSubimage(point.x, point.y, needWh, needhg);
    //截出來以後重新畫在jframe上,覆蓋原先背景圖片,以不同的透明度
    g3.drawImage(needScr,point.x, point.y, null);
    g3.setColor(Color.RED);
    g3.drawRect(point.x, point.y, point2.x - point.x, point2.y - point.y);
}

確定所選區域為正方形才繼續截圖,這樣就不會報錯。

其實最根本的原因在這個地方,就是當你點擊完成、重截、退出的時候同樣會觸發mouseReleased事件,只要加一個標志就可以了:

boolean isRecapt = false; //標記是否是重新截圖
boolean isComplt = false; //標記是否完成截圖
boolean isExit = false; //標記是否是退出

public void actoinCut(MouseEvent e) // 操作功能框的方法
{
if (isEndCut) {
// 完成
if (e.getX() >= point3.x && e.getX() <= point3.x + 60
&& e.getY() >= point3.y + 5 && e.getY() <= point3.y + 35) {
isComplt = true;
//將截好的圖保存起來 原理是利用點下完成的“按鈕”時的坐標 即是最後一次決定的選區 對圖片進行截圖保存
try {
ImageIO.write(bufferedImage.getSubimage(point.x, point.y,
Math.abs(point2.x - point.x), Math.abs(point2.y
- point.y)), "jpg", new File("JAVA截圖_" + System.currentTimeMillis() + ".jpg"));
} catch (IOException e1) {
e1.printStackTrace();
};
System.exit(0);
}

    // 重截
    else if (e.getX() >= point3.x + 70
            && e.getX() <= point3.x + 70 + 60
            && e.getY() >= point3.y + 5 && e.getY() <= point3.y + 35) {

        isEndCut = false; // 重新截圖 一切進入初始狀態 這個 重截一直搞不好 求大神
        isStarCut = false;
        isRecapt = true; //重新截圖置為true
        // 點擊重截後鼠標依然保持手型樣式 所以要恢復默認
        setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
        // 重繪
        repaint();
    }
    // 退出
    else if (e.getX() >= point3.x + 140
            && e.getX() <= point3.x + 140 + 60
            && e.getY() >= point3.y + 5 && e.getY() <= point3.y + 35) {
        isExit = true;
        System.exit(0);
    }
}

}

public void mouseReleased(MouseEvent e) {

//當點擊完成、重截、退出以後,現有程序會將釋放鼠標(Release)的動作視為截圖動作的開始,這顯然是錯誤的,因此要過濾掉。
if (isRecapt || isComplt || isExit){
    System.out.println("我return了 mouseReleased");
    isRecapt = false;
    repaint();// 重繪
    return ;
}
// 截圖開始生效
if (isStarCut && isEndCut == false
        && e.getButton() == MouseEvent.BUTTON1) {
    isEndCut = true; // 鼠標一放開馬上標記截圖結束
    isStarCut = false; // 重新標記未開始選區狀態
    repaint();// 重繪

}

}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved