开发者

How to make a dynamic image at run time?

开发者 https://www.devze.com 2023-04-12 02:26 出处:网络
I\'m working on a card game based on the NetBeans platform and I\'m struggling to get my head around dynamic images. Why dynamic? Well I want the cards to adjust at run time to changes to the page (i.

I'm working on a card game based on the NetBeans platform and I'm struggling to get my head around dynamic images. Why dynamic? Well I want the cards to adjust at run time to changes to the page (i.e. name, text, cost, etc).

My first hack at it was creating a component (JPanel) with labels pre-placed where I loaded the text/image based on the card values. That seems to work fine but then it became troublesome when I thought about some pages having a different look in later editions (meaning not everything would be on the same place).

So I'm trying to get an idea about ways to do this based on some kind of template.

Any idea?

There's a follow-up qu开发者_如何学Cestion at: JList of cards?


Finally I got some time to get back to this and was able to figure out a way using Java 2D tutorial.

The pictures are not near what I will use in my application but serves as proof of concept.

package javaapplication3;

import java.awt.*; import java.awt.font.FontRenderContext; import java.awt.font.LineBreakMeasurer; import java.awt.font.TextAttribute; import java.awt.font.TextLayout; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.text.AttributedCharacterIterator; import java.text.AttributedString; import java.util.ArrayList; import java.util.HashMap; import java.util.logging.Level; import java.util.logging.Logger; import javax.imageio.ImageIO;

/** * * @author Javier A. Ortiz Bultrón */ public class DefaultImageManager {

/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    try {
        // TODO code application logic here
        DefaultImageManager manager = new DefaultImageManager();
        URL url = DefaultImageManager.class.getResource("weather-rain.png");
        manager.getLayers().add(ImageIO.read(url));
        url = DefaultImageManager.class.getResource("weather-sun.png");
        manager.getLayers().add(ImageIO.read(url));
        manager.addText(new Font("Arial", Font.PLAIN, 10), "Many people believe that Vincent van Gogh painted his best works "
                + "during the two-year period he spent in Provence. Here is where he "
                + "painted The Starry Night--which some consider to be his greatest "
                + "work of all. However, as his artistic brilliance reached new "
                + "heights in Provence, his physical and mental health plummeted. ",
                200, 150, new Point(0, 0));
        manager.generate();
    } catch (MalformedURLException ex) {
        Logger.getLogger(DefaultImageManager.class.getName()).log(Level.SEVERE,

null, ex); } catch (IOException ex) { Logger.getLogger(DefaultImageManager.class.getName()).log(Level.SEVERE, null, ex); } } /** * Layers used to create the final image */ private ArrayList layers = new ArrayList(); private ArrayList textLayers = new ArrayList();

/**
 * @return the layers
 */
public ArrayList<BufferedImage> getLayers() {
    return layers;
}

private Dimension getMaxSize() {
    int width = 0, height = 0;
    for (BufferedImage img : getLayers()) {
        if (img.getWidth() > width) {
            width = img.getWidth();
        }
        if (img.getHeight() > height) {
            height = img.getHeight();
        }
    }
    return new Dimension(width, height);
}

public void addText(Font font, String text, int height, int width, Point location) {
    BufferedImage textImage = new BufferedImage(width, height,
            BufferedImage.TYPE_INT_ARGB);
    HashMap<TextAttribute, Object> map =
            new HashMap<TextAttribute, Object>();
    map.put(TextAttribute.FAMILY, font.getFamily());
    map.put(TextAttribute.SIZE, font.getSize());
    map.put(TextAttribute.FOREGROUND, Color.BLACK);
    AttributedString aString = new AttributedString(text, map);
    AttributedCharacterIterator paragraph = aString.getIterator();
    // index of the first character in the paragraph.
    int paragraphStart = paragraph.getBeginIndex();
    // index of the first character after the end of the paragraph.
    int paragraphEnd = paragraph.getEndIndex();
    Graphics2D graphics = textImage.createGraphics();
    FontRenderContext frc = graphics.getFontRenderContext();
    // The LineBreakMeasurer used to line-break the paragraph.
    LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(paragraph, frc);
    // Set break width to width of Component.
    float breakWidth = width;
    float drawPosY = 0;
    // Set position to the index of the first character in the paragraph.
    lineMeasurer.setPosition(paragraphStart);

    // Get lines until the entire paragraph has been displayed.
    while (lineMeasurer.getPosition() < paragraphEnd) {
        // Retrieve next layout. A cleverer program would also cache
        // these layouts until the component is re-sized.
        TextLayout layout = lineMeasurer.nextLayout(breakWidth);

        // Compute pen x position. If the paragraph is right-to-left we
        // will align the TextLayouts to the right edge of the panel.
        // Note: this won't occur for the English text in this sample.
        // Note: drawPosX is always where the LEFT of the text is placed.
        float drawPosX = layout.isLeftToRight()
                ? 0 : breakWidth - layout.getAdvance();

        // Move y-coordinate by the ascent of the layout.
        drawPosY += layout.getAscent();

        // Draw the TextLayout at (drawPosX, drawPosY).
        layout.draw(graphics, drawPosX, drawPosY);

        // Move y-coordinate in preparation for next layout.
        drawPosY += layout.getDescent() + layout.getLeading();
    }
    getTextLayers().add(textImage);
}

public void generate() throws IOException {
    Dimension size = getMaxSize();
    BufferedImage finalImage = new BufferedImage(size.width, size.height,
            BufferedImage.TYPE_INT_ARGB);
    for (BufferedImage img : getLayers()) {
        finalImage.createGraphics().drawImage(img,
                0, 0, size.width, size.height,
                0, 0, img.getWidth(null),
                img.getHeight(null),
                null);
    }
    for(BufferedImage text: getTextLayers()){
        finalImage.createGraphics().drawImage(text,
                0, 0, text.getWidth(), text.getHeight(),
                0, 0, text.getWidth(null),
                text.getHeight(null),
                null);
    }
    File outputfile = new File("saved.png");
    ImageIO.write(finalImage, "png", outputfile);
}

/**
 * @return the textLayers
 */
public ArrayList<BufferedImage> getTextLayers() {
    return textLayers;
}

/**
 * @param textLayers the textLayers to set
 */
public void setTextLayers(ArrayList<BufferedImage> textLayers) {
    this.textLayers = textLayers;
} }

It still needs some refining specially on the placement of the text but it works. I guess I can implement a xml format to store all this information so is easily configurable. In the example below suns are drawn on top of rain, and the text is on top of all that. For my application each layer will build together the page I want.

Here are the images I used:

How to make a dynamic image at run time?

How to make a dynamic image at run time?

And the final result:

How to make a dynamic image at run time?

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号