如何让我的Buffered Image类在我的GUI中显示?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何让我的Buffered Image类在我的GUI中显示?相关的知识,希望对你有一定的参考价值。

我有一个程序,使用定时器切换图像进行动画。当程序在其最后一个图像上时,我使用一个类来创建该图像的缓冲图像,其上有文本。当显示动画的最后一个图像时,我想将显示的图像更改为缓冲图像。我无法让它发挥作用。代码就像粗体部分不在那里一样。如果我删除它上面的行,它会显示带有文本的图像,而不显示任何其他内容。我应该对我的代码进行哪些编辑来修复此问题?

执行动画的类

**import java.awt.event.*;
  import java.awt.Graphics;
  import java.awt.Color;
  import java.awt.Font;
  import java.awt.image.*;

  import java.io.*;
  import java.io.File;

  import java.awt.*;
  import java.awt.image.BufferedImage;

  import java.net.URL;

  import javax.swing.*;
  import javax.swing.*;

  import javax.imageio.ImageIO;

  /**
   * Write a description of class Reveal here.
   *
   * @author (your name)
   * @version (a version number or a date)
   */
  public class Reveal extends JPanel
  {
      private JPanel panel = new JPanel();       //a panel to house the label
      private JLabel label = new JLabel();       //a label to house the image
      private String[] image = {"Jack in the Box 1.png","Jack in the Box 2.png","Jack in the Box 3.png","Jack in the Box 4.png","Jack in the Box 5.png","Jack in the Box 6.png","Jack in the Box 7.png"}; //an array to hold the frames of the animation
      private ImageIcon[] icon = new ImageIcon[7]; //an array of icons to be the images
      private JFrame f;

private TextOverlay TO;

private Timer timer;
private Timer timer2;
int x = 0;
int y = 4;
int counter = 0;
/**
 * Constructor for objects of class Reveal
 */
public Reveal(String name, int number) 
{ 
    TO = new TextOverlay("Jack in the Box 7.png", name, number);

    for (int h = 0; h < 7; h++){
      icon[h] = new ImageIcon(image[h]);
      icon[h].getImage();
    }

    JFrame f = new JFrame();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setVisible(true);

    //Sets the size of the window
    f.setSize(800,850);
    panel = new JPanel();
    label = new JLabel();
    label.setIcon( icon[x] );
    panel.add(label);


    setVisible(true);

    f.add(panel);
    display(name, number);
    **f.add(TO);**

}

public void display(String name, int number){
    timer = new Timer(150, new ActionListener(){
        public void actionPerformed(ActionEvent e) {
            if (counter > 27){
            timer.stop();
            timer2.start(); //starts the second half of the animation
          }else{

            if (x != 3){
                x++;
            }else{
                x = 0;
            }
            label.setIcon( icon[x] );
            counter++;
          } //ends if-else
        } //ends action method
    }); //ends timer

    timer2 = new Timer(250, new ActionListener(){
        public void actionPerformed(ActionEvent e){ 
          if (y > 6) {   
            timer2.stop();
          }else{
            label.setIcon( icon[y] );
            y++;
          } //ends if-else
        } //ends action method
    }); //ends timer2

    timer.start();
    }

}
**

将文本放在图像上的类

import java.io.*;
import java.awt.*;
import javax.swing.*;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;

/**
 * @see     https://stackoverflow.com/questions/2658663
 */
public class TextOverlay extends JPanel {

private BufferedImage image;
private String name;
private String fileX;
private int number;
public TextOverlay(String f, String s, int n) {
    name = s;
    number = n;
    fileX = f;

    try {
        image = ImageIO.read(new File(fileX));
    } catch (IOException e) {
        e.printStackTrace();
    }
    image = process(image, name, number);
}



@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.drawImage(image, 0, 0, null);
}

private BufferedImage process(BufferedImage old, String name, int number) {
    int w = old.getWidth();
    int h = old.getHeight();
    BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2d = img.createGraphics();
    g2d.drawImage(old, 0, 0, w, h, this);
    g2d.setPaint(Color.black);
    g2d.setFont(new Font("Franklin Gothic Demi Cond", Font.PLAIN, 30));
    String s1 = name;
    String s2 = Integer.toString(number);;
    FontMetrics fm = g2d.getFontMetrics();
    g2d.drawString(s1, 40, 90);
    g2d.drawString(s2, 40, 140);
    g2d.dispose();
    return img;
}

}

答案

所以,你似乎对Swing如何工作有误解,你可能会发现How to Use Swing TimersConcurrency in Swing的一些帮助。

基本上,当你start一个Timer时,它不会在此时阻止,直到计时器结束(即使它确实如此,你的工作方式也不会像你想要的那样)。而是创建一个新线程,并在指定的时间段后,在Event Dispatching Thread上发出一个请求以执行提供的Runnable

这意味着当你做某事......

f.add(panel);
display(name, number);
f.add(TO);

你实际上是在qazxsw poi之上添加了qazxsw poi组件(因为框架使用的是TO,而JLabel位置是默认位置。

相反,在第二个计时器完成后,您需要删除标签并添加BorderLayout组件...

CENTRE

Runnable Example...

TO

A "slightly" different approach...

动画实际上是一个非常复杂的主题,不容易实现。

这就是为什么当遇到这些问题时,我更愿意看看已经实施的库来帮助解决这些问题。我建议你看看:

  • timer2 = new Timer(250, new ActionListener() { public void actionPerformed(ActionEvent e) { if (y > 6) { timer2.stop(); Container parent = label.getParent(); parent.remove(label); parent.add(TO); parent.revalidate(); } else { label.setIcon(icon[y]); y++; } //ends if-else } //ends action method }); //ends timer2
  • import java.awt.event.*; import java.awt.Graphics; import java.awt.Color; import java.awt.Font; import java.awt.*; import java.awt.image.BufferedImage; import javax.swing.*; import javax.swing.border.LineBorder; public class Reveal extends JPanel { public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } new Reveal("Test", 5); } }); } private JPanel panel = new JPanel(); //a panel to house the label private JLabel label = new JLabel(); //a label to house the image private ImageIcon[] icon = new ImageIcon[7]; //an array of icons to be the images private JFrame f; private TextOverlay TO; private Timer timer; private Timer timer2; int x = 0; int y = 4; int counter = 0; /** * Constructor for objects of class Reveal */ public Reveal(String name, int number) { TO = new TextOverlay("Jack in the Box 7.png", name, number); for (int h = 0; h < 7; h++) { icon[h] = new ImageIcon(makeImage(h)); icon[h].getImage(); } JFrame f = new JFrame(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setVisible(true); //Sets the size of the window f.setSize(800, 850); panel = new JPanel(new GridBagLayout()); label = new JLabel(); label.setIcon(icon[x]); label.setBorder(new LineBorder(Color.RED)); panel.add(label); f.add(panel); display(name, number); // f.add(TO); setVisible(true); } public void display(String name, int number) { timer = new Timer(150, new ActionListener() { public void actionPerformed(ActionEvent e) { if (counter > 27) { timer.stop(); timer2.start(); //starts the second half of the animation } else { if (x != 3) { x++; } else { x = 0; } label.setIcon(icon[x]); counter++; } //ends if-else } //ends action method }); //ends timer timer2 = new Timer(250, new ActionListener() { public void actionPerformed(ActionEvent e) { if (y > 6) { timer2.stop(); Container parent = label.getParent(); parent.remove(label); parent.add(TO); parent.revalidate(); } else { label.setIcon(icon[y]); y++; } //ends if-else } //ends action method }); //ends timer2 timer.start(); } protected BufferedImage makeImage(int h) { BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB); Graphics2D g2d = img.createGraphics(); FontMetrics fm = g2d.getFontMetrics(); String text = Integer.toString(h); int x = (100 - fm.stringWidth(text)) / 2; int y = ((100 - fm.getHeight()) / 2) + fm.getAscent(); g2d.setColor(Color.BLUE); g2d.fillRect(0, 0, 100, 100); g2d.setColor(Color.BLACK); g2d.drawString(text, x, y); g2d.dispose(); return img; } public class TextOverlay extends JPanel { private BufferedImage image; private String name; private String fileX; private int number; public TextOverlay(String f, String s, int n) { name = s; number = n; fileX = f; image = makeImage(n); image = process(image, name, number); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); g.drawImage(image, 0, 0, this); } @Override public Dimension getPreferredSize() { return new Dimension(100, 100); } private BufferedImage process(BufferedImage old, String name, int number) { int w = old.getWidth(); int h = old.getHeight(); BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics2D g2d = img.createGraphics(); g2d.drawImage(old, 0, 0, w, h, this); g2d.setPaint(Color.black); g2d.setFont(new Font("Franklin Gothic Demi Cond", Font.PLAIN, 30)); String s1 = name; String s2 = Integer.toString(number);; FontMetrics fm = g2d.getFontMetrics(); g2d.drawString(s1, 40, 90); g2d.drawString(s2, 40, 140); g2d.dispose(); return img; } } }
  • The Timing Framework

作为一些起点。

虽然我更喜欢使用库,但有时它不可能,或者库不符合我的整体需求......而且我喜欢涉猎......这是一种爱好。

基于我从你的代码中可以理解的东西,你试图从快速动画开始,然后慢下来直到你到达最后一帧。在动画理论中,这通常被称为缓和,更具体地说,“缓慢/缓和”。

以下借鉴了我一直在玩的一堆片段(设计一个更可重复使用的库),它将在4秒内基本上(随机)显示图像,动画放慢速度,最后呈现“幸运” “号码

Trident

nb gif动画实际上非常慢,你需要运行它才能看到差异

universal-tween-engine

以上是关于如何让我的Buffered Image类在我的GUI中显示?的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 AFNetworkReachabilityManager 类在我的 OS X 项目中获取网络可达性

如何让我的 user.address 州和国家/地区字段正确包含在我的视图中?

如何让我的存储过程在我的 Visual Studio 项目中工作?

IOS swift如何让我的子视图出现在我的搜索栏下方

斯威夫特:如何让我的角色在我的游戏中只有落地后才能跳跃?

在我的 Laravel 应用程序中放置以及如何调用辅助函数?