~HiDpi~计算机中的Java swing应用程序太小
我有一个java桌面应用程序,它使用JavaSwing,可以正常显示 但是当谈到~hiDpi~显示器(3200*1800)时,整个应用程序太小了 由于应用程序代码非常庞大和复杂,很难重新排列代码以匹配hi dpi。 这个问题有解决办法吗~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
我见过像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
sUIDefaults
,找出所有基于“字体”的属性,并将其存储为“基本”。完成后,它将使用这些值,根据比例和原始大小计算字体大小,并更新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);
}
}
}