如何用Java“正确”检测显示器的DPI?

2024-03-02

我有以下绘制规则的应用程序:

public class Rule extends JComponent
{
  public static final long serialVersionUID=26362862L;
//  public static final int INCH=Toolkit.getDefaultToolkit().getScreenResolution();
  public static final int INCH=(int)(Toolkit.getDefaultToolkit().getScreenResolution()*1.15);  // Auto adjust this 1.15 ?
  public static final int HORIZONTAL=0;
  public static final int VERTICAL=1;
  public static final int SIZE=35;
  public int orientation;
  public boolean isMetric;
  private int increment;
  private int units;
//  private Color rule_color=new Color(0,135,235);
  private Color rule_color=new Color(120,170,230);
  static JFrame frame=new JFrame("Rule");
  static Dimension screenSize=Toolkit.getDefaultToolkit().getScreenSize();  // 1600 x 1200  ,  1024 x 768
  static JPanel rulerPanel=new JPanel(new BorderLayout());

  public Rule(int o,boolean m)
  {
    orientation=o;
    isMetric=m;
    setIncrementAndUnits();
  }

  public void setIsMetric(boolean isMetric)
  {
    this.isMetric=isMetric;
    setIncrementAndUnits();
    repaint();
  }

  private void setIncrementAndUnits()
  {
    if (isMetric)
    {
      units=(int)((double)INCH/(double)2.54); // dots per centimeter
      increment=units;
    }
    else
    {
      units=INCH;
      increment=units/2;
    }
  }

  public boolean isMetric() { return this.isMetric; }

  public int getIncrement() { return increment; }

  public void setPreferredHeight(int ph) { setPreferredSize(new Dimension(SIZE,ph)); }

  public void setPreferredWidth(int pw) { setPreferredSize(new Dimension(pw,SIZE)); }

  public void setColor(Color color) { rule_color=color; }

  public void paintComponent(Graphics g)
  {
    Rectangle drawHere=g.getClipBounds();

    // Fill clipping area with blue-gray.
    g.setColor(rule_color);
    g.fillRect(drawHere.x,drawHere.y,drawHere.width,drawHere.height);

    // Do the ruler labels in a small font that's black.
    g.setFont(new Font("SansSerif",Font.PLAIN,10));
    g.setColor(Color.black);

    // Some vars we need.
    int end=0;
    int start=0;
    int tickLength=0;
    String text=null;

    // Use clipping bounds to calculate first tick and last tick location.
    if (orientation==HORIZONTAL)
    {
      start=(drawHere.x/increment)*increment;
      end=(((drawHere.x+drawHere.width)/increment)+1)*increment;
    }
    else
    {
      start=(drawHere.y/increment)*increment;
      end=(((drawHere.y+drawHere.height)/increment)+1)*increment;
    }

    // Make a special case of 0 to display the number within the rule and draw a units label.
    if (start==0)
    {
      text=Integer.toString(0)+(isMetric?" cm":" in");
      tickLength=10;
      if (orientation==HORIZONTAL)
      {
        g.drawLine(0,SIZE-1,0,SIZE-tickLength-1);
        g.drawString(text,2,21);
      }
      else
      {
        g.drawLine(SIZE-1,0,SIZE-tickLength-1,0);
        g.drawString(text,9,10);
      }
      text=null;
      start=increment;
    }

    // ticks and labels
    for (int i=start;i<end;i+=increment)
    {
      if (i%units==0)
      {
        tickLength=10;
        text=Integer.toString(i/units);
      }
      else
      {
        tickLength=5;
        text=null;
      }

      if (tickLength!=0)
      {
        if (orientation==HORIZONTAL)
        {
          g.drawLine(i,SIZE-1,i,SIZE-tickLength-1);
          if (text!=null) g.drawString(text,i-3,21);
        }
        else
        {
          g.drawLine(SIZE-1,i,SIZE-tickLength-1,i);
          if (text!=null) g.drawString(text,9,i+3);
        }
      }
    }
  }

  // Create the GUI and show it. For thread safety, this method should be invoked from the event-dispatching thread.
  static void createAndShowGUI()
  {
    rulerPanel.setPreferredSize(new Dimension(570,78));

    Rule cmView=new Rule(Rule.HORIZONTAL,true);
    int H=35;
    cmView.setPreferredHeight(H);
    cmView.setColor(new Color(128,200,235));
    JScrollPane cmScrollPane=new JScrollPane();
    cmScrollPane.setViewportBorder(BorderFactory.createLineBorder(Color.black));
    cmScrollPane.setColumnHeaderView(cmView);

    rulerPanel.add("North",cmScrollPane);

    Rule inchView=new Rule(Rule.HORIZONTAL,true);
    inchView.setPreferredHeight(H);
    inchView.setColor(new Color(168,200,235)); //238,238,238
    inchView.setIsMetric(false);
    JScrollPane inchScrollPane=new JScrollPane();
    inchScrollPane.setViewportBorder(BorderFactory.createLineBorder(Color.black));
    inchScrollPane.setColumnHeaderView(inchView);

    rulerPanel.add("South",inchScrollPane);
    frame.getContentPane().add(rulerPanel);
    frame.addWindowListener(new WindowAdapter()
    {
      public void windowActivated(WindowEvent e) { }
      public void windowClosed(WindowEvent e) { }
      public void windowClosing(WindowEvent e) { System.exit(0); }
      public void windowDeactivated(WindowEvent e) { }
      public void windowDeiconified(WindowEvent e) { rulerPanel.repaint(); }
      public void windowGainedFocus(WindowEvent e) { rulerPanel.repaint(); }
      public void windowIconified(WindowEvent e) { }
      public void windowLostFocus(WindowEvent e) { }
      public void windowOpening(WindowEvent e) { rulerPanel.repaint(); }
      public void windowOpened(WindowEvent e) { }
      public void windowResized(WindowEvent e) { rulerPanel.repaint(); }
      public void windowStateChanged(WindowEvent e) { rulerPanel.repaint(); }
    });
    frame.pack();
    frame.setBounds((screenSize.width-rulerPanel.getWidth())/2,(screenSize.height-rulerPanel.getHeight())/2-19,rulerPanel.getWidth()+20,rulerPanel.getHeight()+38);
    frame.setVisible(true);
  }

  public static void main(String[] args)
  {
    // Schedule a job for the event-dispatching thread : creating and showing this application's GUI.
    SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } });
  }
}

它在我的旧 17" 和 20" 显示器上运行良好,现在我注意到在我的新 27" LCD 上,它不准确,所以我必须更改第 4 行以使其更准确,不是 Toolkit.getDefaultToolkit()。 getScreenResolution() 应该获得准确的 DPI,为什么它不正确,为了让我的应用程序在具有不同显示尺寸和 DPI 的其他机器上工作,如何自动调整我手动输入的 1.15 ?

PS:不仅我的Java应用程序的DPI不准确,而且当我查看Windows 7上的其他几个应用程序(例如paint.exe或paint.net)时,它们的英寸和厘米也是正确的。您可以在您的机器上尝试它们。


驱动问题。

真正的 DPI 只有驱动程序知道,驱动程序将其报告给操作系统,操作系统将其报告给 Java 和其他应用程序。因为不仅 Java 的标度错误,而且一定是驱动程序的问题。

这是一个古老的问题。许多图形应用程序都有一个全局设置“屏幕 DPI”,用户可以根据实际显示器进行调整。

此外,由于您是用 Java 编写的,请记住,某些操作系统无法告诉 Java 真实的 DPI(因为它们不知道自己)。因此,DPI 配置设置的需求就更加明确了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何用Java“正确”检测显示器的DPI? 的相关文章

  • Spring 配置:无法找到 Spring NamespaceHandler

    配置问题 无法找到 XML 模式名称空间的 Spring NamespaceHandler http www springframework org schema tx http www springframework org schema
  • PDFBox 更改线条颜色

    我使用 pdfbox 1 8 5 并尝试使用绘制彩色线PDPageContentStream drawLine 我尝试过PDPageContentStream setNonStrokingColor 255 0 0 但它不起作用 我也没有找
  • 将jquery日期选择器集成到jsf中

    我正在关注这些例子here http jqueryui com demos datepicker icon trigger and here http jqueryui com demos datepicker icon trigger但我
  • 从字符串编译Java源代码? [复制]

    这个问题在这里已经有答案了 有没有办法让正在运行的Java程序编译Java源代码 作为字符串传递 Class newClass Compiler compile class ABC void xyz etc etc 理想情况下 传入源代码引
  • Spring 3、Jersey (JSR-311) 和 Maven 依赖项

    我目前正在努力集成基于 Jersey 和 Spring 的 REST 服务 我正在使用 Spring 3 0 2 RELEASE 和 jersey spring 1 2 但是 jersey spring 在我的项目中添加了对 Spring
  • 如何阻止 Apache CXF 发送响应消息?

    如果给定的 SOAP 标头元素具有给定值 例如 如果标头标记 response 的值为 0 我根本不希望 Apache CXF 返回响应 我怎样才能做到这一点 CXF 似乎假设所有呼叫都会收到响应 我知道这在 Web 服务上下文中看起来很奇
  • Jackson @JsonRawValue 获取地图的值

    我有以下 Java bean 类 使用 Jackson 将其转换为 JSON public class Thing public String name JsonRawValue public Map content new HashMap
  • Java 文档生成器为 Xml 字符串返回 null 文档

    I have tried all possible answers https stackoverflow com questions 33098082 passing xml string as document returning nu
  • 根据使用频率随机生成字母?

    如何根据常用语音中的使用频率随机生成字母 任何伪代码都值得赞赏 但如果用 Java 实现就更棒了 否则 只需朝正确的方向戳一下就会有所帮助 注意 我不需要生成使用频率 我确信我可以很容易地查找到它 我假设您将频率存储为 0 到 1 之间的浮
  • 如何处理过时的连接?

    我们的应用程序是一个 J2EE 应用程序 在 Websphere 6 1 上通过 Mainframe DB2 后端使用 Struts EJB Hibernate 最近已投入生产 我们收到过时的连接异常当用户第一次或有时登录应用程序时 此异常
  • Dao 和服务接口的需求

    我是Spring Mvc的新手 在很多教程中 我发现有一个像这样的Dao接口 public interface StudentDAO public List
  • jni.h:没有这样的文件或目录

    我一直在关注本教程 http www java tips org other api tips jni simple example of using the java native interface html 在第 5 步 我从 GCC
  • 面向 Clojure 用户的 Java

    我一直在断断续续地使用 Lisp 并且正在赶上 clojure clojure的好处是我可以自然地使用所有的java函数 而clojure的坏处也是我必须自然地了解java函数 例如 我不得不花一些时间 谷歌搜索 来查找 Java 中的平方
  • 如何停止在控制台上打印异常堆栈跟踪?

    我编写了一个 Servlet 来处理 Web 应用程序中发生的异常 并将它们映射到 web xml 中
  • 为什么实现接口的类与 Java 中的接口不属于同一类型?

    I have out load output transactions columnHeaders dataFormat Where load定义为 public boolean load String outputfile List
  • 在自定义 BaseAdapter 子类中使用 Butter Knife 会导致“无法注入视图”错误

    我正在尝试使用 Butter Knife 来简化自定义 BaseAdapter 类的创建 我正在遵循这里的示例 http jakewharton github io butterknife http jakewharton github i
  • 连接空字符串来进行字符串转换真的那么糟糕吗?

    假设我有两个char变量 稍后我想将它们连接成一个字符串 我就是这样做的 char c1 c2 String s c1 c2 我见过有人说 trick 是 丑陋的 等等 你应该使用String valueOf or Character to
  • 使用 libGDX 写入 Json

    我是 Json 和 libGDX 的新手 但我创建了一个简单的游戏 我想将玩家姓名及其分数存储在 Json 文件中 有没有办法做到这一点 我想创建一个 Json 文件Gdx files localStorage如果它不存在 如果存在 则向其
  • List 和 List 之间的区别[重复]

    这个问题在这里已经有答案了 我读过很多这方面的内容 我知道 List listOfObject new ArrayList
  • 如何从 netbeans 远程调试 jar

    我正在尝试弄清楚如何调试远程运行的 jar 这是我的场景 我的 jar 将从 VPS 运行 这个jar基本上运行一个服务器 对于游戏 所以它还连接到 mysql 数据库 我使用 3 个 bat 文件启动服务器 如下所示 设置 CLASSPA

随机推荐