2011-01-16 24 views
13

Tôi đã ứng dụng sau đó rút ra một quy luật:Làm thế nào để "chính xác" phát hiện DPI của màn hình với Java?

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(); } }); 
    } 
} 

Nó hoạt động tốt trên tuổi 17" của tôi và 20" màn hình, bây giờ tôi đã nhận thấy trên mới LCD 27" của tôi, nó là không chính xác, vì vậy tôi có getScreenResolution() phải nhận được DPI chính xác, tại sao nó không chính xác, để ứng dụng của tôi hoạt động trên các máy khác có kích thước hiển thị khác nhau và DPI, cách để tự động điều chỉnh 1.15 Tôi đã tự tay điều chỉnh 1.15 Tôi đã tự tay đặt?

PS: Không chỉ DPI của ứng dụng Java của tôi không chính xác, mà còn khi tôi xem một số ứng dụng khác trên Windows 7 như paint.exe hoặc paint.net, inch của chúng và cm là als o đúng. Bạn có thể thử chúng trên máy của bạn.

+0

Thông tin DPI được báo cáo bởi hệ điều hành hoặc thậm chí bởi chính trình điều khiển hiển thị thường không chính xác. Có thể bạn không may mắn cho một trường hợp thực sự chung chung. –

+0

Tôi không chắc chắn, nhưng thay vì 'Toolkit.getDefaultToolkit(). GetScreenSize();', hãy thử sử dụng để nhận kích thước 'GraphicsEnvironment.getLocalGraphicsEnvironment(). GetDefaultScreenDevice(). GetDisplayMode();'. Câu lệnh cuối cùng sẽ cho bạn chế độ hiển thị, sử dụng nó để lấy chiều cao và chiều rộng. – Favonius

+0

@Favonius: Cảm ơn, nhưng một khi tôi nhận được chúng, làm cách nào để có được DPI chính xác mà tôi cần? Các con số trông giống như thế này: Default_device Chiều rộng: 2560 Chiều cao: 1440 Tốc độ làm mới: 59 Độ sâu bit: 32 , Khá nhiều thông tin giống như tôi nhận được từ getScreenSize(); – Frank

Trả lời

8

Vấn đề về trình điều khiển.

DPI thực được biết chỉ với trình điều khiển, báo cáo nó cho hệ điều hành, báo cáo nó cho Java và các ứng dụng khác. Vì không chỉ Java có quy mô sai, nó phải là trình điều khiển.

Đây là vấn đề tuổi già. Nhiều ứng dụng đồ họa có cài đặt toàn cầu "màn hình DPI" nơi người dùng có thể điều chỉnh cho màn hình thực tế của họ.

Ngoài ra, vì bạn đang viết bằng Java, hãy nhớ rằng một số hệ điều hành không có cách nào nói cho Java biết về DPI thực sự (vì họ không biết chính mình). Do đó, nhu cầu thiết lập cấu hình DPI càng rõ ràng hơn.

Các vấn đề liên quan