您好可以在titledBorder的标题中放置一个图标,例如以下代码:
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.TitledBorder;
public class TitledExample extends JPanel {
public TitledExample() {
super(true);
this.setLayout(new GridLayout(1, 1, 5, 5));
JLabel label = new JLabel("Titled Border");
label.setHorizontalAlignment(JLabel.CENTER);
TitledBorder titled = new TitledBorder("Image here ?? Title");
label.setBorder(titled);
add(label);
}
谢谢,干杯
答案 0 :(得分:9)
尝试继承TitledBorder
,并覆盖paintBorder
方法:
@Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height)
{
super.paintBorder(c, g, x, y, width, height);
// Now use the graphics context to draw whatever needed
g.drawImage(img, xImageOffset, yImageOffset, imgWidth, imgHeight, observer);
}
不是非常确定这是完全正确的方法调用,但你明白了;一旦您可以访问Graphics
对象,就可以绘制任何您需要的内容。
答案 1 :(得分:6)
这可能不是你想要的,但也许是一个不错的Unicode™ glyph或两个。
附录:@rhu's approach更可取,但我无法抗拒尝试:
TitledBorder titled = BorderFactory.createTitledBorder("\u2615");
titled.setTitleFont(new Font(Font.Dialog, Font.PLAIN, 32));
titled.setTitleColor(Color.blue);
label.setBorder(titled);
答案 2 :(得分:3)
您可以使用反射来访问TitledBorder使用的JLabel。
try
{
// Get the field declaration
Field f = TitledBorder.class.getDeclaredField("label");
// Make it accessible (it normally is private)
f.setAccessible(true);
// Get the label
JLabel borderLabel = (JLabel)f.get(titledBorder);
// Put the field accessibility back to default
f.setAccessible(false);
// Set the icon and do whatever you want with your label
borderLabel.setIcon(myIcon);
}
catch(Exception e)
{
e.printStackTrace();
}
重要的是要注意,这在Java 10中不起作用,因为它将对setAccessible
的使用有更严格的规则
答案 3 :(得分:1)
另一种方法是使用html格式。
使用img
组件使图形可视化。
这是一个完整的示例:
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import javax.swing.border.TitledBorder;
public class TitledBorderIcon {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
// Setup GUI
JFrame mdi = new JFrame("Test Titled Border with Icon");
mdi.setSize(600, 400);
mdi.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JLabel label = new JLabel("My Component");
label.setHorizontalAlignment(JLabel.CENTER);
mdi.add(label);
// Build the html formatted text
StringBuilder sb = new StringBuilder();
sb.append("<html>");
sb.append("<img src=\"https://via.placeholder.com/24/007AAE/\">");
sb.append(" My Title");
sb.append("</html>");
TitledBorder titled = new TitledBorder(sb.toString());
label.setBorder(titled);
mdi.setVisible(true);
});
}
}
答案 4 :(得分:0)
TitledBorder使用JLabel在边框上绘制文本。不幸的是,JLabel是一个私人领域。您可以通过两种方式添加图标:
访问私人JLabel字段,并在JLabel上设置图标。
子类TitledBorder并重新实现paintBorder方法。我&#39; d
可能还会添加一个带有JLabel的构造函数,这样就可以了
控制边框上画的东西。
答案 5 :(得分:0)
TitledBorder
复制到您的类路径和根据需要自定义它:例如:
public class IconTitleBorderFactory {
public static Border create(Consumer<JLabel> leftLabelDecorator, Consumer<JLabel> rightLabelDecorator) {
CustomTitledBorder border = new CustomTitledBorder(" ");
border.getLabel().setHorizontalTextPosition(SwingConstants.LEFT);
leftLabelDecorator.accept(border.getLabel());
CustomTitledBorder border2 = new CustomTitledBorder(" ");
border2.setTitleJustification(TitledBorder.RIGHT);
rightLabelDecorator.accept(border2.getLabel());
border.setBorder(border2);
return border;
}
private static class CustomTitledBorder extends AbstractBorder {
protected String title;
protected Border border;
protected int titlePosition;
protected int titleJustification;
protected Font titleFont;
protected Color titleColor;
private final JLabel label;
/**
* Use the default vertical orientation for the title text.
*/
static public final int DEFAULT_POSITION = 0;
/** Position the title above the border's top line. */
static public final int ABOVE_TOP = 1;
/** Position the title in the middle of the border's top line. */
static public final int TOP = 2;
/** Position the title below the border's top line. */
static public final int BELOW_TOP = 3;
/** Position the title above the border's bottom line. */
static public final int ABOVE_BOTTOM = 4;
/** Position the title in the middle of the border's bottom line. */
static public final int BOTTOM = 5;
/** Position the title below the border's bottom line. */
static public final int BELOW_BOTTOM = 6;
/**
* Use the default justification for the title text.
*/
static public final int DEFAULT_JUSTIFICATION = 0;
/** Position title text at the left side of the border line. */
static public final int LEFT = 1;
/** Position title text in the center of the border line. */
static public final int CENTER = 2;
/** Position title text at the right side of the border line. */
static public final int RIGHT = 3;
/**
* Position title text at the left side of the border line for left to right
* orientation, at the right side of the border line for right to left
* orientation.
*/
static public final int LEADING = 4;
/**
* Position title text at the right side of the border line for left to right
* orientation, at the left side of the border line for right to left
* orientation.
*/
static public final int TRAILING = 5;
// Space between the border and the component's edge
static protected final int EDGE_SPACING = 2;
// Space between the border and text
static protected final int TEXT_SPACING = 2;
// Horizontal inset of text that is left or right justified
static protected final int TEXT_INSET_H = 5;
/**
* Creates a TitledBorder instance.
*
* @param title the title the border should display
*/
public CustomTitledBorder(String title) {
this(null, title, LEADING, DEFAULT_POSITION, null, null);
}
/**
* Creates a TitledBorder instance with the specified border and an empty title.
*
* @param border the border
*/
public CustomTitledBorder(Border border) {
this(border, "", LEADING, DEFAULT_POSITION, null, null);
}
/**
* Creates a TitledBorder instance with the specified border and title.
*
* @param border the border
* @param title the title the border should display
*/
public CustomTitledBorder(Border border, String title) {
this(border, title, LEADING, DEFAULT_POSITION, null, null);
}
/**
* Creates a TitledBorder instance with the specified border, title,
* title-justification, and title-position.
*
* @param border the border
* @param title the title the border should display
* @param titleJustification the justification for the title
* @param titlePosition the position for the title
*/
public CustomTitledBorder(Border border, String title, int titleJustification, int titlePosition) {
this(border, title, titleJustification, titlePosition, null, null);
}
/**
* Creates a TitledBorder instance with the specified border, title,
* title-justification, title-position, and title-font.
*
* @param border the border
* @param title the title the border should display
* @param titleJustification the justification for the title
* @param titlePosition the position for the title
* @param titleFont the font for rendering the title
*/
public CustomTitledBorder(Border border, String title, int titleJustification, int titlePosition, Font titleFont) {
this(border, title, titleJustification, titlePosition, titleFont, null);
}
/**
* Creates a TitledBorder instance with the specified border, title,
* title-justification, title-position, title-font, and title-color.
*
* @param border the border
* @param title the title the border should display
* @param titleJustification the justification for the title
* @param titlePosition the position for the title
* @param titleFont the font of the title
* @param titleColor the color of the title
*/
@ConstructorProperties({ "border", "title", "titleJustification", "titlePosition", "titleFont", "titleColor" })
public CustomTitledBorder(Border border, String title, int titleJustification, int titlePosition, Font titleFont,
Color titleColor) {
this.title = title;
this.border = border;
this.titleFont = titleFont;
this.titleColor = titleColor;
setTitleJustification(titleJustification);
setTitlePosition(titlePosition);
this.label = new JLabel();
this.label.setOpaque(false);
this.label.putClientProperty(BasicHTML.propertyKey, null);
}
public JLabel getLabel() {
return label;
}
/**
* Paints the border for the specified component with the specified position and
* size.
*
* @param c the component for which this border is being painted
* @param g the paint graphics
* @param x the x position of the painted border
* @param y the y position of the painted border
* @param width the width of the painted border
* @param height the height of the painted border
*/
@Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
Border border = getBorder();
String title = getTitle();
if ((title != null) && !title.isEmpty()) {
int edge = (border instanceof CustomTitledBorder) ? 0 : EDGE_SPACING;
JLabel label = getLabel(c);
Dimension size = label.getPreferredSize();
Insets insets = getBorderInsets(border, c, new Insets(0, 0, 0, 0));
int borderX = x + edge;
int borderY = y + edge;
int borderW = width - edge - edge;
int borderH = height - edge - edge;
int labelY = y;
int labelH = size.height;
int position = getPosition();
switch (position) {
case ABOVE_TOP:
insets.left = 0;
insets.right = 0;
borderY += labelH - edge;
borderH -= labelH - edge;
break;
case TOP:
insets.top = edge + insets.top / 2 - labelH / 2;
if (insets.top < edge) {
borderY -= insets.top;
borderH += insets.top;
} else {
labelY += insets.top;
}
break;
case BELOW_TOP:
labelY += insets.top + edge;
break;
case ABOVE_BOTTOM:
labelY += height - labelH - insets.bottom - edge;
break;
case BOTTOM:
labelY += height - labelH;
insets.bottom = edge + (insets.bottom - labelH) / 2;
if (insets.bottom < edge) {
borderH += insets.bottom;
} else {
labelY -= insets.bottom;
}
break;
case BELOW_BOTTOM:
insets.left = 0;
insets.right = 0;
labelY += height - labelH;
borderH -= labelH - edge;
break;
}
insets.left += edge + TEXT_INSET_H;
insets.right += edge + TEXT_INSET_H;
int labelX = x;
int labelW = width - insets.left - insets.right;
if (labelW > size.width) {
labelW = size.width;
}
switch (getJustification(c)) {
case LEFT:
labelX += insets.left;
break;
case RIGHT:
labelX += width - insets.right - labelW;
break;
case CENTER:
labelX += (width - labelW) / 2;
break;
}
if (border != null) {
if ((position != TOP) && (position != BOTTOM)) {
border.paintBorder(c, g, borderX, borderY, borderW, borderH);
} else {
Graphics g2 = g.create();
if (g2 instanceof Graphics2D) {
Graphics2D g2d = (Graphics2D) g2;
Path2D path = new Path2D.Float();
path.append(new Rectangle(borderX, borderY, borderW, labelY - borderY), false);
path.append(new Rectangle(borderX, labelY, labelX - borderX - TEXT_SPACING, labelH), false);
path.append(new Rectangle(labelX + labelW + TEXT_SPACING, labelY,
borderX - labelX + borderW - labelW - TEXT_SPACING, labelH), false);
path.append(new Rectangle(borderX, labelY + labelH, borderW,
borderY - labelY + borderH - labelH), false);
g2d.clip(path);
}
border.paintBorder(c, g2, borderX, borderY, borderW, borderH);
g2.dispose();
}
}
g.translate(labelX, labelY);
label.setSize(labelW, labelH);
label.paint(g);
g.translate(-labelX, -labelY);
} else if (border != null) {
border.paintBorder(c, g, x, y, width, height);
}
}
/**
* Reinitialize the insets parameter with this Border's current Insets.
*
* @param c the component for which this border insets value applies
* @param insets the object to be reinitialized
*/
@Override
public Insets getBorderInsets(Component c, Insets insets) {
Border border = getBorder();
insets = getBorderInsets(border, c, insets);
String title = getTitle();
if ((title != null) && !title.isEmpty()) {
int edge = (border instanceof CustomTitledBorder) ? 0 : EDGE_SPACING;
JLabel label = getLabel(c);
Dimension size = label.getPreferredSize();
switch (getPosition()) {
case ABOVE_TOP:
insets.top += size.height - edge;
break;
case TOP: {
if (insets.top < size.height) {
insets.top = size.height - edge;
}
break;
}
case BELOW_TOP:
insets.top += size.height;
break;
case ABOVE_BOTTOM:
insets.bottom += size.height;
break;
case BOTTOM: {
if (insets.bottom < size.height) {
insets.bottom = size.height - edge;
}
break;
}
case BELOW_BOTTOM:
insets.bottom += size.height - edge;
break;
}
insets.top += edge + TEXT_SPACING;
insets.left += edge + TEXT_SPACING;
insets.right += edge + TEXT_SPACING;
insets.bottom += edge + TEXT_SPACING;
}
return insets;
}
/**
* Returns whether or not the border is opaque.
*/
@Override
public boolean isBorderOpaque() {
return false;
}
/**
* Returns the title of the titled border.
*
* @return the title of the titled border
*/
public String getTitle() {
return title;
}
/**
* Returns the border of the titled border.
*
* @return the border of the titled border
*/
public Border getBorder() {
return border != null ? border : UIManager.getBorder("TitledBorder.border");
}
/**
* Returns the title-position of the titled border.
*
* @return the title-position of the titled border
*/
public int getTitlePosition() {
return titlePosition;
}
/**
* Returns the title-justification of the titled border.
*
* @return the title-justification of the titled border
*/
public int getTitleJustification() {
return titleJustification;
}
/**
* Returns the title-font of the titled border.
*
* @return the title-font of the titled border
*/
public Font getTitleFont() {
return titleFont == null ? UIManager.getFont("TitledBorder.font") : titleFont;
}
/**
* Returns the title-color of the titled border.
*
* @return the title-color of the titled border
*/
public Color getTitleColor() {
return titleColor == null ? UIManager.getColor("TitledBorder.titleColor") : titleColor;
}
// REMIND(aim): remove all or some of these set methods?
/**
* Sets the title of the titled border.
*
* @param title the title for the border
*/
public void setTitle(String title) {
this.title = title;
}
/**
* Sets the border of the titled border.
*
* @param border the border
*/
public void setBorder(Border border) {
this.border = border;
}
/**
* Sets the title-position of the titled border.
*
* @param titlePosition the position for the border
*/
public void setTitlePosition(int titlePosition) {
switch (titlePosition) {
case ABOVE_TOP:
case TOP:
case BELOW_TOP:
case ABOVE_BOTTOM:
case BOTTOM:
case BELOW_BOTTOM:
case DEFAULT_POSITION:
this.titlePosition = titlePosition;
break;
default:
throw new IllegalArgumentException(titlePosition + " is not a valid title position.");
}
}
/**
* Sets the title-justification of the titled border.
*
* @param titleJustification the justification for the border
*/
public void setTitleJustification(int titleJustification) {
switch (titleJustification) {
case DEFAULT_JUSTIFICATION:
case LEFT:
case CENTER:
case RIGHT:
case LEADING:
case TRAILING:
this.titleJustification = titleJustification;
break;
default:
throw new IllegalArgumentException(titleJustification + " is not a valid title justification.");
}
}
/**
* Sets the title-font of the titled border.
*
* @param titleFont the font for the border title
*/
public void setTitleFont(Font titleFont) {
this.titleFont = titleFont;
}
/**
* Sets the title-color of the titled border.
*
* @param titleColor the color for the border title
*/
public void setTitleColor(Color titleColor) {
this.titleColor = titleColor;
}
/**
* Returns the minimum dimensions this border requires in order to fully display
* the border and title.
*
* @param c the component where this border will be drawn
* @return the {@code Dimension} object
*/
public Dimension getMinimumSize(Component c) {
Insets insets = getBorderInsets(c);
Dimension minSize = new Dimension(insets.right + insets.left, insets.top + insets.bottom);
String title = getTitle();
if ((title != null) && !title.isEmpty()) {
JLabel label = getLabel(c);
Dimension size = label.getPreferredSize();
int position = getPosition();
if ((position != ABOVE_TOP) && (position != BELOW_BOTTOM)) {
minSize.width += size.width;
} else if (minSize.width < size.width) {
minSize.width += size.width;
}
}
return minSize;
}
/**
* Returns the baseline.
*
* @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
* @see javax.swing.JComponent#getBaseline(int, int)
* @since 1.6
*/
@Override
public int getBaseline(Component c, int width, int height) {
if (c == null) {
throw new NullPointerException("Must supply non-null component");
}
if (width < 0) {
throw new IllegalArgumentException("Width must be >= 0");
}
if (height < 0) {
throw new IllegalArgumentException("Height must be >= 0");
}
Border border = getBorder();
String title = getTitle();
if ((title != null) && !title.isEmpty()) {
int edge = (border instanceof CustomTitledBorder) ? 0 : EDGE_SPACING;
JLabel label = getLabel(c);
Dimension size = label.getPreferredSize();
Insets insets = getBorderInsets(border, c, new Insets(0, 0, 0, 0));
int baseline = label.getBaseline(size.width, size.height);
switch (getPosition()) {
case ABOVE_TOP:
return baseline;
case TOP:
insets.top = edge + (insets.top - size.height) / 2;
return (insets.top < edge) ? baseline : baseline + insets.top;
case BELOW_TOP:
return baseline + insets.top + edge;
case ABOVE_BOTTOM:
return baseline + height - size.height - insets.bottom - edge;
case BOTTOM:
insets.bottom = edge + (insets.bottom - size.height) / 2;
return (insets.bottom < edge) ? baseline + height - size.height
: baseline + height - size.height + insets.bottom;
case BELOW_BOTTOM:
return baseline + height - size.height;
}
}
return -1;
}
/**
* Returns an enum indicating how the baseline of the border changes as the size
* changes.
*
* @throws NullPointerException {@inheritDoc}
* @see javax.swing.JComponent#getBaseline(int, int)
* @since 1.6
*/
@Override
public Component.BaselineResizeBehavior getBaselineResizeBehavior(Component c) {
super.getBaselineResizeBehavior(c);
switch (getPosition()) {
case CustomTitledBorder.ABOVE_TOP:
case CustomTitledBorder.TOP:
case CustomTitledBorder.BELOW_TOP:
return Component.BaselineResizeBehavior.CONSTANT_ASCENT;
case CustomTitledBorder.ABOVE_BOTTOM:
case CustomTitledBorder.BOTTOM:
case CustomTitledBorder.BELOW_BOTTOM:
return JComponent.BaselineResizeBehavior.CONSTANT_DESCENT;
}
return Component.BaselineResizeBehavior.OTHER;
}
private int getPosition() {
int position = getTitlePosition();
if (position != DEFAULT_POSITION) {
return position;
}
Object value = UIManager.get("TitledBorder.position");
if (value instanceof Integer) {
int i = (Integer) value;
if ((0 < i) && (i <= 6)) {
return i;
}
} else if (value instanceof String) {
String s = (String) value;
if (s.equalsIgnoreCase("ABOVE_TOP")) {
return ABOVE_TOP;
}
if (s.equalsIgnoreCase("TOP")) {
return TOP;
}
if (s.equalsIgnoreCase("BELOW_TOP")) {
return BELOW_TOP;
}
if (s.equalsIgnoreCase("ABOVE_BOTTOM")) {
return ABOVE_BOTTOM;
}
if (s.equalsIgnoreCase("BOTTOM")) {
return BOTTOM;
}
if (s.equalsIgnoreCase("BELOW_BOTTOM")) {
return BELOW_BOTTOM;
}
}
return TOP;
}
private int getJustification(Component c) {
int justification = getTitleJustification();
if ((justification == LEADING) || (justification == DEFAULT_JUSTIFICATION)) {
return c.getComponentOrientation().isLeftToRight() ? LEFT : RIGHT;
}
if (justification == TRAILING) {
return c.getComponentOrientation().isLeftToRight() ? RIGHT : LEFT;
}
return justification;
}
protected Font getFont(Component c) {
Font font = getTitleFont();
if (font != null) {
return font;
}
if (c != null) {
font = c.getFont();
if (font != null) {
return font;
}
}
return new Font(Font.DIALOG, Font.PLAIN, 12);
}
private Color getColor(Component c) {
Color color = getTitleColor();
if (color != null) {
return color;
}
return (c != null) ? c.getForeground() : null;
}
private JLabel getLabel(Component c) {
// this.label.setText(getTitle());
this.label.setFont(getFont(c));
this.label.setForeground(getColor(c));
this.label.setComponentOrientation(c.getComponentOrientation());
this.label.setEnabled(c.isEnabled());
return this.label;
}
private static Insets getBorderInsets(Border border, Component c, Insets insets) {
if (border == null) {
insets.set(0, 0, 0, 0);
} else if (border instanceof AbstractBorder) {
AbstractBorder ab = (AbstractBorder) border;
insets = ab.getBorderInsets(c, insets);
} else {
Insets i = border.getBorderInsets(c);
insets.set(i.top, i.left, i.bottom, i.right);
}
return insets;
}
}
}
那么:
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel container = new JPanel();
container.add(new JButton("A"));
container.setBorder(IconTitleBorderFactory.create(leftLabel -> {
leftLabel.setText("Information");
}, rightLabel -> {
rightLabel.setIcon(UIManager.getIcon("Tree.openIcon"));
}));
frame.setContentPane(container);
frame.pack();
frame.setSize(300, 300);
frame.setLocationByPlatform(true);
frame.setVisible(true);
});
}
产生:
注意:标签仅用于绘画。他们不在屏幕上。添加侦听器、工具提示或 getLocation()
对它们不起作用。