Ist es möglich, einen automatischen Zeilenumbruch von Texten in JButtons zu erreichen? Ich habe einige dynamische Schaltflächen, die ich zur Laufzeit erstelle. Ich möchte die Schaltflächen mit einem Wortumbruch versehen, damit ich bessere Tests auf den Schaltflächen sehen kann. Ist es möglich, dies zu tun?
Antworten
Zu viele Anzeigen?In diesem Beispiel werden die in Java eingebauten CSS-Rendering-Fähigkeiten genutzt, um zu bestimmen, wann ein Zeilenumbruch erforderlich ist, und um die "schwere Arbeit" zu erledigen. Es verwendet eine JLabel
aber die gleichen Grundsätze gelten für jede Komponente, die HTML wiedergibt.
FestgelegteBreiteText.java
import javax.swing.*;
class FixedWidthText {
public static void showLabel(int width, String units) {
String content1 = "<html>"
+ "<body style='background-color: white; width: ";
String content2 = "'>"
+ "<h1>Fixed Width</h1>"
+ "<p>Body width fixed at ";
String content3
= " using CSS. "
+ "Java's HTML"
+ " support includes support"
+ " for basic CSS.</p>";
final String content = content1 + width + units
+ content2 + width + units + content3;
Runnable r = () -> {
JLabel label = new JLabel(content);
JOptionPane.showMessageDialog(null, label);
};
SwingUtilities.invokeLater(r);
}
public static void main(String[] args) {
showLabel(160, "px");
showLabel(200, "px");
showLabel(50, "%");
}
}
Bildschirmfotos
160px
200px
50%
Am einfachsten ist es, eine andere Komponente, die den Zeilenumbruch unterstützt, so zu ändern, dass sie als Schaltfläche fungiert. Ich habe eine einfache Klasse erstellt, die JTextArea so manipuliert, dass sie als Schaltfläche fungiert.
public class MultiLineButton extends JTextArea implements MouseListener {
/**
*
*/
private static final long serialVersionUID = 1L;
private Color defaultColor;
private Color highlight, lightHighlight;
private BtnState state;
private List<ActionListener> actionListeners;
public MultiLineButton(String text, Color defaultColor) {
this.setEditable(false);
this.setText(text);
this.setLineWrap(true);
this.setWrapStyleWord(true);
this.addMouseListener(this);
this.setBorder(new EmptyBorder(5, 10, 5, 10));
state = BtnState.NORMAL;
this.defaultColor = defaultColor;
this.setBackground(defaultColor);
highlight = new Color(122, 138, 153);
lightHighlight = new Color(184, 207, 229);
// clickedColor = new Color(r, g, b);/
actionListeners = new ArrayList<>();
}
@Override
public Color getSelectionColor() {
return getBackground();
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
setBackground(lightHighlight);
state = BtnState.CLICKED;
repaint();
}
@Override
public void mouseReleased(MouseEvent e) {
for (ActionListener l : actionListeners) {
l.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, this.getText()));
}
setBackground(defaultColor);
state = BtnState.NORMAL;
repaint();
}
@Override
public void mouseEntered(MouseEvent e) {
state = BtnState.HOVERED;
repaint();
}
@Override
public void mouseExited(MouseEvent e) {
setBackground(defaultColor);
state = BtnState.NORMAL;
repaint();
}
@Override
public void paintBorder(Graphics g) {
super.paintBorder(g);
Graphics g2 = g.create();
g2.setColor(highlight);
switch (state) {
case NORMAL:
g2.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
break;
case HOVERED:
g2.drawRect(1, 1, getWidth() - 3, getHeight() - 3);
g2.setColor(lightHighlight);
g2.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
g2.drawRect(2, 2, getWidth() - 5, getHeight() - 5);
break;
case CLICKED:
Border b = new BevelBorder(BevelBorder.LOWERED);
b.paintBorder(this, g2, 0, 0, getWidth(), getHeight());
break;
}
g2.dispose();
}
public void addActionListener(ActionListener l) {
actionListeners.add(l);
}
public List<ActionListener> getActionListeners() {
return actionListeners;
}
}
BtnState ist einfach ein Enum mit den Konstanten NORMAL, HOVERED, CLICKED
Der meiste Code wird nur verwendet, um das JTextArea wie einen JButton aussehen zu lassen, und das funktioniert ganz gut. Ein Nachteil ist, dass Sie die Möglichkeit verlieren, es über ButtonModels zu modifizieren, aber für die meisten Anwendungen wird dies ausreichen.
@Override
public void paint(Graphics pGraphics)
{
super.paint(pGraphics);
Graphics2D g2d = (Graphics2D) pGraphics;
FontRenderContext frc = g2d.getFontRenderContext();
String itemName = item.getName();
AttributedString attributedString = new AttributedString(itemName);
attributedString.addAttribute(TextAttribute.FONT, getFont());
AttributedCharacterIterator iterator = attributedString.getIterator();
LineBreakMeasurer measurer = new LineBreakMeasurer(iterator, frc);
float wrappingWidth = getSize().width - 15;
StringBuilder stringBuilder = new StringBuilder("<html><center>");
int previousIndex = 0;
while (measurer.getPosition() < itemName.length())
{
if (previousIndex != 0) stringBuilder.append("<br>");
stringBuilder.append(itemName.substring(previousIndex, measurer.getPosition()));
previousIndex = measurer.getPosition();
measurer.nextLayout(wrappingWidth);
}
if (previousIndex < itemName.length())
{
if (previousIndex != 0) stringBuilder.append("<br>");
stringBuilder.append(itemName.substring(previousIndex));
}
stringBuilder.append("</center></html>");
setText(stringBuilder.toString());
}