当前位置: 首页 > 知识库问答 >
问题:

JPanel的宽度和高度为0(具体情况)

郁烨
2023-03-14

请原谅我,如果这是很难遵循,但我有一个具体的问题,我需要帮助解决。我做了大量的研究,尝试了许多解决方案,但都没有奏效。

我的问题是,我有一个ImagePanel类,它正在扩展JPanel(下面的代码),这个类需要使用宽度和高度来缩放图像(我正在制作一个程序,用户可以创建自定义教程,包括图像)。当我实例化这个时,我得到一个错误,说宽度和高度必须非零。我明白这是因为布局管理器还没有传递ImagePanel首选大小,但是我不知道如何将该大小传递给面板。ImagePanel在一个JPanel内,它在一个JSplitPane内,在一个JSplitPane内,在一个JSplitPane

  1. JFrame(网格布局)
  2. JSplitPane(默认拆分窗格布局)
  3. JTabbedPane(Deault JTabbedPane布局)
  4. JPanel(网格布局)
  5. JScrollPane(默认滚动窗格布局)
  6. JSplitPane(默认拆分窗格布局)
  7. JPanel(网格布局)
  8. 图像面板

ImagePanel的代码如下所示:

import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JPanel;

public class ImagePanel extends JPanel{

    private BufferedImage i;
    private ImageIcon miniature;
    private Image paint = null;

    public void createImage(String path){
        try {                
            i = ImageIO.read(new File(path));
        } catch (IOException ex) {
            ex.printStackTrace();
        }

        if(i != null){
            int width = (int)((double)i.getWidth() * ((double)getWidth()/i.getWidth()));
            int height = (int)((double)i.getHeight()*i.getHeight()/i.getWidth()*((double)this.getHeight()/i.getHeight()));
            miniature = new ImageIcon(i.getScaledInstance(width, height, Image.SCALE_SMOOTH));
            paint = miniature.getImage();
        }

    }


    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        if (paint!=null){
            g.drawImage(paint, 0, 0, null);}     
    }

}

如何获得ImagePanel的正确大小。我希望图像随着JFrame的大小而改变大小,这就是为什么我不使用setPreferedSize()


共有2个答案

杨利
2023-03-14

至少有两种方法可以实现这一点,第一种方法是允许画图组件检查画图的状态,并在图像为null时适当地重新缩放图像

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);

    if (i != null && paint == null){
        generateScaledInstance();
    }
    if (paint != null) {
        g.drawImage(paint, 0, 0, this);
    }
}

这将起作用,因为除非组件的大小大于0,并且连接到本地对等方(在屏幕上),否则永远不应调用paintComponent

这不是一个好主意,因为缩放可能需要时间,如果可以避免的话,您不想减慢绘制过程。

您可以使用连接到ImagePanelComponentListener监视componentresisted事件

addComponentListener(new ComponentAdapter() {
    @Override
    public void componentResized(ComponentEvent e) {
        if (i != null) {
            generateScaledInstance();
        }
    }
});

这可能会被快速连续调用多次,所以要小心。

在本例中,我倾向于使用javax。摆动计时器设置为小延迟,以将更新合并到尽可能少的调用,例如。。。

private Timer resizeTimer;
//...
// Probably in you classes constructor
resizeTimer = new Timer(250, new ActionListener() {
    public void actionPerformed(ActionEvent evt) {
        // Actually perform the resizing of the image...
        generateScaledInstance();
    }
});
// Don't want a repeating event...
resizeTimer.setRepeats(false);

//...
public void componentResized(ComponentEvent evt) {
    resizeTimer.restart();
}

这允许快速连续多次调用组件调整大小,但是如果之间的时间超过250毫秒,则可以调用GenerateScaledInstance,例如...

默认情况下,还应提供非0大小的preferredSize值(请记住,面板的默认首选大小为0x0)。根据布局管理器的不同,这可以忽略,但通常用作大多数布局管理器的基础。。。

俞衡虑
2023-03-14

我想改变图像的大小与JFrame的大小

你可以使用达里尔的拉伸图标,而不是在你自己的组件中进行自定义绘画。图标将根据可用空间自动调整大小。

这就是为什么我不只是使用setPreferedsize();。

如果使用自定义绘制,则不应使用setPreferredSize()。您应该重写getPreferredSize()方法以返回图像的大小。请记住,首选尺寸只是向布局经理提出的建议。布局管理器可以使用或忽略尺寸。

如果要在paintComponent()方法中自动缩放图像,则代码应为:

Dimension d = getSize();
g.drawImage(paint, 0, 0, d.width, d.height, this);

因此,代码中的真正挑战(无论您选择哪种解决方案)是确保您使用的布局管理器将为组件提供所有可用空间,以便图像可以自动缩放。

 类似资料:
  • 因此,我创建了一个简单的模拟,其中方块是随机产生的,随机向量和窗口边缘的反弹。 我希望它能考虑到正在调整的窗口大小。因此,如果我将窗口的尺寸从600x600改为1200x600,则新边框的方块将会弹出,而不是600x600。 我尝试执行getWidth()getHeight(),但它将返回0。因此,我将它放在pain()(因为它在window resize中被调用)方法中,并将返回值保存为局部变量

  • 我有一个字体对象,我需要字体的宽度和高度。我知道getSize()返回字体的高度,因为字体的点号通常是高度,但在确定字体的宽度时,我不知所措。 或者,能够确定字体支持的每个特定字符的宽度也是一个可接受的解决方案。 我的最佳猜测是,宽度是在使用loadFont方法时指定的,但文档没有指定size参数是表示字体的宽度还是高度。 使用的所有字体都是单空格字体,如DejaVu Sans mono、GNU

  • 主要内容:1. width,2. height,3. max-width 和 max-height,4. min-width 和 min-heightCSS 尺寸属性指的就是元素的宽度和高度属性,虽然说非常简单,但却是必须掌握的技能。CSS 中提供了 width、height、max-width、min-width、max-height 和 min-height 等几个属性来设置元素的宽度和高度,这些元素使用起来非常简单,下面我们就来简单介绍一下。 1. width 通过 width 属性可以设

  • 文件:main。派克 文件:run_me.py 我试图从左下角到右上角画一条线。 我认为这可能是一个尺度问题(变量self.available\u width,self.available\u height)。 我做错了什么?

  • 前面我们提到HTML元素的尺寸(高或宽)是动态的,会随着内容调整。不过我们也可以为元素设定固定的尺寸大小。 blockquote{ width: 600px;} 上面的 blockquote 将始终保持600px的宽度,如果浏览器窗口小于600px,将显示一个水平滚动条。 因为我们只设置了宽度,那么这个 blockquote 的高度仍然是动态的,会自动调整来适应内容。 CSS 溢出(overflo

  • 我会保持简短直截了当,这样我就明白了: > vw根据视区宽度更改字体大小。 VH根据视区高度更改字体大小。 我的问题是; 有没有一种方法可以根据视区的宽度和高度来缩放我的字体大小?因此,改变浏览器的高度和宽度将适当地缩放我的字体大小。 我这样问是因为我想根据它们所在的容器适当地缩放我的文本大小,我的问题是容器缩放到100%的宽度和100%的高度。因此,根据高度和宽度来缩放文本大小似乎是合乎逻辑的,