我有一个给定的Canvas类,我想加载一个带有特殊celltype的Sprite,然后在我的Canvas上绘制它。我是GUI和Canvas建模的新手,下面的代码部分我总是得到一个"未处理的类型IO异常错误"在第3行我实现我的精灵加载器。我可以轻松地绘制矩形,否则我无法加载我的精灵并将其转换为图像。
private class Canvas extends JPanel {
private static final long serialVersionUID = 1L;
public SpritesheetLoader SL=SpritesheetLoader.defaultLoader();
private Spritesheet S=SL.getSpritesheet("graphics/sprites/equipment/chest/tnecksweater-female");
Image I=S.getCel(0);
/**
* Creates a new canvas object
*/
public Canvas() {
super(true);
super.setBackground(new Color(0, 128, 0)); // middle green
}
/**
* Redraws the canvas
*
* @param g The graphics context to redraw with
*/
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
synchronized (UIPanel.this) {
if (canvasDrawer != null) {
canvasDrawer.draw(g);
}
}
g.drawImage(I, 10, 10, this);
}
}
编辑:
public class SpritesheetLoader {
private String filename;
private Map<String, ZipEntry> spritesheets = null;
// XML parser
private DocumentBuilder xmlParser = null;
private ZipFile zipFile;
public SpritesheetLoader(String filename) {
this.filename = filename;
try {
this.xmlParser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
} catch (ParserConfigurationException exn) {
throw new RuntimeException(exn);
}
}
@SuppressWarnings("unused")
private static void printDocument(Document doc, OutputStream out) {
// code by http://stackoverflow.com/users/203907/bozho
try {
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
transformer.transform(new DOMSource(doc),
new StreamResult(new OutputStreamWriter(out, "UTF-8")));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void init() throws IOException {
if (spritesheets != null) {
return;
}
spritesheets = new HashMap<>();
this.zipFile = new ZipFile(this.filename);
Enumeration<? extends ZipEntry> zipIterator = zipFile.entries();
while (zipIterator.hasMoreElements()) {
ZipEntry z = zipIterator.nextElement();
if (z.getName().endsWith(".xml")) {
String name = z.getName().substring(0, z.getName().length() - 4);
spritesheets.put(name, z);
}
}
}
public Spritesheet getSpritesheet(String name) {
ZipEntry entry = spritesheets.get(name);
if (entry == null) {
return null;
}
SpritesheetParser parser = new SpritesheetParser();
parser.parseToplevel(getData(entry));
return parser.getSpritesheet();
}
private InputStream getData(ZipEntry entry) {
try {
InputStream s = zipFile.getInputStream(entry);
return s;
} catch (IOException exn) {
throw new RuntimeException(exn);
}
}
private InputStream getDataForFilename(String data) {
try {
ZipEntry entry = zipFile.getEntry(data);
if (entry == null) {
throw new RuntimeException("Missing file entry: " + data);
}
InputStream s = zipFile.getInputStream(entry);
return s;
} catch (IOException exn) {
throw new RuntimeException(exn);
}
}
public Set<? extends String> getSpritesheetNames() {
return spritesheets.keySet();
}
private static SpritesheetLoader DEFAULT = null;
public static SpritesheetLoader defaultLoader() throws IOException {
if (DEFAULT != null) {
return DEFAULT;
}
DEFAULT = new SpritesheetLoader(System.getProperty("user.home") + File.separator + "prgpr" + File.separator + "graphics.zip");
DEFAULT.init();
return DEFAULT;
}
public static void main(String[] args) throws IOException {
SpritesheetLoader loader = defaultLoader();
System.out.println(loader.getSpritesheetNames());
System.out.println(loader.getSpritesheet("graphics/sprites/equipment/chest/tnecksweater-female"));
}
private class SpritesheetParser {
private Spritesheet spritesheet;
public Spritesheet getSpritesheet() {
return spritesheet;
}
public Element parseDoc(InputStream indoc) {
Document doc;
try {
doc = xmlParser.parse(indoc);
} catch (SAXException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
return doc.getDocumentElement();
}
public Element includeIfNeeded(Element elt) {
if (elt.getTagName().equals("include")) {
return parseDoc(getDataForFilename(elt.getAttribute("file")));
}
return null;
}
private void parseImageSet(Element elt) {
if (spritesheet != null) { // already have a spritesheet; obey override semantics
return;
}
String filename = elt.getAttribute("src");
EnumSet<DyeChannel> dyeChannels = EnumSet.noneOf(DyeChannel.class);
int splitIndex;
if ((splitIndex = filename.indexOf('|')) > 0) {
int index = splitIndex + 1;
for (; index < filename.length(); index++) {
switch (filename.charAt(index)) {
case 'R': dyeChannels.add(DyeChannel.RED); break;
case 'G': dyeChannels.add(DyeChannel.GREEN); break;
case 'B': dyeChannels.add(DyeChannel.BLUE); break;
case 'C': dyeChannels.add(DyeChannel.CYAN); break;
case 'M': dyeChannels.add(DyeChannel.MAGENTA); break;
case 'Y': dyeChannels.add(DyeChannel.YELLOW); break;
case 'W': dyeChannels.add(DyeChannel.WHITE); break;
}
}
filename = filename.substring(0, splitIndex);
}
BufferedImage bufferedImage;
try {
bufferedImage = ImageIO.read(getDataForFilename(filename));
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
spritesheet = new Spritesheet(bufferedImage, dyeChannels);
if (elt.hasAttribute("width") && elt.hasAttribute("height")) {
spritesheet.setCelDimensions(Integer.parseInt(elt.getAttribute("width")), Integer.parseInt(elt.getAttribute("height")));
}
}
int intAttribute(Element elt, String name) {
if (elt.hasAttribute(name)) {
return Integer.parseInt(elt.getAttribute(name));
}
return 0;
}
private void parseAnimation(Element elt, String name) {
Direction direction = Direction.DEFAULT;
switch (elt.getAttribute("direction")) {
case "up": direction = Direction.UP; break;
case "down": direction = Direction.DOWN; break;
case "left": direction = Direction.LEFT; break;
case "right": direction = Direction.RIGHT; break;
}
Animation animation = new Animation();
boolean looping = true;
NodeList nl = elt.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node n = nl.item(i);
if (n instanceof Element) {
Element animationStep = (Element)n;
int xoffset = intAttribute(animationStep, "offsetX");
int yoffset = intAttribute(animationStep, "offsetY");
switch (animationStep.getTagName()) {
case "frame":
int index = intAttribute(animationStep, "index");
animation.addCelSequence(new CelSequence(
index, index, intAttribute(animationStep, "delay")).setOffsets(xoffset, yoffset));
break;
case "sequence":
animation.addCelSequence(new CelSequence(
intAttribute(animationStep, "start"),
intAttribute(animationStep, "end"),
intAttribute(animationStep, "delay")).setOffsets(xoffset, yoffset));
case "end":
looping = false;
break;
}
}
}
animation.setIsLooping(looping);
spritesheet.addAnimation(name, direction, animation);
}
private void parseAction(Element elt) {
String actionName = elt.getAttribute("name");
NodeList nl = elt.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node n = nl.item(i);
if (n instanceof Element) {
Element actionPart = (Element)n;
switch (actionPart.getTagName()) {
case "animation": parseAnimation(actionPart, actionName); break;
}
}
}
}
public void parseToplevel(InputStream docStream) {
parseToplevelElement(parseDoc(docStream));
}
public void parseToplevelElement(Element body) {
if (body == null) {
return;
}
if (!body.getTagName().equals("sprite")) {
System.err.println("Not a <sprite>");
return;
}
NodeList nl = body.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node n = nl.item(i);
if (n instanceof Element) {
Element elt = (Element) n;
switch (elt.getTagName()) {
case "imageset":
parseImageSet(elt);
break;
case "action":
parseAction(elt);
break;
case "include":
parseToplevelElement(includeIfNeeded(elt));
}
}
}
}
}
}