当 setMaximumSize() 和 setPreferedSize() 不起作用时,如何对 JComponent 设置硬限制? [英] How do I set hard limit on a JComponent when setMaximumSize() and setPrefferedSize() don't work?

查看:32
本文介绍了当 setMaximumSize() 和 setPreferedSize() 不起作用时,如何对 JComponent 设置硬限制?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试制作一个类似于 Photoshop 或 Paint Shop Pro 中的图像处理框架,但我遇到了问题.

I'm trying to make an image processing frame similar to one found in something like Photoshop or Paint Shop Pro and I'm running into problems.

现在我有一个带有 JDesktopPane 的 JFrame 窗口.当我单击一个按钮时,会生成一个 JInternalFrame,其中包含以下组件:

Right now I have a JFrame window with a JDesktopPane. When I click a button, a JInternalFrame is made with the following components in it:

imageLabel = new JLabel("picture.png");
scrollPane.setViewPort(imageLabel);
internalFrame.add(scrollPane);  // I also tried with a BorderLayout()
desktopPane.add(internalFrame);

我的问题是:如果 JLabel 小于 JInternalFrame,我不希望 JLabel 或 JScrollPane 拉伸到 JInternalFrame 的大小.

My problem is this: I don't want the JLabel or the JScrollPane to stretch to the size of the JInternalFrame if the JLabel is smaller than the JInternalFrame.

我尝试用空"JLabel 填充 JLabel 周围的空间.我试过切换 JScrollPane 的布局样式.我已经尝试将 JLabel 和 JScrollPane 的首选和最大尺寸设置为picture.png 的尺寸.没有一个适合我的需要.我不希望 JLabel 周围的空白空间"成为 JScrollPane 或 JLabel 的一部分,以便我可以使用各种 MouseEvents 来触发图片本身,而不是拉伸"的 JLabel 或 JScrollPane 留下的空间.我调整了 JInternalFrame 的大小.

I've tried padding the space around the JLabel with "empty" JLabels. I've tried switching layout styles of the JScrollPane. I've tried setting the preferred and maximum sizes of the JLabel and the JScrollPane to that of picture.png. None of it works for what I need. I don't want the blank "space" around the JLabel to be a part of the JScrollPane or the JLabel so that I can use various MouseEvents to trigger on the picture itself rather than the space left by the "stretched" JLabel or JScrollPane whenever I resize the JInternalFrame.

提前致谢.

Edit1:这里是一些突出问题的代码.

Here is a bit of code that highlights the problem.

import java.awt.*;
import java.awt.event.*;

class fooFrame extends JFrame implements MouseListener
{
private static fooFrame frame;
JLabel fooLabel;

public fooFrame()
{ 
    JDesktopPane background = new JDesktopPane();

    JInternalFrame internalFrame = new JInternalFrame("Internal Frame", true, true, true, true);
    internalFrame.setSize(500, 500);
    internalFrame.setLocation(20, 20);
    internalFrame.setVisible(true);

    Image image = Toolkit.getDefaultToolkit().getImage("test.gif");

    fooLabel = new JLabel(new ImageIcon("test.gif"));
    fooLabel.setPreferredSize(new Dimension(image.getWidth(null), image.getHeight(null)));

    JScrollPane fooScrollPane = new JScrollPane(fooLabel, JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    fooScrollPane.setPreferredSize(new Dimension(fooLabel.getWidth(), fooLabel.getHeight()));

    fooScrollPane.setViewportView(fooLabel);    // add JLabel to JScrollPane
    internalFrame.add(fooScrollPane);           // add JScrollPane to JInternalFrame
    background.add(internalFrame);              // add JInternalFrame to JDesktopPanel
    this.setContentPane(background);            // add JDesktopPanel to JFrame

    fooLabel.addMouseListener(this);
}

public void mouseClicked(MouseEvent me)
{
    if (me.getSource() == fooLabel)
        System.out.println("Clicked the picture.");
}
public void mouseEntered(MouseEvent me)
{
    if (me.getSource() == fooLabel)
        System.out.println("Entered the picture.");
}
public void mouseExited(MouseEvent me)
{
    if (me.getSource() == fooLabel)
        System.out.println("Exited the picture.");
}
public void mousePressed(MouseEvent me){}
public void mouseReleased(MouseEvent me){}

public static void createAndShowGUI()
{
    try 
    {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    }
    catch (Exception e) { }

    frame = new fooFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setTitle("foo");
    frame.setSize(800,600);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true); 
    }
}

您将必须获得自己的test.gif",如果您使 internalFrame 大于图片,它将用标签填充剩余空间.当我穿过 internalFrame 而不是像我希望发生的那样到达图片时,所有的 mouseEvents 都会触发.

You will have to get your own "test.gif" and if you make the internalFrame larger than the picture it fills the remaining space with the label. As all the mouseEvents fire when I cross the internalFrame rather than onto the picture like I want to have happen.

Edit2:根据 Kleopatra 的建议修改了代码.

Code modified with Kleopatra's suggestions.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.LineBorder;

public class a1
{
    public static void main(String[] args)
    {
            fooFrame.createAndShowGUI();
    }
}
class fooFrame extends JFrame implements MouseListener
{
private static fooFrame frame;
JLabel fooLabel;

public fooFrame()
{ 
    JDesktopPane background = new JDesktopPane();

    JInternalFrame internalFrame = new JInternalFrame("Internal Frame", true, true, true, true);
    internalFrame.setLocation(20, 20);
    internalFrame.setVisible(true);     
    internalFrame.pack();

    Image image = Toolkit.getDefaultToolkit().getImage("test.gif");
    fooLabel = new JLabel(new ImageIcon(image));
    fooLabel.setBorder(new LineBorder(Color.PINK));
    JScrollPane fooScrollPane = new JScrollPane((fooLabel), JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
    internalFrame.setLayout(new BoxLayout(internalFrame.getContentPane(), BoxLayout.LINE_AXIS));

    fooScrollPane.setViewportView(fooLabel);    // add JLabel to JScrollPane
    internalFrame.add(fooScrollPane);           // add JScrollPane to JInternalFrame
    background.add(internalFrame);              // add JInternalFrame to JDesktopPanel
    this.setContentPane(background);            // add JDesktopPanel to JFrame

    fooLabel.addMouseListener(this);
}

public void mouseClicked(MouseEvent me)
{
    if (me.getSource() == fooLabel)
        System.out.println("Clicked the picture.");
}

public void mouseEntered(MouseEvent me)
{
    if (me.getSource() == fooLabel)
        System.out.println("Entered the picture.");
}

public void mouseExited(MouseEvent me)
{
    if (me.getSource() == fooLabel)
        System.out.println("Exited the picture.");
}

public void mousePressed(MouseEvent me)
{
}

public void mouseReleased(MouseEvent me)
{
}

@Override
public Dimension getMaximumSize()
{
    return getPreferredSize();
}

public static void createAndShowGUI()
{
    try
    {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    } catch (Exception e)
    {
    }

    frame = new fooFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setTitle("foo");
    frame.setSize(800, 600);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
}
}

推荐答案

在这个例子中,内部框架最初不会超过 MAX_SIZE 像素.较小的图片将被调整大小,以便不需要滚动.

In this example, the internal frame will initially be no more than MAX_SIZE pixels. Smaller pictures will be sized so that scrolling is not required.

附录:仔细阅读标题,您可能还想限制内部框架的最大尺寸:

Addendum: Reading the title more closely, you may also want to limit the internal frame's maximum size:

internalFrame.setMaximumSize(new Dimension(fooLabel.getPreferredSize()));

附录:这种变化可能有助于澄清问题.使用默认布局 BorderLayout.CENTER,滚动条按要求显示,但 MouseListener 的行为不符合预期.使用尊重首选大小的布局,FlowLayoutMouseListener 正确报告,但滚动条永远不会出现,因为标签的首选大小永远不会改变.为方便起见,我添加了合成图像.

Addendum: This variation may help clarify the problem. With the default layout, BorderLayout.CENTER, the scroll bars appear as required, but the MouseListener does not behave as desired. With a layout that respects preferred sizes, FlowLayout, the MouseListener reports correctly, but the the scroll bars never appear, as the label's preferred size never changes. I've added synthetic images for convenience.

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;

class PictureFrame extends JFrame {

    private static final String NAME = "image.jpg";

    public PictureFrame() {
        JDesktopPane dtp = new JDesktopPane();
        dtp.add(new MyFrame("Large", FauxImage.create(300, 500), 50));
        dtp.add(new MyFrame("Small", FauxImage.create(200, 200), 25));
        this.add(dtp);
    }

    private static class MyFrame extends JInternalFrame {

        private static final int MAX_SIZE = 256;

        public MyFrame(String title, Image image, int offset) {
            super(title, true, true, true, true);
            //this.setLayout(new FlowLayout());
            final JLabel label = new JLabel(new ImageIcon(image));
            this.add(new JScrollPane(label));
            this.pack();
            int w = Math.min(MAX_SIZE, image.getWidth(null));
            int h = Math.min(MAX_SIZE, image.getHeight(null));
            Insets i = this.getInsets();
            this.setSize(w + i.left + i.right, h + i.top + i.bottom);
            this.setLocation(offset, offset);
            this.setVisible(true);
            label.addMouseListener(new MouseAdapter() {

                @Override
                public void mouseEntered(MouseEvent me) {
                    if (me.getSource() == label) {
                        System.out.println("Entered.");
                    }
                }

                @Override
                public void mouseExited(MouseEvent me) {
                    if (me.getSource() == label) {
                        System.out.println("Exited.");
                    }
                }
            });
        }
    }

    private static class FauxImage {

        static public Image create(int w, int h) {
            BufferedImage bi = new BufferedImage(
                w, h, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2d = bi.createGraphics();
            g2d.setPaint(Color.lightGray);
            g2d.fillRect(0, 0, w, h);
            g2d.setColor(Color.black);
            String s = w + "u00D7" + h;
            int x = (w - g2d.getFontMetrics().stringWidth(s)) / 2;
            g2d.drawString(s, x, 24);
            g2d.dispose();
            return bi;
        }
    }

    public static void createAndShowGUI() {
        PictureFrame frame = new PictureFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setTitle("PictureFrame");
        frame.setSize(640, 400);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

这篇关于当 setMaximumSize() 和 setPreferedSize() 不起作用时,如何对 JComponent 设置硬限制?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆