我正在尝试制作一个只包含一个标签的弹出窗口。理想情况下,我会指定弹出窗口的最大宽度,以及要显示的字符串,弹出窗口会自动调整大小,以便文本在超过指定的最大宽度时会换行,并且它将是正确的高度。如果不通过计算复杂地使用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()
调用中同时指定宽度和高度,因此处理不同的行为并不健全输入消息。
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();
}
}
}
答案 0 :(得分:4)
请参阅使用CSS修复宽度的FixedWidthText
:
答案 1 :(得分:0)
我可能会使用包装JTextArea而不是带有html的JLabel的单词,请参阅此处的JMultiLineLabel答案Java swing: Multiline labels?
至于弹出窗口的大小,我不知道除了使用FontMetrics之外的任何其他方法,尽管它并不复杂。
public class FoxPopup extends JPanel {
private Popup popup;
public FoxPopup(String message, int width) {
setBackground(Color.pink);
setLayout(new BorderLayout());
JTextArea textArea = createMultiLineLabel(message);
add(textArea);
setSize(textArea, width);
}
private JTextArea createMultiLineLabel(String message) {
JTextArea textArea = new JTextArea(message);
textArea.setEditable(false);
textArea.setCursor(null);
textArea.setOpaque(false);
textArea.setFocusable(false);
textArea.setFont(UIManager.getFont("Label.font"));
textArea.setWrapStyleWord(true);
textArea.setLineWrap(true);
return textArea;
}
private void setSize(JTextArea textArea, int width) {
FontMetrics fm = textArea.getFontMetrics(textArea.getFont());
int textWidth = SwingUtilities.computeStringWidth(textArea.getText());
Dimension d = new Dimension();
d.setSize(width, fm.getHeight() * Math.ceil((double) textWidth / (double) width));
setPreferredSize(d);
}
public void launch(Component owner, int x, int y) {
popup = PopupFactory.getSharedInstance().getPopup(owner, this, x, y);
popup.show();
}
}