Kombinierte TitledBorder kursiv/normal

sina.die

Mitglied
Hallo,

wie bekomme ich in einer TitledBorder ein Wort kursiv und alle anderen in normaler Schrift?
Mit HTML kriege ich es nicht hin und wenn ich eine Font übergebe, ist natürlich alles kursiv.

So sieht mein HTML-Versuch aus:
Java:
pnl.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(BevelBorder.LOWERED),
                        "<html>Mitarbeiter/<i>Gast</i></html>",
                        TitledBorder.LEADING, TitledBorder.TOP));

Danke im vorraus,
Sina
 

Marco13

Top Contributor
Bei dem Code aus der TitledBorder...
Code:
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
     ...
     g.setFont(getFont(c));
     ..
     SwingUtilities2.drawString(jc, g, getTitle(), textLoc.x, textLoc.y);
     ...
wird die Luft da ziemlich dünn...


Einer der übelsten Hacks, die ich je zusammengefrickelt habe:

(EDIT: Die original paintBorder-Methode, mit möglichst wenigen änderungen, damit's compiliert, und dem Italic-Ding drin .... ggf. sollte man sich für sowas lieber eine eigene Border-Klasse schreiben, 90% von dem Code sind für dich wahrscheinlich überflüssig....)

(EDIT2: Das solltest du so lieber NICHT verwenden.... :exclaim: )
Code:
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;


class BorderTest
{
    public static void main(String args[])
    {
        JFrame f = new JFrame();
        JPanel p = new JPanel();
        p.setBorder(new TestBorder(BorderFactory.createEtchedBorder(BevelBorder.LOWERED),
                        "Mitarbeiter/Gast"));
        f.add(p);
        f.pack();
        f.setVisible(true);
    }

}


class TestBorder extends TitledBorder
{
    public TestBorder(Border border, String title)
    {
        super(border, title);
    }

    public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {

        Border border = getBorder();
        Point textLoc = new Point();

        if (getTitle() == null || getTitle().equals("")) {
            if (border != null) {
                border.paintBorder(c, g, x, y, width, height);
            }
            return;
        }

        Rectangle grooveRect = new Rectangle(x + EDGE_SPACING, y + EDGE_SPACING,
                                             width - (EDGE_SPACING * 2),
                                             height - (EDGE_SPACING * 2));
        Font font = g.getFont();
        Color color = g.getColor();

        g.setFont(getFont(c));

        JComponent jc = (c instanceof JComponent) ? (JComponent)c : null;
        FontMetrics fm = g.getFontMetrics();
        int         fontHeight = fm.getHeight();
        int         descent = fm.getDescent();
        int         ascent = fm.getAscent();
        int         diff;
        int         stringWidth = fm.stringWidth(getTitle());
        Insets      insets;

        if (border != null) {
            insets = border.getBorderInsets(c);
        } else {
            insets = new Insets(0, 0, 0, 0);
        }

        int titlePos = getTitlePosition();
        switch (titlePos) {
            case ABOVE_TOP:
                diff = ascent + descent + (Math.max(EDGE_SPACING,
                                 TEXT_SPACING*2) - EDGE_SPACING);
                grooveRect.y += diff;
                grooveRect.height -= diff;
                textLoc.y = grooveRect.y - (descent + TEXT_SPACING);
                break;
            case TOP:
            case DEFAULT_POSITION:
                diff = Math.max(0, ((ascent/2) + TEXT_SPACING) - EDGE_SPACING);
                grooveRect.y += diff;
                grooveRect.height -= diff;
                textLoc.y = (grooveRect.y - descent) +
                (insets.top + ascent + descent)/2;
                break;
            case BELOW_TOP:
                textLoc.y = grooveRect.y + insets.top + ascent + TEXT_SPACING;
                break;
            case ABOVE_BOTTOM:
                textLoc.y = (grooveRect.y + grooveRect.height) -
                (insets.bottom + descent + TEXT_SPACING);
                break;
            case BOTTOM:
                grooveRect.height -= fontHeight/2;
                textLoc.y = ((grooveRect.y + grooveRect.height) - descent) +
                        ((ascent + descent) - insets.bottom)/2;
                break;
            case BELOW_BOTTOM:
                grooveRect.height -= fontHeight;
                textLoc.y = grooveRect.y + grooveRect.height + ascent +
                        TEXT_SPACING;
                break;
        }

    int justification = getTitleJustification();
    if(true){ // || isLeftToRight(c)) {
        if(justification==LEADING ||
           justification==DEFAULT_JUSTIFICATION) {
            justification = LEFT;
        }
        else if(justification==TRAILING) {
            justification = RIGHT;
        }
    }
    else {
        if(justification==LEADING ||
           justification==DEFAULT_JUSTIFICATION) {
            justification = RIGHT;
        }
        else if(justification==TRAILING) {
            justification = LEFT;
        }
    }

        switch (justification) {
            case LEFT:
                textLoc.x = grooveRect.x + TEXT_INSET_H + insets.left;
                break;
            case RIGHT:
                textLoc.x = (grooveRect.x + grooveRect.width) -
                        (stringWidth + TEXT_INSET_H + insets.right);
                break;
            case CENTER:
                textLoc.x = grooveRect.x +
                        ((grooveRect.width - stringWidth) / 2);
                break;
        }

        // If title is positioned in middle of border AND its fontsize
    // is greater than the border's thickness, we'll need to paint
    // the border in sections to leave space for the component's background
    // to show through the title.
        //
        if (border != null) {
            if (((titlePos == TOP || titlePos == DEFAULT_POSITION) &&
          (grooveRect.y > textLoc.y - ascent)) ||
         (titlePos == BOTTOM &&
          (grooveRect.y + grooveRect.height < textLoc.y + descent))) {

                Rectangle clipRect = new Rectangle();

                // save original clip
                Rectangle saveClip = g.getClipBounds();

                // paint strip left of text
                clipRect.setBounds(saveClip);
                if (computeIntersection(clipRect, x, y, textLoc.x-1-x, height)) {
                    g.setClip(clipRect);
                    border.paintBorder(c, g, grooveRect.x, grooveRect.y,
                                  grooveRect.width, grooveRect.height);
                }

                // paint strip right of text
                clipRect.setBounds(saveClip);
                if (computeIntersection(clipRect, textLoc.x+stringWidth+1, y,
                               x+width-(textLoc.x+stringWidth+1), height)) {
                    g.setClip(clipRect);
                    border.paintBorder(c, g, grooveRect.x, grooveRect.y,
                                  grooveRect.width, grooveRect.height);
                }

                if (titlePos == TOP || titlePos == DEFAULT_POSITION) {
                    // paint strip below text
                    clipRect.setBounds(saveClip);
                    if (computeIntersection(clipRect, textLoc.x-1, textLoc.y+descent,
                                        stringWidth+2, y+height-textLoc.y-descent)) {
                        g.setClip(clipRect);
                        border.paintBorder(c, g, grooveRect.x, grooveRect.y,
                                  grooveRect.width, grooveRect.height);
                    }

                } else { // titlePos == BOTTOM
          // paint strip above text
                    clipRect.setBounds(saveClip);
                    if (computeIntersection(clipRect, textLoc.x-1, y,
                          stringWidth+2, textLoc.y - ascent - y)) {
                        g.setClip(clipRect);
                        border.paintBorder(c, g, grooveRect.x, grooveRect.y,
                                  grooveRect.width, grooveRect.height);
                    }
                }

                // restore clip
                g.setClip(saveClip);

            } else {
                border.paintBorder(c, g, grooveRect.x, grooveRect.y,
                                  grooveRect.width, grooveRect.height);
            }
        }

        g.setColor(getTitleColor());


        String s[] = getTitle().split("/");
        int stringWidth0 = fm.stringWidth(s[0]);
        g.drawString(s[0], textLoc.x, textLoc.y);
        Font ft = getFont(c).deriveFont(Font.ITALIC | Font.BOLD);
        g.setFont(ft);
        g.drawString("/"+s[1], textLoc.x+stringWidth0, textLoc.y);


        g.setFont(font);
        g.setColor(color);
    }

    private static boolean computeIntersection(Rectangle dest,
                                               int rx, int ry, int rw, int rh) {
    int x1 = Math.max(rx, dest.x);
    int x2 = Math.min(rx + rw, dest.x + dest.width);
    int y1 = Math.max(ry, dest.y);
    int y2 = Math.min(ry + rh, dest.y + dest.height);
        dest.x = x1;
        dest.y = y1;
        dest.width = x2 - x1;
        dest.height = y2 - y1;

    if (dest.width <= 0 || dest.height <= 0) {
        return false;
    }
        return true;
    }

}

(dass die Leute auch immer so Sonderwünsche haben müssen :noe: ;) )
 
Zuletzt bearbeitet:

Ebenius

Top Contributor
EDIT: Schade, der Ansatz der eben hier stand funktioniert nicht gegen jeden LayoutManager. :-(

Ich versuch's dann nochmal.

Ebenius
 
Zuletzt bearbeitet:

Ebenius

Top Contributor
Da will man nur mal eben den Ansatz zu Ende denken, und schon kommt sowas dabei raus ...

Anhang anzeigen 1133

Hier eine Border-Implementation die den TitledBorder nachbastelt, aber ein JLabel für die Darstelling benutzt. Achtung: Der Border macht absichtlich kein Line-Wrapping, weil das mit Borders nicht funktioniert. Der Border braucht statische Größeneinschübe.

Java:
/* $Id$ */

/* Copyright 2010 Sebastian Haufe

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       [url]http://www.apache.org/licenses/LICENSE-2.0[/url]

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License. */

package com.ebenius;

import java.awt.*;

import javax.swing.JLabel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.AbstractBorder;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;

/**
 * A titled Border instance capable of showing HTML (uses a {@link JLabel} as
 * renderer). This implementation behaves as the {@link TitledBorder} does,
 * but provides nothing but the {@link TitledBorder#TOP TOP title placement}.
 * <p>
 * Note: This border never does line-wrapping, as borders need static border
 * insets which conflicts with danymic line wrapping.
 * 
 * @version $Revision$ as of $Date$
 * @author Sebastian Haufe
 */
public class HTMLTitledBorder extends AbstractBorder
  implements java.io.Serializable {

  /** Serial version UID */
  private static final long serialVersionUID = 1L;

  /* same setup as the titled border */

  // 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;

  // -------------------------------------------------------------------------
  // Inner classes
  // -------------------------------------------------------------------------

  /**
   * Evil JLable derivate, faking a parent. We do not really add the label to
   * a parent, as the parent's layout manager might dislike an additional
   * child.
   */
  private static class EvilJLabel extends JLabel {

    /** Serial version UID */
    private static final long serialVersionUID = 1L;
    private transient Container parent;

    /** Creates a new {@code HTMLTitledBorder.EvilJLabel}. */
    EvilJLabel() {}

    void setParent(Container parent) {
      final Container oldParent = this.parent;
      if (oldParent != parent) {
        this.parent = null;
        if (oldParent != null) {
          this.removeNotify();
        }
        this.parent = parent;
        if (parent != null) {
          this.addNotify();
        }
      }
    }

    @Override
    public Container getParent() {
      return parent;
    }
  }

  // -------------------------------------------------------------------------
  // Instance fields
  // -------------------------------------------------------------------------

  private transient EvilJLabel label;
  private Border border;
  private String title;
  private int titleJustification = SwingConstants.LEFT;

  // -------------------------------------------------------------------------
  // Constructors
  // -------------------------------------------------------------------------

  /**
   * Creates a new {@code HTMLTitledBorder}.
   * 
   * @param title the border title, as interpreted by the {@link JLabel} class
   */
  public HTMLTitledBorder(String title) {
    setTitle(title);
  }

  /**
   * Creates a new {@code HTMLTitledBorder}.
   * 
   * @param border this titled border's border
   * @param title the border title, as interpreted by the {@link JLabel} class
   */
  public HTMLTitledBorder(Border border, String title) {
    this(title);
    this.border = border;
  }

  // ------------------------------------------------------------------------
  // Implementing java.awt.Border
  // -------------------------------------------------------------------------

  @Override
  public Insets getBorderInsets(Component c) {
    return getBorderInsets(c, new Insets(0, 0, 0, 0));
  }

  @Override
  public Insets getBorderInsets(Component c, Insets insets) {
    Border border = getBorder();
    if (border != null) {
      if (border instanceof AbstractBorder) {
        ((AbstractBorder) border).getBorderInsets(c, insets);
      } else {
        final Insets i = border.getBorderInsets(c);
        insets.top = i.top;
        insets.right = i.right;
        insets.bottom = i.bottom;
        insets.left = i.left;
      }
    } else {
      insets.left = insets.top = insets.right = insets.bottom = 0;
    }

    if (getTitle() == null || getTitle().equals("")) {
      return insets;
    }

    final EvilJLabel label = getLabel();
    final Dimension prefSize = label.getPreferredSize();
    final int labelHeight = prefSize.height;
    insets.top = Math.max(labelHeight, insets.top);

    insets.left += EDGE_SPACING + TEXT_SPACING;
    insets.right += EDGE_SPACING + TEXT_SPACING;
    insets.top += EDGE_SPACING + TEXT_SPACING;
    insets.bottom += EDGE_SPACING + TEXT_SPACING;

    return insets;
  }

  @Override
  public void paintBorder(
        Component c,
        Graphics g,
        int x,
        int y,
        int width,
        int height) {

    final Border border = getBorder();

    // no title? okay, so just the border
    if (getTitle() == null || getTitle().equals("")) {
      if (border != null) {
        border.paintBorder(c, g, x, y, width, height);
      }
      return;
    }

    // get the evil label
    final EvilJLabel label = getLabel();
    final Dimension labelPrefSize = label.getPreferredSize();
    final int labelPrefHeight = labelPrefSize.height;
    final int labelPrefWidth = labelPrefSize.width;

    // place the whole border bounds
    x += EDGE_SPACING;
    y += EDGE_SPACING;
    width -= EDGE_SPACING * 2;
    height -= EDGE_SPACING * 2;

    // place the label bounds
    final Rectangle labelBounds = new Rectangle();
    labelBounds.x = x + TEXT_INSET_H;
    labelBounds.y = y;
    labelBounds.width = width - 2 * TEXT_INSET_H;
    labelBounds.height = labelPrefHeight + TEXT_SPACING;

    // move the label according to slave border insets
    if (border != null) {
      final Insets borderInsets = border.getBorderInsets(c);
      labelBounds.x += borderInsets.left;
      labelBounds.width -= borderInsets.left + borderInsets.right;

      if (borderInsets.top >= labelBounds.height) {
        labelBounds.y += (borderInsets.top - labelBounds.height) / 2;
      } else {
        final int diff = (labelBounds.height - borderInsets.top) / 2;
        y += diff;
        height -= diff;
      }
    }

    // place the label according to alignment
    final boolean ltr = c.getComponentOrientation().isLeftToRight();
    switch (getAbsoluteTitleAlignment(ltr)) {
    case SwingConstants.LEFT:
      break;
    case SwingConstants.CENTER:
      labelBounds.x += (labelBounds.width - labelPrefWidth) / 2;
      break;
    case SwingConstants.RIGHT:
      labelBounds.x += labelBounds.width - labelPrefWidth;
      break;
    }
    labelBounds.width = Math.min(labelPrefWidth, labelBounds.width);

    // paint slave border in three strips
    g = g.create();
    try {
      final Rectangle orgClip = g.getClipBounds();
      final Rectangle clipRect = new Rectangle(orgClip);
      if (border != null) {
        // left of text
        final int split0 = labelBounds.x - TEXT_SPACING;
        if (intersect(clipRect, x, y, split0 - 1, height)) {
          g.setClip(clipRect);
          border.paintBorder(c, g, x, y, width, height);
        }

        // right of text
        clipRect.setBounds(orgClip.getBounds());
        final int split1 = split0 + labelBounds.width + 2 * TEXT_SPACING;
        if (intersect(clipRect, split1, y, width - split1 + x, height)) {
          g.setClip(clipRect);
          border.paintBorder(c, g, x, y, width, height);
        }

        // below text
        clipRect.setBounds(orgClip);
        if (intersect(clipRect, x + split0 - 1, labelBounds.y
              + labelBounds.height, split1 - split0 - 1, y
              + height
              - labelBounds.y
              - labelBounds.height)) {
          g.setClip(clipRect);
          border.paintBorder(c, g, x, y, width, height);
        }
      }

      // paint the evil label
      label.setParent(c.getParent()); // need any valid parent
      label.validate();
      clipRect.setBounds(orgClip);
      if (intersect(clipRect, labelBounds.x, labelBounds.y,
            labelBounds.width, labelBounds.height)) {
        labelBounds.width = Integer.MAX_VALUE; // never line-wrap :-)
        label.setBounds(labelBounds);
        g.setClip(clipRect);
        g.translate(labelBounds.x, labelBounds.y);
        label.paint(g);
      }
    } finally {
      label.setParent(null);
      g.dispose(); // we created a copy, so this is okay!
    }
  }

  // -------------------------------------------------------------------------
  // private helper methods
  // -------------------------------------------------------------------------

  private int getAbsoluteTitleAlignment(boolean ltr) {
    // make the alignment absolute
    final int align;
    switch (titleJustification) {
    case SwingConstants.LEADING:
      align = ltr ? SwingConstants.LEFT : SwingConstants.RIGHT;
      break;
    case SwingConstants.TRAILING:
      align = ltr ? SwingConstants.RIGHT : SwingConstants.LEFT;
      break;
    default:
      align = titleJustification;
    }

    return align;
  }

  private EvilJLabel getLabel() {
    if (label == null) {
      label = new EvilJLabel();
      label.setBackground(new Color(255, 0, 0, 127));
      label.setOpaque(false);
      label.setVerticalAlignment(SwingConstants.TOP);
    }
    label.setText(title);
    return label;
  }

  private static boolean intersect(
        Rectangle target,
        int rect2X,
        int rect2Y,
        int rect2Width,
        int rect2Height) {
    final int x1 = Math.max(rect2X, target.x);
    final int x2 = Math.min(rect2X + rect2Width, target.x + target.width);
    final int y1 = Math.max(rect2Y, target.y);
    final int y2 = Math.min(rect2Y + rect2Height, target.y + target.height);
    target.x = x1;
    target.y = y1;
    target.width = x2 - x1;
    target.height = y2 - y1;

    return target.width > 0 && target.height > 0;
  }

  // -------------------------------------------------------------------------
  // Bean getters and setters
  // -------------------------------------------------------------------------

  /**
   * Returns the border of the titled border.
   * 
   * @return the border &ndash; possibly {@code null}
   */
  public Border getBorder() {
    Border b = border;
    if (b == null)
      b = UIManager.getBorder("TitledBorder.border");
    return b;
  }

  /**
   * Sets the border of the titled border.
   * 
   * @param border the border &ndash; possibly {@code null}
   */
  public void setBorder(Border border) {
    this.border = border;
  }

  /**
   * Returns the title.
   * 
   * @return the title &ndash; possibly {@code null}
   */
  public String getTitle() {
    return title;
  }

  /**
   * Sets the title of the titled border.
   * 
   * @param title the title &ndash; possibly {@code null}
   */
  public void setTitle(String title) {
    this.title = title;
  }

  /**
   * Returns the title-justification of the titled border.
   * 
   * @return one of {@link SwingConstants#LEFT}, {@link SwingConstants#CENTER}
   *         , {@link SwingConstants#RIGHT}, {@link SwingConstants#LEADING},
   *         {@link SwingConstants#TRAILING}
   */
  public int getTitleJustification() {
    return titleJustification;
  }

  /**
   * Sets the titleJustification.
   * 
   * @param titleJustification one of {@link SwingConstants#LEFT},
   *          {@link SwingConstants#CENTER} , {@link SwingConstants#RIGHT},
   *          {@link SwingConstants#LEADING}, {@link SwingConstants#TRAILING}
   * @throws IllegalArgumentException if {@code titleJustification} is none of
   *           the above mentioned
   */
  public void setTitleJustification(int titleJustification) {
    switch (titleJustification) {
    case SwingConstants.LEFT:
    case SwingConstants.CENTER:
    case SwingConstants.RIGHT:
    case SwingConstants.LEADING:
    case SwingConstants.TRAILING:
      break;
    default:
      throw new IllegalArgumentException("Illegal title justification: "
            + titleJustification);
    }
    this.titleJustification = titleJustification;
  }
}
Und hier ein hübscher Test dazu:
Java:
/* $Id$ */

/* Copyright 2010 Sebastian Haufe

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       [url]http://www.apache.org/licenses/LICENSE-2.0[/url]

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License. */

package com.ebenius;

import java.awt.*;
import java.util.Formatter;

import javax.swing.*;
import javax.swing.border.TitledBorder;

public class HTMLTitledBorderTestGui {

  /**
   * Test main method.
   * 
   * @param args ignored
   */
  public static void main(String[] args) {
    final JPanel contentPane = new JPanel(new BorderLayout(6, 6)) {

      final Color c1 = new Color(0, 255, 0, 127);
      final Color c2 = new Color(0, 0, 255, 127);

      @Override
      protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        // gradient to test border transparency
        ((Graphics2D) g).setPaint(new GradientPaint(new Point(0, 0), c1,
              new Point(getWidth() / 2, getHeight() / 2), c2));
        g.fillRect(0, 0, getWidth(), getHeight());
        final Insets ins = getInsets();
        final int x = ins.left;
        final int y = ins.top;
        final int w = getWidth() - x - ins.right;
        final int h = getHeight() - y - ins.bottom;
        g.fillRect(x, y, w, h);
        g.setColor(Color.RED);
        g.drawRect(x, y, w, h);
      }
    };

    // the border
    final String greenBubble =
          "http://www.java-forum.org/images/statusicon/user_online.gif";
    final String patt =
          "<html><h1>&nbsp;<img src=\"%s\">&nbsp;Nice HTML Title&nbsp;</h1>";
    final HTMLTitledBorder theBorder =
          new HTMLTitledBorder(BorderFactory.createEtchedBorder(),
                new Formatter().format(patt, greenBubble).toString());
    contentPane.setBorder(theBorder);

    // the content
    final String myAvatar = "http://www.java-forum.org/avatars/ebenius.gif";
    final String contentHTML =
          "<html><table><tr><td><img src=\"%s\" border=1></td>"
                + "<td>Note that the red line around this area is drawn "
                + "in <code>paintComponent()</code> and is not "
                + "a border. It just shows where the border insets end."
                + "</td></tr>"
                + "<tr><td> </td><td>Happy Hacking!<br>"
                + "&nbsp; &ndash;Ebenius</td></tr>"
                + "</table>";
    contentPane.add(new JLabel(new Formatter().format(contentHTML, myAvatar)
          .toString()));

    final JFrame f = new JFrame("Test Frame: HTMLTitledBorderTestGui");
    f.setContentPane(contentPane);
    f.setSize(320, 280);
    f.setLocationRelativeTo(null);
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.setVisible(true);
  }
}
Getestet gegen Metal, Nimbus, CDE/Motif und GTK+ LAF.

Ebenius
 

Ähnliche Java Themen

Neue Themen


Oben