我正在开发基于NetBeans平台的纸牌游戏,我正在努力让我的头脑围绕动态图像。为什么动态?好吧,我希望卡片在运行时调整到页面的更改(即名称,文本,成本等)。
我的第一个黑客是创建一个组件(JPanel),其中预先放置了标签,我根据卡片值加载了文本/图像。这似乎工作正常,但当我想到一些页面在后期版本中具有不同的外观(意味着并非所有内容都在同一个地方)时,它变得很麻烦。
所以我试图根据某种模板来了解如何做到这一点。
有什么想法吗?
有一个跟进问题:JList of cards?
答案 0 :(得分:0)
最后,我有时间回到这一点,并且能够找到使用Java 2D tutorial的方法。
图片并不接近我在申请中使用的图片,但作为概念证明。
package javaapplication3;
import java.awt。*; import java.awt.font.FontRenderContext;进口 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;进口 java.net.MalformedURLException; import java.net.URL;进口 java.text.AttributedCharacterIterator;进口 java.text.AttributedString; import java.util.ArrayList;进口 的java.util.HashMap; import java.util.logging.Level;进口 java.util.logging.Logger中; import javax.imageio.ImageIO;
/ ** * * @author Javier A.OrtizBultró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())。日志(Level.SEVERE, null,ex); } } / ** *用于创建最终图像的图层 * / 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; } }
它仍然需要对文本的放置进行一些精炼但是有效。我想我可以实现一个xml格式来存储所有这些信息,因此很容易配置。在下面的例子中,太阳在雨的顶部绘制,文本在所有这些之上。对于我的应用程序,每个层将构建我想要的页面。
以下是我使用的图片:
最终结果: