~HiDpi~计算机中的Java swing应用程序太小

~HiDpi~计算机中的Java swing应用程序太小,java,swing,intellij-idea,hdpi,Java,Swing,Intellij Idea,Hdpi,我有一个java桌面应用程序,它使用JavaSwing,可以正常显示 但是当谈到~hiDpi~显示器(3200*1800)时,整个应用程序太小了 由于应用程序代码非常庞大和复杂,很难重新排列代码以匹配hi dpi。 这个问题有解决办法吗 我见过像IntelliJidea和eclipse这样的应用程序可以很好地与这种显示器配合使用,没有任何问题。感谢您的帮助。我没有现成的解决方案,但是: 如果您的元素位于JFrame中的JPanel(标准方式),请编写您自己的布局管理器,将此根JPanel缩放到J

我有一个java桌面应用程序,它使用JavaSwing,可以正常显示

但是当谈到~hiDpi~显示器(3200*1800)时,整个应用程序太小了

由于应用程序代码非常庞大和复杂,很难重新排列代码以匹配hi dpi。 这个问题有解决办法吗


我见过像IntelliJidea和eclipse这样的应用程序可以很好地与这种显示器配合使用,没有任何问题。感谢您的帮助。

我没有现成的解决方案,但是:

如果您的元素位于JFrame中的JPanel(标准方式),请编写您自己的布局管理器,将此根JPanel缩放到JFrame大小的1/4,并使JFrame的大小增大四倍(宽度x2,长度x2)

覆盖JFrame中的绘制方法,以及getGraphics()的一些逻辑(您需要对此进行研究),确保在将方法setScale(2,2)提供给绘图代码之前,在图形上调用该方法,它将使所有绘制的图形都变大四倍

使用java.awt.EventQueue,编写自己的EventQueue来代理所有鼠标事件,并将它们转换为窗口中原始位置的1/4(x/2,y/2),然后放开它们,它们应该在适当的元素上触发事件


整个想法是让组件保持其原始大小(虚拟),但缩放绘图代码和鼠标事件,因此其外观和工作方式应与低分辨率显示器相同。

不久前,我的任务是开发一个解决方案,允许用户动态增加或减少应用程序的字体大小。不用说,我花了很多时间来解决问题(主要是因为我的前任立即使用了
setPreferredSize
和其他愚蠢的想法,这使得任何解决方案都很难实现)

下面是我提出的想法的一个例子。它允许您修改
UIManager
s“font”属性,并对字体大小应用比例

基本上,它扫描
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 Map<String, Font> originals;

    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<String, Font> 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);
        }
    }

}
基本思想是根据“默认”屏幕分辨率
1
定义缩放算法,随着屏幕分辨率/DPI的增加,您可以增加字体缩放

这是有问题的。它可能不适用于外观(看着你的nimbus),如果你定义了自己的字体,它们将不会被更新。这也是一个非常好的方式来了解你在api上做了什么蠢事,因为它会破坏你的布局

另一种解决方案是使用
JXLayer
/
JLayer
动态缩放整个UI

导入java.awt.BorderLayout;
导入java.awt.Dimension;
导入java.awt.EventQueue;
导入java.awt.GridBagConstraints;
导入java.awt.GridBagLayout;
导入java.awt.RenderingHints;
导入java.util.HashMap;
导入java.util.Map;
导入javax.swing.JComponent;
导入javax.swing.JFrame;
导入javax.swing.JLabel;
导入javax.swing.JPanel;
导入javax.swing.JSlider;
导入javax.swing.JTextField;
导入javax.swing.UIManager;
导入javax.swing.UnsupportedLookAndFeelException;
导入javax.swing.event.ChangeEvent;
导入javax.swing.event.ChangeListener;
导入org.jdesktop.jxlayer.jxlayer;
导入org.pbjar.jxlayer.demo.TransformUtils;
导入org.pbjar.jxlayer.plaf.ext.transform.DefaultTransformModel;
公共类TestJLayerZoom{
公共静态void main(字符串[]args){
新的TestJLayerZoom();
}
公共测试jlayerzoom(){
invokeLater(新的Runnable(){
@凌驾
公开募捐{
试一试{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}catch(ClassNotFoundException |实例化Exception | IllegalacessException |不支持ookandfeelException ex){
}
JFrame=新JFrame(“测试”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(新的BorderLayout());
frame.add(newtestpane());
frame.pack();
frame.setLocationRelativeTo(空);
frame.setVisible(true);
}
});
}
公共类TestPane扩展了JPanel{
私有JXLayer层;
私有模式转换模式;
私有JPanel内容;
公共测试窗格(){
content=newJPanel(newGridBagLayout());
GridBagConstraints gbc=新的GridBagConstraints();
gbc.gridy=0;
JLabel标签=新的JLabel(“你好”);
JTextField=新的JTextField(“世界”,20);
内容。添加(标签,gbc);
内容。添加(字段,gbc);
gbc.gridy++;
gbc.gridwidth=GridBagConstraints.rements;
最终JSlider滑块=新JSlider(50200);
slider.addChangeListener(新的ChangeListener(){
@凌驾
公共无效状态已更改(更改事件e){
int value=slider.getValue();
双刻度=数值/100d;
transformModel.setScale(比例);
}
});
添加(滑块,gbc);
transformModel=新的DefaultTransformModel();
transformModel.setScaleToPreferredSize(真);
映射提示=新的HashMap();
//put(renderinghits.KEY\u抗锯齿,renderinghits.VALUE\u抗锯齿开);
//put(renderinghits.KEY\u抖动,renderinghits.VALUE\u抖动\u启用);
//提示。放置(渲染提示)
scale += 1f;
FontUtilities.setFontScale(scale);
SwingUtilities.updateComponentTreeUI(TextSamplerDemo.this);
updateUI();
revalidate();
repaint();
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 JXLayer<JComponent> layer;
        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<RenderingHints.Key, Object> 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);


        }

    }

}