Как плавно автоматически настроить размер шрифта нескольких JLabel на основе размера контейнера?

Мне нужно изменить размер шрифта нескольких JLabel на основе коэффициента масштабирования, используемого для изменения размера контейнера. Для этого я устанавливаю для шрифта каждой JLabel значение null, чтобы они брали шрифт контейнера. Это работает, но также дает странные результаты.

Чтобы быть точным, текст кажется «отстающим» от контейнера, а иногда даже усекается. Я хотел бы избежать такого поведения. Есть идеи как?

Пример кода, моделирующего поведение:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.geom.AffineTransform;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class TextResize implements Runnable {

    public static void main(String[] args) {
        TextResize example = new TextResize();
        SwingUtilities.invokeLater(example);
    }

    public void run() {
        JFrame frame = new JFrame("JLabel Text Resize");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setPreferredSize(new Dimension(800, 400));

        Container container = frame.getContentPane();
        container.setLayout(new BorderLayout());

        final JPanel labelContainer = new JPanel(new GridBagLayout());
        labelContainer.setBorder(BorderFactory.createLineBorder(Color.black));

        //initial font
        final Font textFont = new Font("Lucida Console", Font.PLAIN, 10).deriveFont(AffineTransform.getScaleInstance(1, 1));
        labelContainer.setFont(textFont);

        GridBagConstraints c = new GridBagConstraints();
        c.fill = GridBagConstraints.BOTH;
        c.insets = new Insets(0, 10, 0, 10);
        c.weightx = 1;
        for (int i = 0; i < 5; i++) {
            JLabel f = new JLabel("Text here with possibly looooooooong words");
            f.setBorder(BorderFactory.createLineBorder(Color.green));
            f.setFont(null);//take the font from parent
            c.gridy = i;
            labelContainer.add(f, c);
        }

        JSlider slider = new JSlider(0,50000,10000);
        slider.addChangeListener(new ChangeListener() {     
            double containerWidth = labelContainer.getPreferredSize().getWidth();
            double containerHeight = labelContainer.getPreferredSize().getHeight();

            @Override
            public void stateChanged(ChangeEvent ev) {
                JSlider source = (JSlider) ev.getSource();
                double scale = (double) (source.getValue() / 10000d);

                //scaling the container
                labelContainer.setSize((int) (containerWidth * scale), (int) (containerHeight * scale));

                //adjusting the font: why does it 'lag' ? why the truncation at times?
                Font newFont = textFont.deriveFont(AffineTransform.getScaleInstance(scale, scale));
                labelContainer.setFont(newFont);

                //print (font.getSize() does not change?)
                System.out.println(scale + " " + newFont.getTransform() + newFont.getSize2D());
            }
        });

        container.add(slider, BorderLayout.NORTH);
        JPanel test = new JPanel();
        test.setLayout(null);
        labelContainer.setBounds(5, 5, labelContainer.getPreferredSize().width, labelContainer.getPreferredSize().height);
        test.add(labelContainer);
        container.add(test, BorderLayout.CENTER);

        frame.pack();
        frame.setVisible(true);
    }

}

Изображение: http://i.stack.imgur.com/tZLOO.png

Спасибо,

-s

6
задан mKorbel 22 March 2012 в 01:37
поделиться