有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java为什么GetScaleInstance()不起作用?

所以,我试图创造一个垄断游戏。我正在尝试将(电路板的)图像加载到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()行代码时,图像就会出现(虽然没有缩放),但当我添加代码行时,图像根本不会出现

为什么会发生这种情况


共 (1) 个答案

  1. # 1 楼答案

    你做错了几件事:

    • 您正在覆盖绘制,而不是绘制组件。这是危险的,因为您正在覆盖一个做得太多、责任太大的映像。如果不小心执行此操作,可能会导致显著的图像副作用,并且由于绘制不是双缓冲,也会导致感知到的动画速度变慢
    • 您没有在覆盖中调用超级绘制方法,这将导致绘制工件的累积和Swing组件绘制链的中断
    • 您可能在一幅图像中多次阅读,并且使用了一种绘画方法,这种方法必须尽可能快,因为它是应用程序感知响应性的主要决定因素。只读取一次,然后将其保存到变量中
    • 您正在使用空布局和设置边界。虽然空布局和setBounds()可能会像创建复杂GUI的最简单和最好的方式一样吸引新手,但您创建的Swing GUI越多,在使用它们时会遇到越严重的困难。当GUI调整大小时,它们不会调整您的组件的大小,它们是一个需要增强或维护的皇家女巫,当它们放置在滚动窗格中时会完全失败,当在所有平台或屏幕分辨率与原始分辨率不同的情况下查看时,它们看起来非常糟糕
    • 您正在使用paint方法缩放图像,再次执行会降低GUI感知响应速度的操作。相反,只缩放图像一次,并将缩放后的图像保存为变量
    • 重要的是,您对原始图像和缩放图像使用了相同的变量board,这将导致每次调用paint时图像的重新缩放
    • 正如Mad指出的,您应该将this传递给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();
                }
            });
        }
    }