2011-01-16 8 views
13

Ho la seguente applicazione che disegna una regola:Come "correttamente" rilevare DPI di visualizzazione con 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(); } }); 
    } 
} 

ha funzionato bene sul mio vecchio 17" e 20" display, ora ho notato sul mio nuovo LCD 27" , è imprecisa, quindi non ho per cambiare la quarta linea per essere più precisi, non è Toolkit.getDefaultToolkit(). getScreenResolution() si suppone che ottenga il DPI accurato, perché non è corretto, perché la mia app funzioni su altre macchine con schermi e DPI diversi, come per regolare automaticamente la 1.15 che ho inserito manualmente?

PS: non solo il DPI della mia app Java è impreciso, ma anche quando ho guardato diverse altre app su Windows 7 come paint.exe o paint.net, il loro pollice e cm sono anche o nel corretto. Puoi provarli sulla tua macchina.

+0

Le informazioni DPI riportate dal sistema operativo o persino dal driver del display stesso sono spesso imprecise. Probabilmente sei sfortunato per un caso veramente generale. –

+0

Non sono molto sicuro ma invece di 'Toolkit.getDefaultToolkit(). GetScreenSize();', prova ad utilizzarlo per ottenere la dimensione 'GraphicsEnvironment.getLocalGraphicsEnvironment(). GetDefaultScreenDevice(). GetDisplayMode();'. L'ultima istruzione ti darà la modalità di visualizzazione, usala per ottenere altezza e larghezza. – Favonius

+0

@Favonius: Grazie, ma una volta ottenuti, come ottenere il DPI corretto di cui ho bisogno? I numeri sono simili a questi: Default_device Larghezza: 2560 Altezza: 1440 Frequenza di aggiornamento: 59 Profondità bit: 32 , Praticamente le stesse informazioni ottenute da getScreenSize(); – Frank

risposta

8

Problema di driver.

Il DPI reale è noto solo al driver, che lo segnala al sistema operativo, che lo segnala a Java e altre applicazioni. Dal momento che non solo Java ha la scala sbagliata, deve essere il driver.

Questo è vecchio problema. Molte applicazioni grafiche hanno un'impostazione globale "DPI schermo" in cui gli utenti possono regolare il proprio monitor reale.

Inoltre, dal momento che stai scrivendo in Java, tieni presente che alcuni sistemi operativi non hanno modo di comunicare a Java i DPI reali (perché non conoscono se stessi). La necessità di impostare la configurazione DPI è quindi ancora più chiara.

Problemi correlati