How do I query the current anti-aliasing settings in Swing L&F?

TL; DR: What is the simplest and most correct way to set up an instance Graphics

to use default options for rendering strings? Or how to render the string using the default anti-aliasing settings to make it look like a JLabel? A more detailed description of the problem follows ...

I am trying to create my own JComponent subclass. In fact, it is kind of TableCellRenderer

capable of displaying rich text. The extension is JEditorPane

too heavy and slow (tried it really) and the JLabel cannot display rich text, so I decided to implement my own, lightweight and fast. Now it (obviously) needs to draw text in paintComponent()

, and I would like that text to look in all other text components like the JLabel.

However, when I do this, it seems to be using different anti-aliasing options from the rest of the application, so it looks pretty ugly. I understand that I can just use Graphics

to Graphics2D

to use the appropriate API, but the question is, which settings should I use? That is, what to pass in setRenderingHint()

as the second parameter?

I can get it to look great on my system by playing around with different AA values, but doesn't it suddenly look terrible on some other system with different default settings?

I tried looking at the JLabel and LabelUI sources, but they seem to use a lot of black magic, like asking for some hidden properties using JComponent.getClientProperty()

and SwingUtilities2

, which aren't even part of official Swing. Of course, I could try to emulate this, but it is a) too tedious and b) obliged to use some not too documented functions for which a guaranteed stable API is not guaranteed.

Or maybe there is a way to reuse some existing UI delegate? Basically, I just want my text to look exactly as shown JLabel

. I could even use an instance JLabel

or a subclass of it as a kind of rubber stamp for drawing text, but it looks a little ugly and I'm not sure about the performance. I realize I JTable

actually does exactly that, but using it JLabel

to draw a whole cell is one thing, using it to draw parts of a cell just doesn't seem right. For example, it may happen that some L&F decorate these in a JLabel

special way that looks ugly.

Ideally, I would like to have something like this (imaginary code):

((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING,
    JLabel.getDefaultUI().getRenderingHint());

      

Or better yet (customize everything, not just AA):

JLabel.getDefaultUI().setupGraphics(g); // this sets up g just like for drawing a JLabel

      

But there seems to be no such simple thing as far as I can see.

+3


source to share


2 answers


Sometimes we cannot see the forest for the trees ...

and JLabel cannot display rich text

If your need is rich text in a table renderer, then (maybe) that is the question! JLabel

actually makes rich text via HTML [Doc] , and even you can use JXLabel

from SwingX for further functionality (turn! line break!).

Given what DefaultTableRenderer

it actually is JLabel

, perhaps you can extend it and make a simple modification:

public class AATableRenderer extends DefaultTableCellRenderer {

    public Component getTableCellRendererComponent(JTable table, Object value,
            boolean isSelected, boolean hasFocus, int row, int column) {
        DefaultTableCellRenderer c = (DefaultTableCellRenderer) super
                .getTableCellRendererComponent(table, value, isSelected,
                        hasFocus, row, column);

        String text = c.getText();

        // Do some style transformations maybe...

        c.setText("<html>" + text + "</html>");

        return c;
    }

}

      

or you can change yours JTable

in the methodprepareRenderer()

public class AATable extends JTable {

    public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
        Component c = super.prepareRenderer(renderer, row, column);

        if (c instanceof JLabel) {
            JLabel l = (JLabel) c;
            String text = l.getText();

            // Do some style transformations maybe...

            l.setText("<html>" + text + "</html>");
        }

        return c;
    }

}

      

But maybe you can't use the HTML thing ... In this case, if you need to stick with your custom component, you might have to do it for each look and feel, since each is handled differently. For example, note that sometimes these properties are set on the system, and most Swing L&Fs respect them (Windows 7 configures this in My Computer> Properties> Advanced System Settings> Performance> Smooth Fonts (check in the list)).

I don't think you can reuse LabelUI

(basic) because maybe all this magic tampering with how you want to paint when you just want anti-aliasing ... Not sure if it's not impossible, but I can't tell ...

THIS IS AN ANSWER TO THE ORIGINAL QUESTION



Short answer

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

Long answer

The reason your component uses different settings is because Swing uses a delegation architecture for painting: the L&F contains delegate prototypes for each component type, when the component is instantiated, which is instantiated and injected by the component, and painting is done there (and behavior). When you just inject a method paintComponent(Graphics)

, you skip this whole architecture and execute the picture directly, and you miss the parameters that can be performed in delegates *. [Doc]

The most correct ("correct" is not always the best solution!) To make your custom component is to create your user interface delegate, register it, and execute the appropriate procedures. [Doc]

It's a long tedious job anyway, so keep it practical: If your application just uses one look and feel, if you're not going to reuse that component, if your time constraints don't allow you to spend a lot of time developing one component ... if you just need to set your antialiasing component, use this code snippet:

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JComponent;

public class AAComponent extends JComponent {

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g); // Maybe you want to skip this, up to your needs...

        Graphics2D g2 = null;
        try {
            g2 = (Graphics2D) g.create();

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

            // Your painting procedures
        } finally {
            if (g2 != null) {
                g2.dispose();
            }
        }
    }

}

      

The creation may g2

look a little strange, but it is quite optimal, it is a way not to propagate changes in yours Graphics

, and the computational cost is less than the minimum. Also, if you want to extend the anti-aliasing to the picture of the superclass (does JComponent

nothing in this case ) just call the super-implementation after setting the render hint.

* This is a bit inaccurate because the configuration does not necessarily rely on L&F, but in conjunction with delegates, but I think this is a good way to illustrate what is going on.

+3


source


For general purposes, the following attributes should set anti-aliasing in your application.

    System.out.println(System.getProperty("awt.useSystemAAFontSettings"));
    System.setProperty("awt.useSystemAAFontSettings","on"); 
    System.out.println(System.getProperty("awt.useSystemAAFontSettings"));
    System.setProperty("swing.aatext", "true");
    // etc.

      



Alternatively, when overridden paintComponent()

in the graphical context, your JLabel

or JPanel

:

        @Override
        protected void paintComponent(Graphics g) {
            Graphics2D g2 = (Graphics2D) g.create();
            try {
                // you can query the RenderingHints here
                g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
                g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
            } finally {
                if(g2 != null) {
                    g2.dispose();
                }
            }
        }

      

0


source







All Articles