【问题标题】:Java - How to resize Image to fit window size?Java - 如何调整图像大小以适应窗口大小?
【发布时间】:2013-11-06 18:29:03
【问题描述】:

我正在制作一个类似于 MS Paint 的简单程序。我创建了一个空白的自定义图像作为我的“画布”。但是,每当我放大窗口时,图像都会保持相同的大小。当我调整窗口大小时,如何才能使图像适合?

我的代码是:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.image.BufferedImage;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class ScribblePad extends JFrame {

    // Setting GUI variables...

    public static int WIDTH = 800;
    public static int HEIGHT = 800;

    public static int X = 10;
    public static int Y = 10;

    public static String TITLE = "ScribblePad";

    // Create GUI components...

    PaintPanel paintPanel = new PaintPanel();

    JPanel buttonPanel = new JPanel();

    Container mainContainer = getContentPane();

    JButton clearButton = new JButton("Clear");

    JButton buttonBlack = new JButton();
    JButton buttonRed = new JButton();
    JButton buttonBlue = new JButton();
    JButton buttonYellow = new JButton();
    JButton buttonGreen = new JButton();

    Cursor crosshairCursor = Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR);

    // Run the entire program...

    public static void main(String []args) {

        new ScribblePad();

    }

    // Create ScribblePad constructor...

    public ScribblePad() {

        // Setting JFrame properties...

        super(TITLE);

        setVisible(true);

        setSize(WIDTH, HEIGHT);
        setLocation(X, Y);      

        setDefaultCloseOperation(EXIT_ON_CLOSE);

        // Setting properties of other components...

        paintPanel.setCursor(crosshairCursor);

        buttonPanel.setBackground(Color.WHITE);

        buttonPanel.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.BLACK));

        // Adding the components...

        mainContainer.add(paintPanel, BorderLayout.CENTER);

        mainContainer.add(buttonPanel, BorderLayout.NORTH);

        // Adding ActionListeners and setting properties of the buttons..

        buttonBlack.setBackground(Color.BLACK);
        buttonBlack.setForeground(Color.BLACK);
        buttonBlack.setPreferredSize(new Dimension(32, 32));

        buttonRed.setBackground(Color.RED);
        buttonRed.setForeground(Color.RED);
        buttonRed.setPreferredSize(new Dimension(32, 32));

        buttonGreen.setBackground(Color.GREEN);
        buttonGreen.setForeground(Color.GREEN);
        buttonGreen.setPreferredSize(new Dimension(32, 32));

        buttonBlue.setBackground(Color.BLUE);
        buttonBlue.setForeground(Color.BLUE);
        buttonBlue.setPreferredSize(new Dimension(32, 32));

        buttonYellow.setBackground(Color.YELLOW);
        buttonYellow.setForeground(Color.YELLOW);
        buttonYellow.setPreferredSize(new Dimension(32, 32));

        clearButton.addActionListener(new ActionListener(){

            public void actionPerformed(ActionEvent e){

                paintPanel.clearCanvas();

            }

        });

        buttonBlack.addActionListener(new ActionListener(){

            public void actionPerformed(ActionEvent e){

                paintPanel.setBlack();

            }

        });

        buttonGreen.addActionListener(new ActionListener(){

            public void actionPerformed(ActionEvent e){

                paintPanel.setGreen();


            }

        });

        buttonRed.addActionListener(new ActionListener(){

            public void actionPerformed(ActionEvent e){

                paintPanel.setRed();

            }

        });

        buttonYellow.addActionListener(new ActionListener(){

            public void actionPerformed(ActionEvent e){

                paintPanel.setYellow();

            }

        });

        buttonBlue.addActionListener(new ActionListener(){

            public void actionPerformed(ActionEvent e){

                paintPanel.setBlue();

            }

        });

        // Adding buttons to the buttonPanel...

        buttonPanel.add(buttonBlack);
        buttonPanel.add(buttonRed);
        buttonPanel.add(buttonGreen);
        buttonPanel.add(buttonBlue);
        buttonPanel.add(buttonYellow);

        buttonPanel.add(clearButton);

    }

    public class PaintPanel extends JComponent {

        Image blankCanvas;

        Graphics2D g2D;

        int mouseX, mouseY, oldX, oldY;

        String currentColour = "BLACK";

        public PaintPanel() {

            setDoubleBuffered(true);

            addMouseListener(new MouseAdapter() {

                public void mousePressed(MouseEvent e) {

                    oldX = e.getX();
                    oldY = e.getY();

                    g2D.drawOval(oldX, oldY, 1, 1);

                    System.out.println("[Debug] Point drawn at (" + oldX + ", " + oldY + ").");

                    repaint();

                }

            });

            addMouseMotionListener(new MouseMotionAdapter(){

                public void mouseDragged(MouseEvent e){

                    mouseX = e.getX();
                    mouseY = e.getY();

                    if(g2D != null)

                    g2D.drawLine(oldX, oldY, mouseX, mouseY);

                    repaint();

                    System.out.println("[Debug] Line drawn from (" + oldX + ", " + oldY + ") to (" + mouseX + ", " + mouseY + ").");

                    oldX = mouseX;
                    oldY = mouseY;

                }

            });

        }

        public void paintComponent(Graphics g) {

            if (blankCanvas == null) {

                blankCanvas = this.createImage(getWidth(), getHeight());

                g2D = (Graphics2D)blankCanvas.getGraphics();

                g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

                clearCanvas();

            }

            g.drawImage(blankCanvas, 0, 0, null);   

        }

        public void clearCanvas() {

            g2D.setPaint(Color.WHITE);
            g2D.fillRect(0, 0, getSize().width, getSize().height);

            switch(currentColour) {

            case "BLACK": g2D.setColor(Color.BLACK); break;

            case "RED": g2D.setColor(Color.RED); break;

            case "GREEN": g2D.setColor(Color.GREEN); break;

            case "BLUE": g2D.setColor(Color.BLUE); break;

            case "YELLOW": g2D.setColor(Color.YELLOW); break;

            }

            System.out.println("[Debug] Canvas cleared.");

            repaint();

        }

        public void setBlack() {

            g2D.setColor(Color.BLACK);

            System.out.println("[Debug] Colour changed to black.");

            currentColour = "BLACK";

        }

        public void setRed() {

            g2D.setColor(Color.RED);

            System.out.println("[Debug] Colour changed to red.");

            currentColour = "RED";

        }

        public void setBlue() {

            g2D.setColor(Color.BLUE);

            System.out.println("[Debug] Colour changed to blue.");

            currentColour = "BLUE";

        }

        public void setYellow() {

            g2D.setColor(Color.YELLOW);

            System.out.println("[Debug] Colour changed to yellow.");

            currentColour = "YELLOW";

        }

        public void setGreen() {

            g2D.setColor(Color.GREEN);

            System.out.println("[Debug] Colour changed to green.");

            currentColour = "GREEN";

        }

    }

}

【问题讨论】:

  • 请展示您到目前为止所做的尝试,并且只发布 SSCCE 而不是您的整个计划。
  • 你可以看看this example

标签: java image swing


【解决方案1】:

我不知道您的问题是关于缩放现有图像,还是随着帧大小的变化而使绘画区域变大/变小。

缩放是个问题,因为一旦你调整了图像的大小,你总是需要重新缩放鼠标点才能让它们回到原来的坐标系。

所以改变绘画区域更容易,但是如果你使用一个图像,那么当你缩小窗口大小时会发生什么?你会截断任何现有的绘画吗?

出于这个原因,我建议您直接在组件上绘制并使用列表来跟踪各个椭圆。这种调整大小的方式不会影响椭圆的绘制。将改变的只是随时可见的内容。

查看Custom Painting Approaches 以获取此方法的示例。这个例子展示了如何使用不同的颜色而不用硬编码特定的方法来设置颜色。

由于这是一个从paintComponent开始的小项目,我想简单地截断该区域。

对于一个简单的解决方案,只需将图像设置为屏幕大小即可。这样您就不必担心每次调整框架大小时都会截断/拉伸。

否则,您需要在面板中添加ComponentListener 并监听 componentResized() 事件。然后您需要创建一个新图像并将旧图像绘制到新图像上。您应该注意,对于调整面板大小的每个像素都会生成一个 componentResized() 事件,因此这将涉及大量后台工作。

【讨论】:

  • 感谢 camickr 的冗长回复。由于这是一个让我开始使用paintComponent 的小项目,我想简单地截断该区域。您对我如何做到这一点有任何想法吗?
  • 我添加了:Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();然后 blankCanvas = this.createImage(screenSize.width, screenSize.height);但这不起作用。我做错了吗?
  • @Eyenstein, but this doesn't work 我不知道这意味着什么。
  • 对不起,我是新来的。我的意思是它仍然存在与以前相同的问题。图像区域仍然是相同的大小
  • @Eyenstein,如果您将图像设置为屏幕的大小,那么这将是它的大小。但是,您只会看到滚动窗格视口中可见的任何内容。因此,随着框架调整大小,图像的可见性会发生变化。
【解决方案2】:

在您的paintComponent 方法中使用g2d.scale(x, y)。您需要获取当前高度和宽度并将其与之前的高度和宽度进行比较以确定比例因子。设置它,以便当屏幕处于默认大小时,您的比例因子为 0。

您需要一个窗口侦听器来计算 componentResized() 事件的比例因子。像 scaleX = getWidth() / WIDTH;

【讨论】:

    【解决方案3】:

    要查找 Windows 的当前高度和宽度,请尝试此代码

    Toolkit toolkit =  Toolkit.getDefaultToolkit ();
    Dimension dim = toolkit.getScreenSize();
    int width = dim.getWidth();
    int height = dim.getHeight();
    

    现在使用Graphics类的缩放函数scale(int x, int y),当窗口大小发生变化时,这个方法会被反复快速连续调用,使用上面的代码检查。

    最好尝试阅读https://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-07
      • 2014-07-04
      • 2020-06-07
      • 2015-04-16
      相关资源
      最近更新 更多