Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to compute SWT widget size according to Windows DPI

Tags:

java

layout

dpi

swt

the problem that I'm facing is that when I'm changing the values of DPI in personalization->display->custom dpi to a value greater or equal with 110%, my label are not fully visibile any more. I'm setting the height and width of the label via .setLayoutData(). When the dpi values are back to normal, this problem never show up. My operating system: Windows 7 x64, SWT libraries: swt-4.3-win32-win32-x86.zip. Eclipse IDE version: Eclipse RCP Kepler, Java: 1.6

This is how I am setting the layout data of my label

public GridData buildENodeBTopLabelGridData() {
   eNBTopLabelGridData = new GridData(SWT.FILL, SWT.FILL, true, true);
   eNBTopLabelGridData.heightHint = 17;
   eNBTopLabelGridData.widthHint = 200;
   return eNBTopLabelGridData;

}

And this is how my widgets look before I change the DPI (default values -> 100%) http://img194.imageshack.us/img194/3134/e26e.png And this is how my widgets are looking at a greater value of DPI (110% in this case) http://imageshack.us/photo/my-images/89/1o2t.png/

Sorry if I've made mistakes regarding the place where to ask a question or the format of my question. Thanks in advance!

like image 650
Bogdan Avatar asked Nov 11 '13 06:11

Bogdan


1 Answers

Although it's an old question, this was one of the first I stumbled upon while looking for a solution to this, so I want to share my results. I developed this for an absolute (null) layout however, not a GridLayout, so it will have to be tweaked for other layouts. The general idea may help though.

SWT has an easy way of fetching the current DPI of the OS, being Display.getDefault().getDPI(). In Windows, the default DPI (at 100%) is 96. I therefore used this as a starting point to compare the current DPI with the default DPI, and scale each widget based on the result.

//I used x here since x and y are always* the same.

public static final int DPI_CURRENT = Display.getDefault().getDPI().x;
public static final float DPI_DEFAULT = 96.0f;
public static final float DPI_SCALE = DPI_CURRENT / DPI_DEFAULT;

This returns DPI_SCALE with a value of 1.0 if set to 100%, 1.5 if set to 150% etc.

Running this through a loop to scale each component within the application window (and the window itself) provided me with the desired results.

public static void scaleToDpi(Composite composite) {
    for(Control control : composite.getChildren()) {
        if(control instanceof Composite) {
            scaleToDpi((Composite) control);
        }
        scaleControl(control);
    }
}

private static void scaleControl(Control control) {
    int x = (int) (control.getLocation().x * DPI_SCALE);
    int y = (int) (control.getLocation().y * DPI_SCALE);
    int w = (int) (control.getSize().x * DPI_SCALE);
    int h = (int) (control.getSize().y * DPI_SCALE);

    control.setBounds(x, y, w, h);
}

This assumes that the application is designed for 100% DPI using absolute positioning and has set up the size of each widget before running the scaling via scaleToDpi(shell);

I hope this information is useful to someone, even if it doesn't directly relate to GridLayout. Thanks for reading my first answer here too!

*The x and y of the DPI may not always be the same in rare cases (I've heard).

like image 58
Magnus Bull Avatar answered Nov 15 '22 09:11

Magnus Bull