Java - 如何调整图像大小以适应窗口大小?

时间:2013-11-06 18:29:04

标签: java image swing

我正在制作一个类似于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";

        }

    }

}

3 个答案:

答案 0 :(得分:1)

我不知道你是否有关于缩放现有图像的问题,或者随着帧尺寸的变化使绘画区域变大或变小。

缩放是一个问题,因为一旦调整图像大小,您将始终需要重新缩放鼠标点以使其返回原始坐标系。

因此更改绘画区域更容易,但如果使用图像,那么缩小窗口大小会发生什么?你截断任何现有的画作吗?

出于这个原因,我建议你只需直接在组件上绘画,然后使用List来跟踪单个椭圆。这种方式调整大小不会影响椭圆的绘制。所有改变的都是随时可见的。

查看Custom Painting Approaches以获取此方法的示例。此示例显示了如何在不使用特定方法硬编码的情况下使用不同的颜色来设置颜色。

  

由于这是一个用paintComponent启动我的小项目,我想简单地截断该区域。

对于简单的解决方案,只需将图像设为屏幕尺寸即可。然后,您不必担心每次帧调整大小时都会截断/拉伸。

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

答案 1 :(得分:0)

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

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

之类的东西

答案 2 :(得分:0)

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

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

现在使用Graphics类的缩放函数缩放(int x,int y),当窗口大小发生变化时,重复调用此方法并快速连续调用,使用上面的代码进行检查。

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