【问题标题】:JPanel is resized if it is larger than its parent如果 JPanel 大于其父级,则调整其大小
【发布时间】:2012-11-27 05:59:14
【问题描述】:

我有一个JScrollPanel,我添加一个包含图像的JPanelJScrollPanel 并且它可以工作,但是如果JPanel 中的图像大于JScrollPanel 在宽度、高度、或将两个面板的大小调整为大约 20x20。为什么这样做?我在JScrollPanel 的视口上使用GridBagLayout。我期待的是,如果 JPanel 大于 JScrollPanel 它将添加滚动条,但这不是正在发生的事情。有什么建议吗?

private void jMenuItem1ActionPerformed(java.awt.event.ActionEvent evt) {                                           
    WebFileChooser wfc = null;
    if(wfc == null){
        wfc = new WebFileChooser(this, "Open an Image");
        wfc.setSelectionMode(SelectionMode.SINGLE_SELECTION);
        wfc.setAvailableFilter(GlobalConstants.IMAGES_AND_FOLDERS_FILTER);
        wfc.setChooseFilter(GlobalConstants.IMAGES_FILTER);
        wfc.setCurrentDirectory("/Users/Ryan/Desktop");
    }
    wfc.setVisible(true);

    if(wfc.getResult() == StyleConstants.OK_OPTION){
        String file = wfc.getSelectedFile().getPath();
        try{
            imagePane.remove(canvas);
        }catch(Exception e){
        }
        canvas = new Canvas();
        canvas.setVisible(true);
        canvas.setImage(file);
        //imagePane.getViewport().setLayout(new GridBagLayout());
        canvas.setSizeFromLoaded();
        imagePane.getViewport().add(canvas);
        imagePane.repaint();
        imagePane.revalidate();
    }
}

这是 Canvas 类:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pocketshop;

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import pocketshop.util.ImageSync;

/**
 *
 * @author Ryan
 */
public class Canvas extends CanvasShadow{

    public static BufferedImage image = null, preview = null;
    public static int width, height;

    public void setImage(String filename){
        try{
            Canvas.image = ImageIO.read(new File(filename));
            Canvas.width = image.getWidth();
            Canvas.height = image.getHeight();
            ImageSync.originalPixels = new int[width * height];
            ImageSync.previewPixels = new int[width * height];
            Canvas.image.getRGB(0, 0, width, height, ImageSync.originalPixels, 0, width);
        }catch(IOException e){
        }
    }

    public static void setImage(BufferedImage image){
        Canvas.image = image;
        Canvas.width = image.getWidth();
        Canvas.height = image.getHeight();
        ImageSync.originalPixels = new int[width * height];
        ImageSync.previewPixels = new int[width * height];
        Canvas.image.getRGB(0, 0, width, height, ImageSync.originalPixels, 0, width);
    }

    public static void setPreview(BufferedImage img, Container parent){
        preview = img;
        parent.repaint();
    }

    public static BufferedImage deepCopy(){
        ColorModel cm = Canvas.image.getColorModel();
        boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
        WritableRaster raster = Canvas.image.copyData(null);
        return new BufferedImage(cm, raster, isAlphaPremultiplied, null);
    }

    public void setSizeFromLoaded(){
        try{
            this.setPreferredSize(new Dimension(Canvas.width + 10, Canvas.height + 10));
            this.setSize(Canvas.width + 10, Canvas.height + 10);
        }catch(Exception e){
            e.getMessage();
        }
    }

    @Override
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        if(Canvas.preview != null){
            g.drawImage(Canvas.preview, 5, 5, width, height, Color.black, null);
        }else{
            g.drawImage(Canvas.image, 5, 5, width, height, Color.black, null);
        }
    }
}

这里是 CanvasShadow 类:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pocketshop;

import java.awt.Color;
import org.jdesktop.swingx.JXPanel;
import org.jdesktop.swingx.border.DropShadowBorder;

public class CanvasShadow extends JXPanel{

    public CanvasShadow(){
        DropShadowBorder shadow = new DropShadowBorder();
        shadow.setShadowColor(Color.BLACK);
        shadow.setShowLeftShadow(true);
        shadow.setShowRightShadow(true);
        shadow.setShowBottomShadow(true);
        shadow.setShowTopShadow(true);
        this.setBorder(shadow);

        float[] hsb = new float[3];

        Color.RGBtoHSB(255, 255, 255, hsb);

        this.setBackground(Color.getHSBColor(hsb[0], hsb[1], hsb[2]));
    }
}

这是实际图片:http://images2.fanpop.com/images/photos/4800000/Beach-beaches-4843817-1280-800.jpg

【问题讨论】:

  • 好吧,我想我应该小心我的要求。伙计,所有的静电是怎么回事?!摆脱他们。您刚刚创建了一个不能多次实例化的可重用面板,因为 Canvas 的所有实例共享同一个图像。实例变量是你的朋友。静电是魔鬼!!这是什么 ImageSync 东西?更多静力学?!
  • 不要使用 remove()。只需在现有画布实例上设置文件。它将使用新图像重绘。
  • 如果我摆脱了静态,我将如何从另一个无法覆盖数据的类中访问该类,例如具有调整滑块以调整图像亮度的对话框。跨度>
  • 只要有一个对该类的实例引用。例如,如果 Canvas 需要与 ImageSync 通信,那么 Canvas 将有一个 ImageSync 类型的实例变量。构建 Canvas 的客户端将在构建时或通过调用 setter 方法将 ImageSync 实例提供给 Canvas 实例。我不确定为什么 Canvas 依赖于 ImageSync,因为没有它你可以做到这一点,但作为一个例子,这就是你要做的。当一个对象引用另一个对象时,它被称为依赖项。您的 Canvas 对象也与 BufferedImage 有依赖关系...
  • 如果对象不管理这些依赖项的生命周期,最好让客户端提供对象所需的依赖项。使用静态作为查找其他对象实例的一种方式会锁定您,因此您永远不能拥有多个给定对象的实例。您今天可能只需要一个实例,但随着需求的变化,您可能需要两个或更多。如果你不使用静态创建另一个实例是 1 分钟的工作。使用静力学,它可能需要几天的重构才能起作用。如果您只需要一个实例调用 new 一次,然后将其传递给您的组件。

标签: java swing


【解决方案1】:

我已经告诉过你摆脱那个 GridBagLayout。在 JScrollPane 上设置布局将调整面板的大小,使其永远不会大于容器。您的面板必须自行布置,以便它是图像的大小,以便 JScrollPane 看到它太大而无法显示。只有这样 JScrollPane 才会添加滚动条。因此,如果您的图像是 2000x2000,那么您的面板需要将其首选尺寸设置为 2000x2000 并表现得像它可以那么大。 JScrollPane 将完成所有繁重的裁剪工作,并确保面板仅呈现基于滚动条的可见部分。如果您的面板始终与 JScrollPane 的视口大小相同,则滚动窗格认为它适合并且不需要滚动条。

更新:快速谷歌搜索揭示了答案:http://chaosinmotion.com/blog/?p=168

【讨论】:

  • 我删除了 GridBagLayout 并且它可以工作,但是现在滚动条不存在并且 JPanel 不再位于 JScrollPanel 的中心。
  • JPanel 不在中心是什么意思?图像在哪里?您显示的图像有多大与 JScrollPane 的视口有多大?您是在 JPanel 上重写 paintComponent() 以在面板上手动绘制图像还是在做其他事情?
  • 好的,我已经添加了一些源代码。图像显示在左上角。 CanvasShadow 显示滚动面板的完整高度和宽度。我将在主要问题上附上两个屏幕截图。
  • 那是因为你把它画在左上角。您可以覆盖 getScrollableTracksViewportHeight() 和 getScrollableTracksViewportWidth() 以返回 false 并且您的组件不会将其大小跟踪到视口的大小。至于当它小于可见区域时将其居中。您可以尝试使用 setHorizo​​ntalAlignment() 和 setVerticalAlignment() 看看 ScrollPaneLayout 是否会注意这些。如果这不起作用,您必须继承 ScrollPaneLayout 以在组件小于视口大小时使组件居中。
  • 甜蜜!这是我添加的内容: canvas.setScrollableTracksViewportHeight(false); canvas.setScrollableTracksViewportWidth(false);
猜你喜欢
  • 2014-05-22
  • 2012-09-23
  • 2016-01-24
  • 1970-01-01
  • 1970-01-01
  • 2016-11-27
  • 2014-07-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多