3

重複の可能性:
パート 2 - JTextPane のスケーリング時に一貫したレンダリングを取得するにはどうすればよいですか?

ユーザーが編集不可能な JTextPane をズームインまたはズームアウトできるようにしたいと考えています。

以下のサンプル プログラムを実行すると、Graphics オブジェクトをスケーリングすると、太字のテキストと太字でないテキストの間の間隔に一貫性がなくなることがわかります。太字と非太字の間に 1 つのスペースがあると、レンダリングの幅が広すぎる場合があり、他のズーム レベルではスペースが消えて隣接する文字が重なります。

レンダリング ヒントがない場合、間隔は 100% で正しいですが、他のズーム レベルでは正しくありません。KEY_FRACTIONALMETRICS レンダリング ヒントを使用すると、結果はすべてのズーム レベルで一貫していますが、太字と非太字の間隔は 100% でも正しくありません。

Java 1.6.0_13 と 1.6.0_23 の両方でこれを試しました。結果は同じでした。すべてのズーム レベルで魅力的なスケーリングされたレンダリングを実現する方法について何か提案はありますか?

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.text.BadLocationException;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.StyledDocument;

public class ScaledJTextPane extends JTextPane
{
    double scale_;

    public ScaledJTextPane()
    {
        scale_ = 1.0;
    }

    protected void paintComponent(Graphics g)
    {
        Graphics2D g2 = (Graphics2D) g;

        // Try with and without the rendering hint
        g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
                RenderingHints.VALUE_FRACTIONALMETRICS_ON);
        g2.scale(scale_, scale_);

        super.paintComponent(g2);
    }

    public void setScale(double scale)
    {
        scale_ = scale;
    }

    private static void createAndShowGUI() 
    {
        // Create and set up the window.
        JFrame frame = new JFrame("ScaledJTextPane");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final ScaledJTextPane scaledTextPane = new ScaledJTextPane();
        StyledDocument doc = scaledTextPane.getStyledDocument();
        Style defaultStyle = StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE);
        Style boldStyle = doc.addStyle("bold", defaultStyle);
        StyleConstants.setBold(boldStyle, true);

        scaledTextPane.setFont(new Font("Dialog", Font.PLAIN, 14));
        String boldText = "Four score and seven years ago ";
        String plainText = "our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal.";
        try 
        {
            doc.insertString(doc.getLength(), boldText, boldStyle);
            doc.insertString(doc.getLength(), plainText, defaultStyle);
        } 
        catch (BadLocationException ble) 
        {
            System.err.println("Couldn't insert text into text pane.");
        }

        final JComboBox zoomCombo=new JComboBox(new String[] {"75%",
                "100%", "150%", "175%", "200%"});
        final JPanel panel = new JPanel()
        {
            protected void paintComponent(Graphics g)
            {
                super.paintChildren(g);
                scaledTextPane.paint(g);
            }
        };
       zoomCombo.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
              String s = (String) zoomCombo.getSelectedItem();
              s = s.substring(0, s.length() - 1);
              double scale = new Double(s).doubleValue() / 100;
              scaledTextPane.setScale(scale);
              panel.invalidate();
              panel.repaint();
            }
          });
        zoomCombo.setSelectedItem("100%");

        // Add content to the window.
        scaledTextPane.setBounds(0, 0, 450, 300);
        panel.setOpaque(true);
        panel.setBackground(Color.WHITE);
        frame.getContentPane().add(panel, BorderLayout.CENTER);
        frame.getContentPane().add(zoomCombo, BorderLayout.NORTH);
        frame.setSize(900, 300);

        //Display the window.
        frame.setVisible(true);
    }

    public static void main(String[] args) 
    {
        SwingUtilities.invokeLater(new Runnable() 
        {
            public void run() 
            {
                createAndShowGUI();
            }
        });
    }
}
4

0 に答える 0