2011-01-16 23 views
13

Tengo el siguiente aplicación que dibuja una regla:¿Cómo detectar "correctamente" el DPI de la pantalla 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(); } }); 
    } 
} 

funcionó bien en mis viejos 17" y 20" pantallas, ahora que he notado en mi nuevo LCD 27" , es inexacta, por lo que tengo para cambiar la 4ª línea para ser más preciso, no se supone que Toolkit.getDefaultToolkit(). getScreenResolution() obtenga el DPI exacto, por qué no es correcto, para que mi aplicación funcione en otras máquinas con diferentes tamaños de pantalla y DPI, cómo para ajustar automáticamente el 1.15 que he puesto manualmente?

PD: No solo el DPI de mi aplicación Java es inexacto, sino que también cuando miré varias otras aplicaciones en Windows 7 como paint.exe o paint.net, su pulgada y cm son als o en correcto. Puedes probarlos en tu máquina.

+0

La información de DPI informada por el sistema operativo o incluso por el controlador de pantalla en sí es a menudo inexacta. Probablemente no tengas suerte en un caso realmente general. –

+0

No estoy muy seguro, pero en lugar de 'Toolkit.getDefaultToolkit(). GetScreenSize();', intente usar esto para obtener el tamaño 'GraphicsEnvironment.getLocalGraphicsEnvironment(). GetDefaultScreenDevice(). GetDisplayMode();'. La última instrucción le dará el modo de visualización, úsela para obtener altura y ancho. – Favonius

+0

@Favonius: Gracias, pero una vez que los obtuve, ¿cómo puedo obtener el DPI exacto que necesito? Los números se ven así: Default_device Ancho: 2560 Altura: 1440 Frecuencia de actualización: 59 Profundidad del bit: 32 , Casi la misma información que recibí de getScreenSize(); – Frank

Respuesta

8

Problema de conductor.

El DPI verdadero es conocido solo por el controlador, que lo informa al sistema operativo, que lo informa a Java y a otras aplicaciones. Como no solo Java tiene la escala incorrecta, debe ser el controlador.

Este es un viejo problema. Muchas aplicaciones gráficas tienen una configuración global "pantalla DPI" donde los usuarios pueden ajustar su monitor real.

Además, como está escribiendo en Java, tenga en cuenta que algunos SO no tienen forma de decirle a Java el DPI real (porque no se conocen a sí mismos). La necesidad de configuración de DPI es, por tanto, aún más clara.

Cuestiones relacionadas