java - 如何制作带有换行文本的自动调整大小的 Swing 弹出窗口?

标签 java swing popup

我正在尝试制作一个仅包含单个标签的弹出窗口。理想情况下,我会指定弹出窗口的最大宽度和要显示的字符串,并且弹出窗口会自动调整自身大小,以便文本在超过指定的最大宽度时会换行,并且它将是正确的高度。如果不使用复杂的 FontMetrics 来暴力计算,在 Swing 中是否可以做到这样的事情?这是我正在尝试做的一个示例:

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Popup;
import javax.swing.PopupFactory;
import javax.swing.SpringLayout;


public class PopupTest extends JFrame {
    private static final String FOX_MESSAGE = "<html>The lithe, quick, brown fox jumps " +
                                              "happily and steadily over the fat, slobbery, " +
                                              "lazy dogs</html>";
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    PopupTest frame = new PopupTest();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public PopupTest() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        final JPanel contentPane = new JPanel();
        setContentPane(contentPane);
        contentPane.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));

        final JButton btnLaunch = new JButton("Launch popup");
        btnLaunch.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                Point btnLoc = btnLaunch.getLocationOnScreen();
                FoxPopup popup = new FoxPopup(FOX_MESSAGE, 200);
                popup.launch(contentPane, btnLoc.x, btnLoc.y + btnLaunch.getHeight());              
            }
        });
        contentPane.add(btnLaunch);
    }

    public class FoxPopup extends JPanel {
        private static final int ARBITRARILY_TALL = 9999;
        private Popup popup;

        public FoxPopup(String message, int width) {
            setBackground(Color.pink);
//          SpringLayout springLayout = new SpringLayout();
//          setLayout(springLayout);

            JLabel lblDescription = new JLabel(message);
//          springLayout.putConstraint(SpringLayout.NORTH, lblDescription, 5, SpringLayout.NORTH, this);
//          springLayout.putConstraint(SpringLayout.WEST, lblDescription, 5, SpringLayout.WEST, this);
//          springLayout.putConstraint(SpringLayout.EAST, lblDescription, -5, SpringLayout.EAST, this);
            add(lblDescription);
//          setPreferredSize(new Dimension(width, 65));
            setMaximumSize(new Dimension(width, ARBITRARILY_TALL));
        }

        public void launch(Component owner, int x, int y) {
            popup = PopupFactory.getSharedInstance().getPopup(owner, this, x, y);
            popup.show();
        }
    }
}

如果我编译并运行上面的代码,那么我会得到一个宽弹出窗口(比我请求的最大 200 像素更宽),所有文本都在一行上。如果我取消注释所有注释行,那么我会得到所需的行为,但我必须setPreferredSize() 调用中指定宽度和高度,所以它是处理不同输入消息的鲁棒性不强。


根据下面 Andrew Thompson 的答案编辑解决方案

public class PopupTest extends JFrame {
    private static final String FOX_MESSAGE = "The lithe, quick, brown fox jumps " +
                                              "happily and steadily over the fat, slobbery, " +
                                              "lazy dogs";
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    PopupTest frame = new PopupTest();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public PopupTest() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        final JPanel contentPane = new JPanel();
        setContentPane(contentPane);
        contentPane.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));

        final JButton btnLaunch = new JButton("Launch popup");
        btnLaunch.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                Point btnLoc = btnLaunch.getLocationOnScreen();
                FoxPopup popup = new FoxPopup(FOX_MESSAGE, 200);
                popup.launch(contentPane, btnLoc.x, btnLoc.y + btnLaunch.getHeight());              
            }
        });
        contentPane.add(btnLaunch);
    }

    public static class FoxPopup extends JPanel {
        private Popup popup;

        public FoxPopup(String message, int width) {
            setBackground(Color.pink);

            JLabel lblDescription = new JLabel(formatMessage(message, width));
            add(lblDescription);
        }

        private static String formatMessage(String message, int width) {
            return String.format("<html><body style='width: %d'>%s</body></html>", width, message);
        }

        public void launch(Component owner, int x, int y) {
            popup = PopupFactory.getSharedInstance().getPopup(owner, this, x, y);
            popup.show();
        }
    }
}

最佳答案

参见FixedWidthText它使用 CSS 来固定宽度:

关于java - 如何制作带有换行文本的自动调整大小的 Swing 弹出窗口?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25266847/

相关文章:

java - 如何使用 Couchbase Java SDK 3 使用不同的端口

java - 如何使用多个spring配置文件

java - hadoop、 Jersey 和 JBoss : application won't start

java - 可以实例化DocumentListener类型

java - 在 JPanel 周围移动 JTextArea

windows - 如何避免 "Your system is running low on virtual memory"弹出窗口?

java - 为什么 javac 提示与类的类型参数无关的泛型?

java - 为什么自定义组件没有显示在 JFrame 上?

javascript - 是否存在弹出窗口? (javascript)

javascript - 在特定情况下显示和隐藏弹出窗口