第2部分 – 如何在缩放JTextPane时获得一致的渲染?

我之前提交了此问题的另一个版本和示例程序: 在缩放JTextPane时如何获得一致的渲染?

重述问题:我想允许用户放大或缩小不可编辑的JTextPane。 运行在前一个问题中提交的示例程序(简单地缩放了Graphics对象),导致粗体文本和非粗体文本之间的间距不一致。

下面的示例程序尝试通过将文本窗格绘制为100%的BufferedImage然后缩放图像来解决问题。 这解决了间距不一致的问题,但结果文本缺乏清晰度。 是否有一些渲染提示(或其他一些变化)的组合将产生漂亮的清晰文本?

提前感谢对此方法可行性的任何建议或意见。

import java.awt.BorderLayout; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.RenderingHints; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; import javax.swing.Box; 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_; BufferedImage raster_; public ScaledJTextPane() { scale_ = 1.0; raster_ = null; } public void draw(Graphics g) { if (raster_ == null) { // Draw this text pane to a BufferedImage at 100% raster_ = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = raster_.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_OFF); paint(g2); } Graphics2D g2 = (Graphics2D) g; // Experiment with different rendering hints g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); // Scale the BufferedImage g2.scale(scale_, scale_); g2.drawImage(raster_, 0, 0, null); } public void setScale(double scale) { scale_ = scale; raster_ = null; } private static void createAndShowGUI() { // Create and set up the window. JFrame frame = new JFrame("ScaledJTextPane using BufferedImage"); 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.paintComponent(g); scaledTextPane.draw(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%"); JPanel optionsPanel = new JPanel(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); c.gridx = 0; c.gridy = 0; c.anchor = GridBagConstraints.WEST; optionsPanel.add(zoomCombo, c); c.gridx++; c.weightx = 1; c.fill = GridBagConstraints.HORIZONTAL; optionsPanel.add(Box.createHorizontalGlue(), c); // 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(optionsPanel, 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(); } }); } } 

可能是这个http://java-sl.com/Scale_In_JEditorPane.html可以提供帮助。

遗憾的是,从固定分辨率缩放到更大的尺寸将始终导致一些混叠伪像。 这是一种缩放JTextPane使用的字体的替代方法。

对于低级别控制,请考虑TextLayout ,其中包含可以管理抗锯齿和小数度量设置的FontRenderContext ,如本示例所示 。

替代文字

 import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.text.*; /** @see https://stackoverflow.com/questions/4566211 */ public class ScaledJTextPane { private static final int SIZE = 14; private static final String FONT = "Dialog"; private static void createAndShowGUI() { JFrame frame = new JFrame("ScaledJTextPane using BufferedImage"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); final JTextPane tp = new JTextPane(); tp.setFont(new Font(FONT, Font.PLAIN, SIZE)); tp.setPreferredSize(new Dimension(400, 300)); StyledDocument doc = tp.getStyledDocument(); Style defaultStyle = StyleContext.getDefaultStyleContext() .getStyle(StyleContext.DEFAULT_STYLE); Style boldStyle = doc.addStyle("bold", defaultStyle); StyleConstants.setBold(boldStyle, true); 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) { ble.printStackTrace(System.err); } final JPanel panel = new JPanel(); panel.add(tp); final JComboBox zoomCombo = new JComboBox(new String[]{ "75%", "100%", "150%", "175%", "200%"}); zoomCombo.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { String s = (String) zoomCombo.getSelectedItem(); s = s.substring(0, s.length() - 1); double scale = new Double(s).doubleValue() / 100; int size = (int) (SIZE * scale); tp.setFont(new Font(FONT, Font.PLAIN, size)); } }); zoomCombo.setSelectedItem("100%"); JPanel optionsPanel = new JPanel(); optionsPanel.add(zoomCombo); panel.setBackground(Color.WHITE); frame.add(panel, BorderLayout.CENTER); frame.add(optionsPanel, BorderLayout.NORTH); frame.pack(); frame.setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { createAndShowGUI(); } }); } } 

我想允许用户放大或缩小不可编辑的JTextPane。

由于文本窗格不可编辑,因此您可以使用Screen Image类创建文本窗格的图像 。 然后,您可以使用适当的缩放系数在面板上绘制图像。