简体   繁体   中英

How to reduce the textRect Rectangle in a Java Swing BasictabbedPaneUI implementation?

I am implementing my own Look&Feel for a JTabbedPane using BasicTabbedPaneUI . Following this tutorial , I want to add close buttons at the end of my tabs.

So far, I have managed to paint my closing icons on the right of the tab but it overlays my tab title. Therefore, I would like to reduce the width of the Rectangle used for the textRect parameter in the overridden method paintTab().

I have tried this but it has no effect:

@Override
protected void paintTab(Graphics g, int tabPlacement, Rectangle[] rects, int tabIndex,
                        Rectangle iconRect, Rectangle textRect) {

    //reduce textrect width to leave space for close icon
    textRect.setSize(textRect.width - (2 * WIDTHDELTA + icon.getIconWidth()), textRect.height);

    super.paintTab(g, tabPlacement, rects, tabIndex, iconRect, textRect);

    Rectangle tabRect = rects[tabIndex];

    // Calculate the coordinates where the button should be.
    int dx = tabRect.x + tabRect.width - icon.getIconWidth() - WIDTHDELTA;
    int dy = tabRect.y + (tabRect.height - icon.getIconHeight()) / 2;

    //Paint the Close button
    icon.paintIcon(tabPane, g, dx, dy);
}

How and where can I shrink the rectangle used to paint the tab's text?

Try to play with the fields of BasicTabbedPaneUI

protected Insets tabInsets;
protected Insets selectedTabPadInsets;
protected Insets tabAreaInsets;
protected Insets contentBorderInsets;

The tabInsets are used in the method you can try to override

protected int calculateTabWidth(int tabPlacement, int tabIndex, FontMetrics metrics)

Here is the solution I came up with:

    private String clipText(FontMetrics metrics, String text) {
    String clipped = "...";

    if (metrics.stringWidth(clipped) < MAX_TEXT_WIDTH) {
        StringBuilder sb = new StringBuilder(clipped);

        int index = 0;
        for (char c : text.toCharArray()) {
            sb.insert(index, c);
            if (metrics.stringWidth(sb.toString()) > MAX_TEXT_WIDTH) {
                clipped = sb.deleteCharAt(index).toString();
                break;
            }
            index++;
        }
    }
    return clipped;
}

I use it in:

    @Override
protected void paintText(Graphics g, int tabPlacement, Font font, FontMetrics metrics,
                         int tabIndex, String title, Rectangle textRect, boolean isSelected) {

    g.setFont(font);

    View v = getTextViewForTab(tabIndex);
    if (v != null) {
        // html
        v.paint(g, textRect);
    } else {
        // plain text
        int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex);

        g.setColor(isSelected ? ANZ_BLUE : Color.WHITE);

        String text;
        int rectX;
        if (metrics.stringWidth(title) <= MAX_TEXT_WIDTH) {
            text = title;
            rectX = textRect.x - (icon.getIconWidth() / 2); //center text
        } else {
            text = clipText(metrics, title);    //clip text
            rectX = textRect.x;
        }

        if (tabPane.isEnabled() && tabPane.isEnabledAt(tabIndex)) {
            BasicGraphicsUtils.drawStringUnderlineCharAt(g, text, mnemIndex, rectX,
                                                         textRect.y + metrics.getAscent());

        } else { // tab disabled
            Color bg = tabPane.getBackgroundAt(tabIndex);
            g.setColor(bg.brighter());
            BasicGraphicsUtils.drawStringUnderlineCharAt(g, text, mnemIndex, rectX,
                                                         textRect.y + metrics.getAscent());
            g.setColor(bg.darker());
            BasicGraphicsUtils.drawStringUnderlineCharAt(g, text, mnemIndex, rectX - 1,
                                                         textRect.y + metrics.getAscent() - 1);
        }
    }
}

It works fine for me.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM