Codename One:自定义SpanToggleCheckBox无文本显示及多行切换按钮实现
Hey there! Let's figure out why your SpanToggleCheckBox isn't showing any text and fix it with practical solutions.
What's Wrong with Your Current Code?
Looking at your snippet, there are a few key issues causing the missing text:
- You didn't add the TextArea to the component tree: You created a
textAreainstance, but never added it to theSpanToggleCheckBoxitself withadd(textArea). Without this, the TextArea doesn't get rendered at all. - CheckBox's default layout doesn't support extra components: CheckBox uses a built-in layout designed for an icon + single-line text label. Shoving a TextArea into it without adjusting the layout will either break the layout or make the TextArea invisible.
- You bypassed CheckBox's native text handling: CheckBox has its own
setText()and text rendering logic, but you ignored that entirely. Your code doesn't sync the TextArea with the CheckBox's state or disable the default text drawing.
Solution 1: Custom Paint for Multi-Line Text (Lightweight & Recommended)
If you just need to display multi-line text (not edit it), the simplest approach is to override the CheckBox's painting logic to draw multiple lines. This keeps all native CheckBox behavior intact while fixing the text display.
import javax.swing.*; import java.awt.*; public class MultiLineToggleCheckBox extends JCheckBox { private String multiLineText; public MultiLineToggleCheckBox(String text) { super(); this.multiLineText = text; setPreferredSize(calculatePreferredSize()); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); // Calculate starting position for text (account for icon and insets) Icon icon = getIcon(); int iconOffset = icon != null ? icon.getIconWidth() + getIconTextGap() : 0; int x = getInsets().left + iconOffset; int y = getInsets().top + g.getFontMetrics().getAscent(); // Draw each line of text Graphics2D g2d = (Graphics2D) g.create(); for (String line : multiLineText.split("\n")) { g2d.drawString(line, x, y); y += g2d.getFontMetrics().getHeight(); } g2d.dispose(); } // Calculate the right size to fit all text lines private Dimension calculatePreferredSize() { FontMetrics fm = getFontMetrics(getFont()); String[] lines = multiLineText.split("\n"); int maxLineWidth = lines.stream().mapToInt(fm::stringWidth).max().orElse(0); Icon icon = getIcon(); int totalWidth = maxLineWidth + (icon != null ? icon.getIconWidth() + getIconTextGap() : 0) + getInsets().left + getInsets().right; int totalHeight = lines.length * fm.getHeight() + getInsets().top + getInsets().bottom; return new Dimension(totalWidth, totalHeight); } // Helper methods to update text public void setMultiLineText(String text) { this.multiLineText = text; setPreferredSize(calculatePreferredSize()); repaint(); } public String getMultiLineText() { return multiLineText; } }
Solution 2: Replace CheckBox's Label with a TextArea (Supports Editing)
If you need the text to be editable or want more control over text formatting, replace the CheckBox's default label with a JTextArea (or JTextPane for rich text). This requires adjusting the layout to fit the TextArea properly.
import javax.swing.*; import java.awt.*; public class SpanToggleCheckBox extends JCheckBox { private JTextArea textArea; public SpanToggleCheckBox(String text) { super(); // Remove the default single-line label setText(null); // Configure the TextArea textArea = new JTextArea(text); textArea.setEditable(false); // Set to true if you want editable text textArea.setOpaque(false); // Match CheckBox's background textArea.setLineWrap(true); textArea.setWrapStyleWord(true); // Set up a layout to align icon and TextArea setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS)); Icon icon = getIcon(); if (icon != null) { add(new JLabel(icon)); add(Box.createHorizontalStrut(getIconTextGap())); } add(textArea); add(Box.createHorizontalGlue()); // Push content to the left // Sync selection state with text color (optional) addChangeListener(e -> { textArea.setForeground(isSelected() ? getSelectedTextColor() : getForeground()); }); } // Override setText/getText to work with the TextArea @Override public void setText(String text) { textArea.setText(text); } @Override public String getText() { return textArea.getText(); } }
Which Solution Should You Use?
- Go with Solution 1 if you just need to display static multi-line text. It's lightweight, maintains all native CheckBox functionality (like keyboard shortcuts, focus states), and is easy to maintain.
- Choose Solution 2 if you need editable text, rich formatting, or more control over the text component's behavior.
内容的提问来源于stack exchange,提问作者Francesco Galgani

