Java JLabel Высота с несколькими строками
Привет, у меня есть проблема в коде ниже (в основном в методе "append(String str)"). Я хочу показать сообщения, полученные в формате HTML (поэтому мне нужно использовать JLabel). Без установки tac.preferredSize вот что я получаю:
НО это не работает, используя длинную строку без пробелов: например, "аааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааааа
Если я установлю tac.preferredSize, высота пузырька не увеличивается:
Как я могу преодолеть эти проблемы? (работает с макетом / размерами и не изменяет строку ввода)
Вот код:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ClientGUI extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
private JLabel label;
private JTextField tf;
private JPanel chatPanel;
private JScrollPane scroll;
ClientGUI() {
super("Chat Client");
label = new JLabel("You can write messages below:", SwingConstants.CENTER);
chatPanel = new JPanel();
tf = new JTextField("");
tf.setBackground(Color.WHITE);
tf.requestFocus();
tf.setVisible(true);
tf.addActionListener(this);
chatPanel.setLayout(new BoxLayout(chatPanel, BoxLayout.PAGE_AXIS));
chatPanel.add(Box.createVerticalGlue());
JPanel centerPanel = new JPanel(new GridLayout(1,1));
scroll = new JScrollPane();
scroll.setViewportView(chatPanel);
scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
scroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
centerPanel.add(scroll);
add(centerPanel, BorderLayout.CENTER);
JPanel southPanel = new JPanel(new BorderLayout());
JPanel writeChatPanel = new JPanel(new GridLayout(2,1));
writeChatPanel.add(label);
writeChatPanel.add(tf);
southPanel.add(writeChatPanel, BorderLayout.NORTH);
add(southPanel, BorderLayout.SOUTH);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(600, 600);
setVisible(true);
chatPanel.scrollRectToVisible(new Rectangle(chatPanel.getSize()));
}
void append(String str) {
LeftArrowBubble leftArrowBubble = new LeftArrowBubble();
leftArrowBubble.setMaximumSize(new Dimension(400,350));
JLabel tac = new JLabel();
tac.setMaximumSize(new Dimension(350,400));
//tac.setPreferredSize(new Dimension(350,50)); //<----------
System.out.println(str);
tac.setText("<html><body style='width: 350px; padding:15px;display:block;'>"+str+"</body></html>");
tac.setOpaque(false);
leftArrowBubble.add(tac, BorderLayout.NORTH);
chatPanel.add(leftArrowBubble);
chatPanel.add(Box.createRigidArea(new Dimension(0,5)));
Rectangle rect = chatPanel.getBounds();
Rectangle r2 = scroll.getViewport().getVisibleRect();
chatPanel.scrollRectToVisible(new Rectangle((int) rect.getWidth(),
(int) rect.getHeight(), (int) r2.getWidth(), (int) r2.getHeight()));
revalidate();
repaint();
}
public void actionPerformed(ActionEvent e) {
// just have to send the message
append(tf.getText());
tf.setText("");
return;
}
public static void main(String[] args) {
new ClientGUI();
}
}
И пузырьковый класс:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.GeneralPath;
import javax.swing.BoxLayout;
import javax.swing.JPanel;
public class LeftArrowBubble extends JPanel {
private static final long serialVersionUID = -5389178141802153305L;
public LeftArrowBubble() {
this.setLayout(new BoxLayout(this,BoxLayout.PAGE_AXIS));
}
@Override
protected void paintComponent(final Graphics g) {
final Graphics2D graphics2D = (Graphics2D) g;
RenderingHints qualityHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
qualityHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
graphics2D.setRenderingHints(qualityHints);
graphics2D.setPaint(new Color(80, 150, 180));
int width = getWidth();
int height = getHeight();
GeneralPath path = new GeneralPath();
path.moveTo(5, 10);
path.curveTo(5, 10, 7, 5, 0, 0);
path.curveTo(0, 0, 12, 0, 12, 5);
path.curveTo(12, 5, 12, 0, 20, 0);
path.lineTo(width - 10, 0);
path.curveTo(width - 10, 0, width, 0, width, 10);
path.lineTo(width, height - 10);
path.curveTo(width, height - 10, width, height, width - 10, height);
path.lineTo(15, height);
path.curveTo(15, height, 5, height, 5, height - 10);
path.lineTo(5, 15);
path.closePath();
graphics2D.fill(path);
}
}
1 ответ
Если вы разбиваете слова, которые являются слишком длинными, добавляя пробелы, я думаю, что большинство ваших проблем решены. Некоторые небольшие изменения в размерах leftArrowBubble
а также tac
компоненты также будут полезны.
Вы можете заменить следующие строки в append
метод:
leftArrowBubble.setMaximumSize(new Dimension(400,350));
JLabel tac = new JLabel();
tac.setMaximumSize(new Dimension(350,400));
//tac.setPreferredSize(new Dimension(350,50)); //<----------
System.out.println(str);
tac.setText("<html><body style='width:350px;padding:15px;display:block;'>"
+ str + "</body></html>");
с помощью следующего кода (вы также можете взглянуть на разделенную строку на подстроки равной длины в Java, чтобы найти больше способов разбить строку на равные части):
leftArrowBubble.setMaximumSize(new Dimension(500, 500));
JLabel tac = new JLabel();
tac.setMaximumSize(new Dimension(450, 450));
//tac.setPreferredSize(new Dimension(350, 50)); //<----------
final int maximumSize = 56;
String textWithSeparators = "";
final StringTokenizer textTokenizer
= new StringTokenizer(str, " \t\n\r", true);
while (textTokenizer.hasMoreTokens()) {
final String part = textTokenizer.nextToken();
for (int beginIndex = 0; beginIndex < part.length();
beginIndex += maximumSize)
textWithSeparators += (beginIndex == 0 ? "" : " ")
+ part.substring(beginIndex,
Math.min(part.length(),
beginIndex + maximumSize));
}
System.out.println(textWithSeparators);
tac.setText("<html><body style='width:350px;padding:15px;display:block;'>"
+ textWithSeparators + "</body></html>");
Значение для maximumSize
может быть рассчитан с использованием метрик шрифта (см. Как получить правильную ширину строки из FontMetrics в JAVA для получения дополнительной информации), но я использовал здесь фиксированное значение для простоты.
Было бы неплохо связать размеры leftArrowBubble
, tac
и ширина в HTML-строке, например:
final int size = 500;
leftArrowBubble.setMaximumSize(new Dimension(size, size));
JLabel tac = new JLabel();
tac.setMaximumSize(new Dimension(size - 50, size - 50));
// [...]
tac.setText("<html><body style='width:" + (size - 150)
+ "px;padding:15px;display:block;'>"
+ textWithSeparators + "</body></html>");