我有一个使用java swing的java桌面应用程序,它可以正常显示.
但是当来到~hiDpi~显示器(3200*1800)时整个应用程序太小了.
由于应用程序代码非常庞大且复杂,因此很难重新排列代码以匹配hi dpi.有这个问题的解决方案吗?
我已经看到像IntelliJ想法这样的应用程序,并且eclipse可以很好地使用这种显示而没有问题.感谢任何帮助.
前段时间,我的任务是开发一个允许用户动态增加或减少应用程序字体大小的解决方案.毋庸置疑,我花了很多时间撕掉我的头发(主要是因为我的前任立即使用setPreferredSize
和其他愚蠢的想法使得任何解决方案都难以实施)
以下是我提出的想法的一个例子.它允许您修改UIManager
s"字体"属性,将缩放应用于字体大小.
基本上,它扫描UIManager
s UIDefaults
,挑选出所有基于"字体"的属性并将它们存储为"基础".完成后,它会使用这些值,根据比例和原始大小计算字体大小,并更新UIManager
import java.awt.Font; import java.util.HashMap; import java.util.Map; import javax.swing.UIManager; import sun.swing.SwingLazyValue; public class FontUtilities { private static Maporiginals; public static void setFontScale(float scale) { if (originals == null) { originals = new HashMap<>(25); for (Map.Entry entry : UIManager.getDefaults().entrySet()) { Object key = entry.getKey(); if (key.toString().toLowerCase().contains(".font")) { Object value = entry.getValue(); Font font = null; if (value instanceof SwingLazyValue) { SwingLazyValue lazy = (SwingLazyValue) entry.getValue(); value = lazy.createValue(UIManager.getDefaults()); } if (value instanceof Font) { font = (Font) value; originals.put(key.toString(), font); } } } } for (Map.Entry entry : originals.entrySet()) { String key = entry.getKey(); Font font = entry.getValue(); float size = font.getSize(); size *= scale; font = font.deriveFont(Font.PLAIN, size); UIManager.put(key, font); } } }
这个例子来自Swing教程,增加了字体缩放
基本上,当+点击按钮时,它正在运行此代码......
scale += 1f; FontUtilities.setFontScale(scale); SwingUtilities.updateComponentTreeUI(TextSamplerDemo.this); updateUI(); revalidate(); repaint();
基本思想是根据"默认"屏幕分辨率定义缩放算法,1
并且随着屏幕分辨率/ DPI的增加,您可以增加字体缩放以遵循.
这有问题.它可能不适用于外观(看着你的灵气),如果你定义自己的字体,它们将不会被更新.这也是一个很好的方式,看你何时用api完成了愚蠢的事情,因为它会对你的布局造成严重破坏
另一种解决方案是使用JXLayer
/ JLayer
来动态扩展UI作为一个整体.
import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.RenderingHints; import java.util.HashMap; import java.util.Map; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JSlider; import javax.swing.JTextField; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.jdesktop.jxlayer.JXLayer; import org.pbjar.jxlayer.demo.TransformUtils; import org.pbjar.jxlayer.plaf.ext.transform.DefaultTransformModel; public class TestJLayerZoom { public static void main(String[] args) { new TestJLayerZoom(); } public TestJLayerZoom() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { } JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); frame.add(new TestPane()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class TestPane extends JPanel { private JXLayerlayer; private DefaultTransformModel transformModel; private JPanel content; public TestPane() { content = new JPanel(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridy = 0; JLabel label = new JLabel("Hello"); JTextField field = new JTextField("World", 20); content.add(label, gbc); content.add(field, gbc); gbc.gridy++; gbc.gridwidth = GridBagConstraints.REMAINDER; final JSlider slider = new JSlider(50, 200); slider.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { int value = slider.getValue(); double scale = value / 100d; transformModel.setScale(scale); } }); content.add(slider, gbc); transformModel = new DefaultTransformModel(); transformModel.setScaleToPreferredSize(true); Map hints = new HashMap<>(); //hints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); //hints.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE); //hints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); layer = TransformUtils.createTransformJXLayer(content, transformModel, hints); setLayout(new BorderLayout()); add(layer); } } }
这是基于这里提出的想法.在答案中链接了一个额外的库,您需要将其用于此工作