phil-daniels
phil-daniels

Reputation: 646

Swing text looks bad

I am overriding the paintComponent() method of a JCOmponent and drawing text in a window. I'm running on Ubuntu and using the font "Ubuntu Mono" (the default font for the Ubuntu text editor). When my java app displays the text, it looks wimpy and blurry. What am I doing wrong?

I'm drawing the text like this:

graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
Font font = new Font("Ubuntu Mono", Font.PLAIN, 18);
fontMetrics = graphics.getFontMetrics(font);
graphics.setFont(font);
graphics.drawString(value, getX(), getY() + fontMetrics.getHeight());

In my java app, it looks like this:

Java app text

In the Ubuntu TextEditor, it looks like this:

enter image description here

Edit: Would performance suffer if .png images were used instead of drawText()? This is a business application, not a game that requires smooth animation.

Edit: I changed the colors to match TextEditor's colors and that actually helped a little on the quality, but the characters are still so much thinner... you almost can't see a ".". In gimp I can recreate the TextEditor look by creating text w/ the right font w/ antialiasing on.

Upvotes: 2

Views: 3498

Answers (4)

phil-daniels
phil-daniels

Reputation: 646

Strangely enough, I tried using "Monospaced" instead of "Ubuntu Mono" with:

graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

and it looks good enough for me. That's what I'm going to use.

Upvotes: 3

LanguagesNamedAfterCofee
LanguagesNamedAfterCofee

Reputation: 5952

Read the .png image and cache it to a BufferedImage. Performance would not suffer - actually using an intermediate image like this has better performance than drawing text in the first place.

Make sure you make it a compatible image like so:

private Image getCompatibleImage(BufferedImage img) throws IOException {
        GraphicsConfiguration c = GraphicsEnvironment
                .getLocalGraphicsEnvironment().getDefaultScreenDevice()
                .getDefaultConfiguration();

        if (c.getColorModel().equals(img.getColorModel()))
            return img;

        BufferedImage compatible = c.createCompatibleImage(img.getWidth(),
                img.getHeight());
        Graphics cg = compatible.getGraphics();
        cg.drawImage(img, 0, 0, null);
        cg.dispose();

        return compatible;
    }

This will save per-pixel conversion on some monitors for increased performance.

Upvotes: 2

tenorsax
tenorsax

Reputation: 21223

Instead of forcing rendering hints try to use native desktop settings for fonts, ie:

Toolkit tk = Toolkit.getDefaultToolkit();
Map desktopHints = (Map)(tk.getDesktopProperty("awt.font.desktophints"));

...

if (desktopHints != null) {
    graphics.addRenderingHints(desktopHints);
}

(source - Filthy Rich Clients)

EDIT:

Be sure to try out various hints for for controlling text rendering quality. Here is the reference and examples.

Upvotes: 1

Dan O
Dan O

Reputation: 6090

You're not necessarily doing anything wrong. From the API for RenderingHints (emphasis mine):

these keys and values are hints, there is no requirement that a given implementation supports all possible choices indicated below or that it can respond to requests to modify its choice of algorithm. The values of the various hint keys may also interact such that while all variants of a given key are supported in one situation, the implementation may be more restricted when the values associated with other keys are modified. [snip]

Implementations are free to ignore the hints completely, but should try to use an implementation algorithm that is as close as possible to the request.

Upvotes: 1

Related Questions