Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/image/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么GetScaleInstance()不起作用?_Java_Image_Swing_Paint_Scaling - Fatal编程技术网

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组件绘制链的中断
  • 您可能在一幅图像中多次阅读,并且使用了一种绘画方法,这种方法必须尽可能快,因为它是应用程序感知响应性的主要决定因素。只读取一次,然后将其保存到变量中
  • 您正在使用空布局和设置边界。虽然空布局和
    setBounds()
    可能会像创建复杂GUI的最简单和最好的方式一样吸引新手,但您创建的GUI越多,在使用它们时遇到的困难就越严重。当GUI调整大小时,它们不会调整您的组件的大小,它们是一个需要增强或维护的皇家女巫,当它们放置在滚动窗格中时会完全失败,当在所有平台或屏幕分辨率与原始分辨率不同的情况下查看时,它们看起来非常糟糕
  • 您正在使用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都不是不透明的,这样图像才能显示出来。