调整绘图大小以匹配框架大小。

6
我编写了一个应用程序,在paint()中基于固定像素位置自定义绘制所有内容。然后我禁用了框架的调整大小,以便它始终可见。
但是,现在我想要能够调整大小,但是我不想改变我的绘制代码。我希望在所有绘制代码之后,能够获取Graphics g对象的300x300正方形并将其调整为当前JFrame的大小,但是我不知道该怎么做。
这里是一个示例代码。在这个示例中,我希望100x100的正方形保持在中间,并与重新调整大小后的JFrame成比例:
package DrawAndScale;

import java.awt.Color;
import java.awt.Graphics;

public class DASFrame extends javax.swing.JFrame {
    public DASFrame() {
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        this.setSize(300, 300);
    }

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new DASFrame().setVisible(true);
            }
        });
    }

    @Override
    public void paint(Graphics g) {
        g.setColor(Color.BLACK);
        g.fill3DRect(100, 100, 100, 100, true);
    }
}

感谢。

1
除非你真的知道自己在做什么,否则不应该覆盖JFrame的paint()方法。自定义绘图是通过覆盖JPanel或JComponent的paintComponent()方法来完成的。 - camickr
真正的代码是在JFrame内的画布上绘制所有内容,我只是为了简洁起见而在其上进行了绘制。不过还是要感谢你,因为我真的不知道自己在做什么。 - Bryan Bueter
4个回答

3
假设您将绘制300x300的方法重命名为paint300,定义一个缓冲图像:
@Override public void paint(Graphics g) {
     Image bufferImage = createImage(300, 300);  // empty image
     paint300(bufferImage.getGraphics());  // fill the image
     g.drawImage(bufferImage, 0, 0, null);  // send the image to graphics device
}

以下是当您想要以全尺寸(300x300)绘制时的情况。 如果您的窗口大小被调整:
@Override public void paint(Graphics g) {
     Image bufferImage = createImage(300, 300);  
     paint300(bufferImage.getGraphics());
     int width = getWidth();
     int height = getHeight(); 
     CropImageFilter crop = 
         new CropImageFilter((300 - width)/2, (300 - height)/2 , width, height);
     FilteredImageSource fis = new FilteredImageSource(bufferImage, crop);
     Image croppedImage = createImage(fis);
     g.drawImage(croppedImage, 0, 0, null);
}

新的类来自于java.awt.image.*。
我没有测试这段代码。它只是为了让你走向正确的方向。

1
是的,就是这样!不过我使用了ReplicateScaleFilter(宽度,高度)而非CropImageFilter(),这样它会按比例缩放到新窗口大小。正好是我想要的。 - Bryan Bueter

2
如果你想进行自定义绘画,则可以查找JLabelJPanel,并在其中包含Icon/ImageIcon。以下是一个简单的例子。

enter image description here enter image description here

enter image description here

import java.awt.*;
import javax.swing.*;

public class MainComponentPaint extends JFrame {

    private static final long serialVersionUID = 1L;

    public MainComponentPaint() {
        setTitle("Customize Preffered Size Test");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public void display() {
        add(new CustomComponent());
        pack();
        setMinimumSize(getSize());
        setPreferredSize(getSize());
    SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {
            setVisible(true);
        }
    });
    }

    public static void main(String[] args) {
        MainComponentPaint main = new MainComponentPaint();
        main.display();
    }
}

class CustomComponent extends JComponent {

    private static final long serialVersionUID = 1L;

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(50, 50);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        int w = getWidth();
        int h = getHeight();
        for (int i = 0; i < Math.max(w, h); i += 20) {
            g.drawLine(i, 0, i, h);
            g.drawLine(0, i, w, i);
        }
    }
}

这并没有回答楼主的问题。 - Jeffrey
@Jeffrey 嗯,我不是在谈论调整自定义2D图形的大小,而是如何正确地在Swing中绘制。顺便说一句,知道如何防止代码闪烁或冻结会很好,那将是对OP的回答,而不是我的兴趣和问题。 - mKorbel
我冒昧修改了你的示例;这样的组件对于研究这些问题非常有价值。如果不正确,请恢复原样;如果我越界了,请谅解。 - trashgod

1
你可以用一些数学方法来实现这个。
public void paint(Graphics g){
    int height = 100;
    int width = 100;

    int x = (this.getWidth() / 2) - (width / 2);
    int y = (this.getHeight() / 2) - (height / 2);

    g.setColor(Color.BLACK);
    g.fill3DRect(x, y, width, height, true);

}

或者,如果您想保持盒子的宽度和高度成比例,请使用int width = this.getWidth() / 3;int height = this.getHeight() / 3

另一个选择是使用 Graphics2D.scale(),正如 JB 指出的那样,传递的 Graphics 对象实际上是一个 Graphics2D 对象。


数学是我想要扩展的原因,我有许多需要编辑的代码行。 - Bryan Bueter

1

我无法直接在绘图对象上使用比例尺。似乎我需要在缓冲图像上进行绘制,然后使用过滤器进行比例缩放。也许我错过了什么,但现在我有答案了。 - Bryan Bueter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接