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.
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. –
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
@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