Я знаю, что это старый вопрос.
Я подумал, что хотел бы воскресить его, потому что, возможно, кто-то знает, как решить эту проблему. У меня есть только «частичное решение».
Я очень быстро реализовал границу, которая делает то, что вы хотите. Я повторно использовал то, что дает Java, то есть интерпретацию HTML в компонентах Swing.
Все работает хорошо, граница нарисована отлично для простого текста или текста HTML, за исключением ситуации, когда вы пытаетесь иметь разные размеры шрифта для текстов.
Я не знаю, как решить эту проблему. Но я очень заинтересован в решении.
Я знаю, что процедура будет заключаться в суммировании ширины каждой строки в ее собственном размере шрифта при вычислении переменной textLengthInPixels.
Проблема в в том, что я не знаю, как его получить, может быть, из View, но не знаю, как?
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Rectangle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.AbstractBorder;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
import javax.swing.text.BadLocationException;
import javax.swing.text.View;
public class MultiColorTitleBorder extends AbstractBorder
{
private static final long serialVersionUID = 1L;
private JLabel label;
private int thicknessTop = 10;
private Border border;
private int thicknessLeft = 0;
private int thicknessRight = 0;
private int thicknessBottom = 0;
public MultiColorTitleBorder(String title)
{
this.label = new JLabel(title);
thicknessTop = label.getPreferredSize().height;
}
public MultiColorTitleBorder(String title, Border border)
{
this(title);
this.border = border;
thicknessLeft = border.getBorderInsets(null).left;
thicknessRight = border.getBorderInsets(null).right;
thicknessBottom = border.getBorderInsets(null).bottom;
}
@Override
public synchronized void paintBorder(Component c, Graphics g, int x, int y, int width, int height)
{
Graphics2D g2 = (Graphics2D) g;
View view = (View) label.getClientProperty("html");
String text = label.getText();
FontMetrics fm = g2.getFontMetrics(label.getFont());
int bY = y + fm.getAscent() - ((fm.getAscent() + fm.getDescent())) / 2;
if(border != null)
{
Insets in = border.getBorderInsets(c);
g2.setClip(x, y, thicknessLeft * 2, height);
border.paintBorder(c, g, x, bY, width, height - bY);
try
{
if(view != null)
text = view.getDocument().getText(0, view.getDocument().getLength());
}catch(BadLocationException ex)
{
Logger.getLogger(MultiColorTitleBorder.class.getName()).log(Level.SEVERE, null, ex);
}
int textLengthInPixels = fm.stringWidth(text);
System.out.println("textLengthInPixels=" + textLengthInPixels);
g2.setClip(x +thicknessLeft * 2+ textLengthInPixels, y, width - thicknessLeft * 2 -textLengthInPixels, height);
border.paintBorder(c, g, x, bY, width, height - bY);
int bottomIn = in.bottom;
g2.setClip(x, height - bottomIn, width, bottomIn);
border.paintBorder(c, g, x, bY, width, height - bY);
g2.setClip(x, y, width, height);
}
if(view != null)
view.paint(g2, new Rectangle(x + thicknessLeft * 2, y, width - thicknessLeft * 2, height));
else
{
Font prevFont = g2.getFont();
g2.setFont(label.getFont());
g2.drawString(text, x + thicknessLeft * 2, fm.getAscent());
g2.setFont(prevFont);
}
}
@Override
public Insets getBorderInsets(Component c)
{
return new Insets(thicknessTop, thicknessLeft, thicknessBottom, thicknessRight);
}
@Override
public Insets getBorderInsets(Component c, Insets insets)
{
insets.top = thicknessTop;
insets.left = thicknessLeft;
insets.right = thicknessRight;
insets.bottom = thicknessBottom;
return insets;
}
@Override
public boolean isBorderOpaque()
{
return false;
}
public static void main(String[] args)
{
JPanel p = new JPanel();
p.setPreferredSize(new Dimension(200, 200));
String title = "<html><color=red> Text 1</font><font color=blue> Text 2</font>";
//title = "<html><font color=red font size=5> Text 1</font><font color=blue> Text 2</font>";
//title = "Text 1 Text 2";
p.setBorder(new MultiColorTitleBorder(title, new LineBorder(Color.CYAN, 6)));
p.setBackground(Color.YELLOW);
p.add(new JTextField(5));
JPanel contentPane = new JPanel();
contentPane.add(p);
JFrame f = new JFrame();
f.setContentPane(contentPane);
f.setSize(800, 600);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}