只绘制缓冲图像的一部分
Only drawing part of bufferedimage
我正在设计纸牌游戏,我想在面板上绘制(绘制)一张纸牌。但是,当我绘画时,只显示图像的一小部分。您可以在这张截图中看到它:
我为 BufferedImage 写了一个包装器 class (CardImage):
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
public class CardImage {
BufferedImage img = null;
public CardImage() {
}
public BufferedImage setImage(Card c) {
try {
img = ImageIO.read(new File("/media/billy/HOME/workspace/Shithead/src/cards/" + toName(c)));
} catch(Exception e) {
System.out.println(e);
}
/*
int scale_factor = 8;
System.out.println(img.getHeight());
Image dimg = img.getScaledInstance((int)img.getWidth()/scale_factor, (int)img.getHeight()/scale_factor, Image.SCALE_SMOOTH);
Graphics g = img.createGraphics();
g.drawImage(dimg, 0, 0, null);
g.dispose();
*/
return img;
}
public String toName(Card c) {
String tmp = c.toString().replaceAll(" ", "_");
tmp = tmp.toLowerCase();
tmp = tmp + ".png";
return tmp;
}
}
我有一个扩展 JPanel 的 HandPanel,我想在其中绘制 CardImage BufferedImage:
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
public class HandPanel extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
CardImage cardImage = new CardImage();
Card card = new Card(2,2);
BufferedImage img = cardImage.setImage(card);
System.out.println(img.getHeight(null) + " " + img.getWidth(null));
g.drawImage(img, 0, 0, null);
}
}
我还有一个 class 来包含 HandPanel:
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ShitGUI {
public static void main(String[] args) {
ShitGUI gui = new ShitGUI();
}
JFrame frame = new JFrame();
JPanel mainPanel = new JPanel();
public ShitGUI() {
mainPanel.setPreferredSize(new Dimension(500,500));
HandPanel pan = new HandPanel();
mainPanel.add(pan);
frame.add(mainPanel);
frame.pack();
frame.setVisible(true);
}
}
卡片的图像比较大(创建Card(2,2)只是红心2,我知道我正确获取了路径)。
感谢任何帮助。谢谢!
N.B。当我取消注释包含 dimg 的部分时,我得到了一张按比例缩小的红色卡片(而不是黑色和白色,不是我以其他方式得到的缩放图像)。我理解缩放,但我不明白为什么我的方法给我的是黑白图像。
可能的直接问题是 HandPanel
不提供任何尺寸提示以允许布局管理器确定组件的最佳尺寸,回退到它的默认首选尺寸 0x0
我回去稍微修改了你的代码,让它更容易重用。
img = ImageIO.read(new File("/media/billy/HOME/workspace/Shithead/src/cards/" + toName(c)));
是个坏主意。
您永远不应引用任何包含 src
的路径,一旦您的应用程序构建完成,src
将不存在。您不应该通过 File
引用嵌入式资源,它们不是(或者至少在构建应用程序时不会),相反,您需要使用 Class#getResource
.
public class CardImage {
BufferedImage img = null;
public CardImage(Card card) {
setImage(card);
}
public BufferedImage getImage() {
return img;
}
public BufferedImage setImage(Card c) {
try {
//img = ImageIO.read(new File("/media/billy/HOME/workspace/Shithead/src/cards/" + toName(c)));
img = ImageIO.read(getClass().getResource("/cards/" + toName(c)));
} catch (Exception e) {
System.out.println(e);
}
/*
int scale_factor = 8;
System.out.println(img.getHeight());
Image dimg = img.getScaledInstance((int)img.getWidth()/scale_factor, (int)img.getHeight()/scale_factor, Image.SCALE_SMOOTH);
Graphics g = img.createGraphics();
g.drawImage(dimg, 0, 0, null);
g.dispose();
*/
return img;
}
public String toName(Card c) {
String tmp = c.toString().replaceAll(" ", "_");
tmp = tmp.toLowerCase();
tmp = tmp + ".png";
return tmp;
}
}
我已经修改了 CardImage
class 所以它需要提前设置,这可以让你缓存图像并更有效地 re-use 它。我还考虑使用某种工厂,当传递 Card
时可以确定它是否需要生成 CardImage
的新实例或 re-use 以前缓存的版本,这将使您的代码执行速度更快。
同样,我修改了 HandPanel
,它现在要求您将 Card
传递给它,它使用它来确定它将使用哪些信息来生成尺寸提示
public class HandPanel extends JPanel {
CardImage cardImage;
public HandPanel(Card card) {
cardImage = new CardImage(card);
}
@Override
public Dimension getPreferredSize() {
BufferedImage img = cardImage.getImage();
return img == null ? super.getPreferredSize() : new Dimension(img.getWidth(), img.getHeight());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
BufferedImage img = cardImage.getImage();
g.drawImage(img, 0, 0, this);
}
}
我还鼓励您查看 Perials of getScaledInstance and Java: maintaining aspect ratio of JPanel background image 以获得一些替代方案
我正在设计纸牌游戏,我想在面板上绘制(绘制)一张纸牌。但是,当我绘画时,只显示图像的一小部分。您可以在这张截图中看到它:
我为 BufferedImage 写了一个包装器 class (CardImage):
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
public class CardImage {
BufferedImage img = null;
public CardImage() {
}
public BufferedImage setImage(Card c) {
try {
img = ImageIO.read(new File("/media/billy/HOME/workspace/Shithead/src/cards/" + toName(c)));
} catch(Exception e) {
System.out.println(e);
}
/*
int scale_factor = 8;
System.out.println(img.getHeight());
Image dimg = img.getScaledInstance((int)img.getWidth()/scale_factor, (int)img.getHeight()/scale_factor, Image.SCALE_SMOOTH);
Graphics g = img.createGraphics();
g.drawImage(dimg, 0, 0, null);
g.dispose();
*/
return img;
}
public String toName(Card c) {
String tmp = c.toString().replaceAll(" ", "_");
tmp = tmp.toLowerCase();
tmp = tmp + ".png";
return tmp;
}
}
我有一个扩展 JPanel 的 HandPanel,我想在其中绘制 CardImage BufferedImage:
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
public class HandPanel extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
CardImage cardImage = new CardImage();
Card card = new Card(2,2);
BufferedImage img = cardImage.setImage(card);
System.out.println(img.getHeight(null) + " " + img.getWidth(null));
g.drawImage(img, 0, 0, null);
}
}
我还有一个 class 来包含 HandPanel:
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ShitGUI {
public static void main(String[] args) {
ShitGUI gui = new ShitGUI();
}
JFrame frame = new JFrame();
JPanel mainPanel = new JPanel();
public ShitGUI() {
mainPanel.setPreferredSize(new Dimension(500,500));
HandPanel pan = new HandPanel();
mainPanel.add(pan);
frame.add(mainPanel);
frame.pack();
frame.setVisible(true);
}
}
卡片的图像比较大(创建Card(2,2)只是红心2,我知道我正确获取了路径)。
感谢任何帮助。谢谢!
N.B。当我取消注释包含 dimg 的部分时,我得到了一张按比例缩小的红色卡片(而不是黑色和白色,不是我以其他方式得到的缩放图像)。我理解缩放,但我不明白为什么我的方法给我的是黑白图像。
可能的直接问题是 HandPanel
不提供任何尺寸提示以允许布局管理器确定组件的最佳尺寸,回退到它的默认首选尺寸 0x0
我回去稍微修改了你的代码,让它更容易重用。
img = ImageIO.read(new File("/media/billy/HOME/workspace/Shithead/src/cards/" + toName(c)));
是个坏主意。
您永远不应引用任何包含 src
的路径,一旦您的应用程序构建完成,src
将不存在。您不应该通过 File
引用嵌入式资源,它们不是(或者至少在构建应用程序时不会),相反,您需要使用 Class#getResource
.
public class CardImage {
BufferedImage img = null;
public CardImage(Card card) {
setImage(card);
}
public BufferedImage getImage() {
return img;
}
public BufferedImage setImage(Card c) {
try {
//img = ImageIO.read(new File("/media/billy/HOME/workspace/Shithead/src/cards/" + toName(c)));
img = ImageIO.read(getClass().getResource("/cards/" + toName(c)));
} catch (Exception e) {
System.out.println(e);
}
/*
int scale_factor = 8;
System.out.println(img.getHeight());
Image dimg = img.getScaledInstance((int)img.getWidth()/scale_factor, (int)img.getHeight()/scale_factor, Image.SCALE_SMOOTH);
Graphics g = img.createGraphics();
g.drawImage(dimg, 0, 0, null);
g.dispose();
*/
return img;
}
public String toName(Card c) {
String tmp = c.toString().replaceAll(" ", "_");
tmp = tmp.toLowerCase();
tmp = tmp + ".png";
return tmp;
}
}
我已经修改了 CardImage
class 所以它需要提前设置,这可以让你缓存图像并更有效地 re-use 它。我还考虑使用某种工厂,当传递 Card
时可以确定它是否需要生成 CardImage
的新实例或 re-use 以前缓存的版本,这将使您的代码执行速度更快。
同样,我修改了 HandPanel
,它现在要求您将 Card
传递给它,它使用它来确定它将使用哪些信息来生成尺寸提示
public class HandPanel extends JPanel {
CardImage cardImage;
public HandPanel(Card card) {
cardImage = new CardImage(card);
}
@Override
public Dimension getPreferredSize() {
BufferedImage img = cardImage.getImage();
return img == null ? super.getPreferredSize() : new Dimension(img.getWidth(), img.getHeight());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
BufferedImage img = cardImage.getImage();
g.drawImage(img, 0, 0, this);
}
}
我还鼓励您查看 Perials of getScaledInstance and Java: maintaining aspect ratio of JPanel background image 以获得一些替代方案