尝试使用Java BufferedImage,Graphics将图像绘制到JFrame [英] Trying to paint image to JFrame with Java BufferedImage, Graphics

查看:202
本文介绍了尝试使用Java BufferedImage,Graphics将图像绘制到JFrame的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图捕获屏幕,然后在缩放图像时递归地将图像绘制为JFrame(以创建您在镜子中查看镜像时获得的效果)。



我的代码有问题 - 它没有绘制任何图形。我做错了什么?

  import java.awt.AWTException; 
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;

import javax.swing.JFrame;


公共类ScreenCapture扩展JFrame {

BufferedImage screenCapture;
图形screenCaptureGraphics;
private static int recurseCount = 0;
private static float $ scale = 0.9f;
private static float scale = 1.0f;
private static int height;
private static int width;

ScreenCapture(){
try {
screenCapture = new Robot()。createScreenCapture(
new Rectangle(Toolkit.getDefaultToolkit()。getScreenSize()));
height = screenCapture.getHeight();
width = screenCapture.getWidth();
setSize(new Dimension(width,height));
addWindowListener(new LocalWindowListener());
Graphics g = recursiveDraw(screenCapture,getGraphics());
paint(g);
} catch(HeadlessException e){
// TODO自动生成的catch块
e.printStackTrace();
catch(AWTException e){
// TODO自动生成的catch块
e.printStackTrace();



private graphics recursiveDraw(BufferedImage img,Graphics imgG){
updateScale(++ recurseCount);
float newWidth = scale * width;
float newHeight = scale * height;
int w =(int)newWidth;
int h =(int)newHeight;
System.out.println(W:+ w +; H:+ h); (w> = 10&& h> = 10)
缩放图像
System.out.print(Creating scaled Image ...);
Image scaled = img.getScaledInstance(w,h,Image.SCALE_SMOOTH);
BufferedImage resized = new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);
imgG = resized.createGraphics();
imgG.drawImage(scaled,0,0,null);
System.out.println(... Image drawn to graphics);
//返回新图形
返回recursiveDraw(resized,imgG);
} else {
//否则返回旧图形
System.out.println(Completed。);
return imgG;




private void updateScale(int count){
for(int i = 0; i< count; i ++){
比例* = $比例;
}
System.out.println(更新的比例:+ scale +;递归计数:+ recurseCount);
}

public static void main(String [] args){
EventQueue.invokeLater(new Runnable(){
@Override
public void run (){
new ScreenCapture()。setVisible(true);
}
});
}

private class LocalWindowListener extends WindowAdapter {
@Override
public void windowClosing(WindowEvent e){
System.exit(0);返回;





$ b

编辑:
这是我在@ andrew-thompson的回答后所尝试的:

  ScreenCapture (){
try {
screenCapture = new Robot()。createScreenCapture(
new Rectangle(Toolkit.getDefaultToolkit()。getScreenSize()));
height = screenCapture.getHeight();
width = screenCapture.getWidth();
setSize(new Dimension(width,height));
addWindowListener(new LocalWindowListener());
setLayout(new GridLayout());
add(new PaintPanel());
} catch(HeadlessException e){
// TODO自动生成的catch块
e.printStackTrace();
catch(AWTException e){
// TODO自动生成的catch块
e.printStackTrace();


$ b私有类PaintPanel扩展JPanel {
@Override
public void paintComponent(Graphics g){
g = recursiveDraw(screenCapture , G);
//如何处理g?
}
}

我仍然遇到同样的问题,知道如何将BufferedImage绘制到图形上。解析方案

将从递归图像创建代码中分离出Swing代码。实际上,考虑创建一个创建并返回BufferedImage并且没有Swing代码的静态方法。然后让GUI在需要时调用该方法,并拍摄图像并将其写入磁盘或将其显示在JLabel的ImageIcon中。



当我这样做时(今天实际上),我用这个签名创建了一个递归方法

  private static void recursiveDraw(BufferedImage img,Graphics imgG,double scale){

使用此方法body(伪代码)

 启动recursiveDraw方法
//最重要的是:所有递归必须有一个好的结局条件:
获得img的高度和宽度。如果< = a min,则返回
使用高度
width和比例因子
为较小的图像创建一个BufferedImage,smlImg,从小图像中获取图形对象smlG
使用smlG.drawImage(...)重载以缩小的
形式将大图形绘制到小图像
上递归地调用递归smdImg,smlG和缩放传递的recursiveDraw。
处理smlG
使用较大的
Graphics对象(传入此方法)和drawImage方法的另一个
重载,将smlImg(小图像)绘制到较大的图像上。
end recursiveDraw method

这个算法产生的图像如下:



例如:

  import java.awt。*; 
import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import javax.swing。*;

public class RecursiveDrawTest {
private static final Color BACKGRND_1 = Color.green;
private static final Color BACKGRND_2 = Color.MAGENTA;
private static final Color FOREGRND_1 = Color.blue;
private static final Color FOREGRND_2 = Color.RED;

private static void createAndShowGui(){
final JPanel mainPanel = new JPanel(new BorderLayout());
final JSlider slider = new JSlider(50,90,65);
slider.setMajorTickSpacing(10);
slider.setMinorTickSpacing(5);
slider.setPaintLabels(true);
slider.setPaintTicks(true);

JPanel southPanel = new JPanel();
southPanel.add(new JLabel(Percent Size Reduction:));
southPanel.add(slider);
southPanel.add(new JButton(new AbstractAction(Create Recursive Image){

@Override
public void actionPerformed(ActionEvent arg0){
try {
double scale = slider.getValue()/ 100.0;
BufferedImage img = createRecursiveImg(scale);
ImageIcon icon = new ImageIcon(img);
JLabel label = new JLabel(icon );

Window win = SwingUtilities.getWindowAncestor(mainPanel);
JDialog dialog = new JDialog(win,Image,ModalityType.MODELESS);
dialog.getContentPane() .add(label);
dialog.pack();
dialog.setLocationRelativeTo(null);
dialog.setVisible(true);
} catch(AWTException e){
e.printStackTrace();
}
}
}));
$ b $ mainPanel.add(new JScrollPane(new JLabel(new ImageIcon(createLabelImg()))),
BorderLayout.CENTER);
mainPanel.add(southPanel,BorderLayout.PAGE_END);

JFrame frame = new JFrame(RecursiveDrawTest);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane()。add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}

//创建一个背景图片在JLabel中显示,这样GUI
//不会很无聊。
private static BufferedImage createLabelImg(){
Dimension d = Toolkit.getDefaultToolkit()。getScreenSize();
int width =(5 * d.width)/ 6;
int height =(5 * d.height)/ 6;
BufferedImage img = new BufferedImage(width,height,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = img.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(new GradientPaint(0,0,BACKGRND_1,40,40,BACKGRND_2,true));
g2.fillRect(0,0,width,height);
g2.setPaint(new GradientPaint(0,height,FOREGRND_1,40,height - 40,FOREGRND_2,true));
g2.fillOval(0,0,2 * width,2 * height);
g2.dispose();
return img;
}

//获取初始图像的非递归图像将以递归方式绘制
public static BufferedImage createRecursiveImg(double scale)throws AWTException {
Robot robot = new Robot();
Dimension screenSz = Toolkit.getDefaultToolkit()。getScreenSize();
Rectangle screenRect = new Rectangle(screenSz);
BufferedImage img = robot.createScreenCapture(screenRect);
图形g = img.getGraphics();
recursiveDraw(img,g,scale); //调用递归方法
g.dispose();
return img;


//在图像中绘制图像的递归方法
private static void recursiveDraw(BufferedImage img,Graphics g,double scale){
int w = img .getWidth();
int h = img.getHeight();

int smlW =(int)(w * scale);
int smlH =(int)(h * scale);
//结束递归的标准
if(smlW< = 1 || smlH< = 1){
return;
}

BufferedImage smlImg = new BufferedImage(smlW,smlH,BufferedImage.TYPE_INT_ARGB);
图形smlG = smlImg.getGraphics();
//在小图片中绘制大图片,缩放至小图片
smlG.drawImage(img,0,0,smlW,smlH,null);

//递归调用
recursiveDraw(smlImg,smlG,scale);
smlG.dispose(); //完成后清空资源

//这些人将较小的img放在较大的
中间int smlX =(w - smlW)/ 2;
int smlY =(h - smlH)/ 2;
//在img
上画小img g.drawImage(smlImg,smlX,smlY,smlW,smlH,null);


public static void main(String [] args){
SwingUtilities.invokeLater(new Runnable(){
public void run(){
createAndShowGui();
}
});
}
}


I'm trying to capture the screen and then paint the image to a JFrame recursively while scaling the image (to create that effect you get when you look at a mirror in a mirror).

I'm having trouble with my code - it doesn't paint any graphics. What am I doing wrong?

import java.awt.AWTException;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;

import javax.swing.JFrame;


public class ScreenCapture extends JFrame {

    BufferedImage screenCapture;
    Graphics screenCaptureGraphics;
    private static int recurseCount = 0;
    private static float $scale = 0.9f;
    private static float scale = 1.0f;
    private static int height;
    private static int width;

    ScreenCapture() {
        try {
            screenCapture = new Robot().createScreenCapture(
                       new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()) );
            height = screenCapture.getHeight();
            width = screenCapture.getWidth();
            setSize(new Dimension(width, height));
            addWindowListener(new LocalWindowListener());
            Graphics g = recursiveDraw(screenCapture, getGraphics());
            paint(g);
        } catch (HeadlessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (AWTException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    private Graphics recursiveDraw(BufferedImage img, Graphics imgG) {
        updateScale(++recurseCount);
        float newWidth = scale*width;
        float newHeight = scale*height;
        int w = (int) newWidth;
        int h = (int) newHeight;
        System.out.println("W: " + w + "; H: " + h);
        if (w >= 10 && h >= 10) {
            //scale image
            System.out.print("Creating scaled Image...");
            Image scaled = img.getScaledInstance(w, h, Image.SCALE_SMOOTH);
            BufferedImage resized = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
            imgG = resized.createGraphics();
            imgG.drawImage(scaled, 0, 0, null);
            System.out.println("...Image drawn to graphics");
            //return new graphics
            return recursiveDraw(resized, imgG);
        } else {
            //otherwise return old graphics
            System.out.println("Completed.");
            return imgG;
        }
    }


    private void updateScale(int count) {
        for (int i=0; i<count; i++) {
            scale *= $scale;
        }
        System.out.println("Updated scale: " + scale + "; Recurse count: " + recurseCount);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new ScreenCapture().setVisible(true);
            }
        });
    }

    private class LocalWindowListener extends WindowAdapter {
        @Override
        public void windowClosing(WindowEvent e) {
            System.exit(0); return;
        }
    }

}

EDIT: This is what I tried after @andrew-thompson 's answer:

ScreenCapture() {
    try {
        screenCapture = new Robot().createScreenCapture(
                   new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()) );
        height = screenCapture.getHeight();
        width = screenCapture.getWidth();
        setSize(new Dimension(width, height));
        addWindowListener(new LocalWindowListener());
        setLayout(new GridLayout());
        add(new PaintPanel());
    } catch (HeadlessException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (AWTException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

private class PaintPanel extends JPanel {
    @Override
    public void paintComponent(Graphics g) {
        g=recursiveDraw(screenCapture, g);
        //what to do with g?
    }
}

I still have the same problem where I don't know how to make the BufferedImage paint to the graphics.

解决方案

would separate out your Swing code from your recursive image creation code. In fact consider creating a static method that creates and returns the BufferedImage and that has no Swing code in it. Then have your GUI call the method when it wishes, and take the image and either write it to disk or display it in a JLabel's ImageIcon.

When I did this (today in fact), I created a recursive method with this signature

private static void recursiveDraw(BufferedImage img, Graphics imgG, double scale) { 

and with this method body (in pseudo-code)

start recursiveDraw method 
   // most important: all recursions must have a good ending condition: 
   get img height and width. If either <= a min, return 
   create a BufferedImage, smlImg, for the smaller image using the height, 
        width and scale factor 
   Get the Graphics object, smlG, from the small image 
   Use smlG.drawImage(...) overload to draw the big image in shrunken 
        form onto the little image 
   recursively call recursiveDraw passing in smlImg, smlG, and scale. 
   dispose of smlG 
   draw smlImg (the small image) onto the bigger one using the bigger's 
        Graphics object (passed into this method) and a different 
        overload of the drawImage method. 
end recursiveDraw method

This algorithm resulted in images like:

For example:

import java.awt.*;
import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import javax.swing.*;

public class RecursiveDrawTest {
   private static final Color BACKGRND_1 = Color.green;
   private static final Color BACKGRND_2 = Color.MAGENTA;
   private static final Color FOREGRND_1 = Color.blue;
   private static final Color FOREGRND_2 = Color.RED;

   private static void createAndShowGui() {
      final JPanel mainPanel = new JPanel(new BorderLayout());
      final JSlider slider = new JSlider(50, 90, 65);
      slider.setMajorTickSpacing(10);
      slider.setMinorTickSpacing(5);
      slider.setPaintLabels(true);
      slider.setPaintTicks(true);

      JPanel southPanel = new JPanel();
      southPanel.add(new JLabel("Percent Size Reduction:"));
      southPanel.add(slider);
      southPanel.add(new JButton(new AbstractAction("Create Recursive Image") {

         @Override
         public void actionPerformed(ActionEvent arg0) {
            try {
               double scale = slider.getValue() / 100.0;
               BufferedImage img = createRecursiveImg(scale);
               ImageIcon icon = new ImageIcon(img);
               JLabel label = new JLabel(icon);

               Window win = SwingUtilities.getWindowAncestor(mainPanel);
               JDialog dialog = new JDialog(win, "Image", ModalityType.MODELESS);
               dialog.getContentPane().add(label);
               dialog.pack();
               dialog.setLocationRelativeTo(null);
               dialog.setVisible(true);
            } catch (AWTException e) {
               e.printStackTrace();
            }
         }
      }));

      mainPanel.add(new JScrollPane(new JLabel(new ImageIcon(createLabelImg()))), 
            BorderLayout.CENTER);
      mainPanel.add(southPanel, BorderLayout.PAGE_END);

      JFrame frame = new JFrame("RecursiveDrawTest");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   // create a background image to display in a JLabel so that the GUI
   // won't be boring.
   private static BufferedImage createLabelImg() {
      Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
      int width = (5 * d.width) / 6;
      int height = (5 * d.height) / 6;
      BufferedImage img = new BufferedImage(width, height, 
            BufferedImage.TYPE_INT_ARGB);
      Graphics2D g2 = img.createGraphics();
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
      g2.setPaint(new GradientPaint(0, 0, BACKGRND_1, 40, 40, BACKGRND_2, true));
      g2.fillRect(0, 0, width, height);
      g2.setPaint(new GradientPaint(0, height, FOREGRND_1, 40, height - 40, FOREGRND_2, true));
      g2.fillOval(0, 0, 2 * width, 2 * height);
      g2.dispose();
      return img;
   }

   // non-recursive image to get the initial image that will be drawn recursively
   public static BufferedImage createRecursiveImg(double scale) throws AWTException {
      Robot robot = new Robot();
      Dimension screenSz = Toolkit.getDefaultToolkit().getScreenSize();
      Rectangle screenRect = new Rectangle(screenSz);
      BufferedImage img = robot.createScreenCapture(screenRect);
      Graphics g = img.getGraphics();
      recursiveDraw(img, g, scale); // call recursive method
      g.dispose();
      return img;
   }

   // recursive method to draw image inside of image
   private static void recursiveDraw(BufferedImage img, Graphics g, double scale) {
      int w = img.getWidth();
      int h = img.getHeight();

      int smlW = (int)(w * scale);
      int smlH = (int)(h * scale);
      // criteria to end recursion
      if (smlW <= 1 || smlH <= 1) {
         return; 
      }

      BufferedImage smlImg = new BufferedImage(smlW, smlH, BufferedImage.TYPE_INT_ARGB);
      Graphics smlG = smlImg.getGraphics();
      // draw big image in little image, scaled to little image
      smlG.drawImage(img, 0, 0, smlW, smlH, null);

      // recursive call
      recursiveDraw(smlImg, smlG, scale);
      smlG.dispose(); // clear resources when done with them

      // these guys center the smaller img on the bigger
      int smlX = (w - smlW) / 2;
      int smlY = (h - smlH) / 2;
      // draw small img on big img
      g.drawImage(smlImg, smlX, smlY, smlW, smlH, null);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

这篇关于尝试使用Java BufferedImage,Graphics将图像绘制到JFrame的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆