Java 为什么GetScaleInstance()不起作用?
所以,我试图创造一个垄断游戏。我正在尝试将(电路板的)图像加载到Java 为什么GetScaleInstance()不起作用?,java,image,swing,paint,scaling,Java,Image,Swing,Paint,Scaling,所以,我试图创造一个垄断游戏。我正在尝试将(电路板的)图像加载到JPanel 我首先要将图像缩放为1024*1024图像 我已经得到了出现在JPanel上的图像(因此文件地址有效) 但是每当我使用getScaledInstance()方法时,图像都不会出现 import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JPanel; import java.awt.Color; import java.a
JPanel
我首先要将图像缩放为1024*1024
图像
我已经得到了出现在JPanel
上的图像(因此文件地址有效)
但是每当我使用getScaledInstance()
方法时,图像都不会出现
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.SystemColor;
//a class that represent the board (JFrame) and all of it components
public class Board extends JFrame {
private final int SCALE;
private JPanel panel;
public Board(int scale) {
getContentPane().setBackground(SystemColor.textHighlightText);
// SCALE = scale;
SCALE = 1;
// set up the JFrame
setResizable(false);
setTitle("Monopoly");
// set size to a scale of 1080p
setSize(1920 * SCALE, 1080 * SCALE);
getContentPane().setLayout(null);
panel = new JPanel() {
public void paint(Graphics g) {
Image board = new ImageIcon(
"C:\\Users\\Standard\\Pictures\\Work\\Monopoly 1.jpg")
.getImage();
board = board.getScaledInstance(1022, 1024, java.awt.Image.SCALE_SMOOTH);
g.drawImage(board, 0, 0, null);
}
};
panel.setBounds(592, 0, 1024, 1024);
getContentPane().add(panel);
}
public static void main(String[] args) {
Board board = new Board(1);
board.setVisible(true);
board.panel.repaint();
}
}
每当我移除board.getScaledInstance()
代码行时,图像都会出现(虽然没有缩放),但当我添加代码行时,图像根本不会出现
为什么会发生这种情况?您做错了几件事:
- 您正在覆盖绘制,而不是绘制组件。这是危险的,因为您正在覆盖一个做得太多、责任太大的映像。如果不小心执行此操作,可能会导致显著的图像副作用,并且由于绘制不是双缓冲,也会导致感知到的动画速度变慢
- 您没有在覆盖中调用超级绘制方法,这将导致绘制工件的累积和Swing组件绘制链的中断
- 您可能在一幅图像中多次阅读,并且使用了一种绘画方法,这种方法必须尽可能快,因为它是应用程序感知响应性的主要决定因素。只读取一次,然后将其保存到变量中
- 您正在使用空布局和设置边界。虽然空布局和
可能会像创建复杂GUI的最简单和最好的方式一样吸引新手,但您创建的GUI越多,在使用它们时遇到的困难就越严重。当GUI调整大小时,它们不会调整您的组件的大小,它们是一个需要增强或维护的皇家女巫,当它们放置在滚动窗格中时会完全失败,当在所有平台或屏幕分辨率与原始分辨率不同的情况下查看时,它们看起来非常糟糕setBounds()
- 您正在使用paint方法缩放图像,再次执行会降低GUI感知响应速度的操作。相反,只缩放图像一次,并将缩放后的图像保存为变量
- 重要的是,您对原始图像和缩放图像使用了相同的变量board,这将导致每次调用paint时图像的重新缩放
- 正如Mad指出的,您应该将
传递给这个
方法调用,以便在图像完全读入之前不绘制图像g.drawImage(…)
- 另外,当您没有将图像用作图像图标时,不要将其作为文件或图像图标读取。使用ImageIO将其作为缓冲区图像读入,并使用资源,而不是文件
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
@SuppressWarnings("serial")
public class MyBoard extends JPanel {
private static final String IMG_PATH = "http://ecx.images-amazon.com/"
+ "images/I/81oC5pYhh2L._SL1500_.jpg";
// scaling constants
private static final int IMG_WIDTH = 1024;
private static final int IMG_HEIGHT = IMG_WIDTH;
// original and scaled image variables
private BufferedImage initialImg;
private Image scaledImg;
public MyBoard() throws IOException {
URL url = new URL(IMG_PATH);
initialImg = ImageIO.read(url); // read in original image
// and scale it *once* and store in variable. Can even discard original
// if you wish
scaledImg = initialImg.getScaledInstance(IMG_WIDTH, IMG_HEIGHT,
Image.SCALE_SMOOTH);
}
// override paintComponent, not paint
@Override // and don't forget the @Override annotation
protected void paintComponent(Graphics g) {
super.paintComponent(g); // call the super's painting method
// just to be safe -- check that it's not null first
if (scaledImg != null) {
// use this as a parameter to avoid drawing an image before it's
// ready
g.drawImage(scaledImg, 0, 0, this);
}
}
// so our GUI is sized the same as the image
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet() || scaledImg == null) {
return super.getPreferredSize();
}
int w = scaledImg.getWidth(this);
int h = scaledImg.getHeight(this);
return new Dimension(w, h);
}
private static void createAndShowGui() {
MyBoard mainPanel = null;
try {
mainPanel = new MyBoard();
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
JFrame frame = new JFrame("My Board");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
您做了几件错误的事情:覆盖paint,而不是paintComponent,不调用超级绘制方法,在一个绘制方法中多次读取图像,使用空布局和设置边界。在绘制方法中缩放图像。。。哟。你在这个网站上搜索过类似的问题吗?这里可以找到做这类事情的更好方法。
g.drawImage(board,0,0,null)代码>应该是g.drawImage(board,0,0,this)代码>避免使用null
布局,像素完美的布局在现代ui设计中是一种错觉。影响零部件单个尺寸的因素太多,您无法控制。Swing的设计目的是与核心的布局管理器一起工作,丢弃它们将导致无止境的问题,您将花费越来越多的时间试图解决这些问题rectify@MadProgrammer成功了!。但是我在网上找到的大多数示例都使用null。此外,我还将尝试使用其他布局,尽管我确实需要坐标来将这些片段移动到指定的位置。感谢您的建议,我肯定会对代码进行更改。尽管我有一些问题:初始图像必须是BuffereImage吗?您会推荐给我什么布局管理器?@VineetPatel:不,初始图像变量可以使用接口声明为图像,但请理解ImageIO.read(…)
将返回BuffereImage。至于布局管理器,很大程度上取决于您想要实现的目标。我将使用各自的布局管理器嵌套JPanel,包括整体布局的BorderLayout,可能使用JPanel嵌套BorderLayout,然后沿边缘为非方形单元嵌套GridLayout。我要确保所有覆盖的JPanel都不是不透明的,这样图像才能显示出来。