2011-01-16 2 views
13

나는 규칙을 그립니다 다음 응용 프로그램이 있습니다Java로 디스플레이의 DPI를 "올바르게"감지하는 방법은 무엇입니까?

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에 나타났습니다, 그것은 정확하지, 그래서 내가 가진 네 번째 라인을 더 정확하게 바꾸기 위해, Toolkit.getDefaultToolkit(). getScreenResolution()은 정확한 DPI를 얻지 못했고, 왜 정확하지 않은가요, 내 애플 리케이션이 다른 디스플레이 크기와 DPI를 가진 다른 머신에서 작동하는 방법입니다. 수동으로 넣은 1.15를 자동으로 조정하려면

PS : 내 Java 응용 프로그램의 DPI가 정확하지 않을뿐만 아니라 Windows 7에서 paint.exe 또는 paint.net과 같은 몇 가지 다른 응용 프로그램을 살펴볼 때 해당 인치 및 cm은 올바른 있음. 당신은 당신의 컴퓨터에서 그것들을 시도 할 수 있습니다.

+0

운영 체제 또는 디스플레이 드라이버 자체에서보고 한 DPI 정보가 부정확 할 수 있습니다. 정말로 일반적인 경우에는 운이 좋지 않을 것입니다. –

+0

'Toolkit.getDefaultToolkit(). getScreenSize();'대신'GraphicsEnvironment.getLocalGraphicsEnvironment(). getDefaultScreenDevice(). getDisplayMode();'크기를 얻기 위해 이것을 사용해보십시오. 마지막 문장은 디스플레이 모드를 제공하여 높이와 너비를 가져 오는 데 사용합니다. – Favonius

+0

@ Favonius : 감사합니다.하지만 일단 내가 얻은 후에는 내가 필요한 정확한 DPI를 얻는 방법은 무엇입니까? 숫자는 다음과 같습니다. Default_device 너비 : 2560 높이 : 1440 새로 고침 빈도 : 59 비트 수 : 32 , getScreenSize()에서 얻은 정보와 거의 동일합니다. – Frank

답변

8

드라이버 문제.

실제 DPI는 드라이버에만 알려 지므로 OS에보고하여 드라이버를 Java 및 기타 응용 프로그램에보고합니다. Java는 잘못된 스케일을 가지고 있기 때문에 드라이버가되어야합니다.

이것은 오래된 문제입니다. 많은 그래픽 응용 프로그램에는 사용자가 실제 모니터를 조정할 수있는 "화면 DPI"라는 전역 설정이 있습니다.

게다가 Java로 작성하기 때문에 일부 OS는 Java를 실제 DPI에 알릴 방법이 없다는 것을 명심하십시오 (자신을 모르기 때문에). 따라서 DPI 구성 설정의 필요성은 더욱 분명합니다.