B4J Question Porting Reflection code to B4j

udg

Expert
Licensed User
Longtime User
Hi all,

I'm in the process to port an old B4A lib of mine to B4J. Unfortunately, it uses the Reflection library to compute the display metrics of the device it runs on.
How could I translate the following sub to B4J? Thank you.

B4X:
'returns Display metrics in inches or millimeters
Private Sub getDisplayMetrics(Xaxis As Boolean, UnitInches As Boolean) As Float
  Dim xdpi, ydpi As Float
  Dim r As Reflector
  r.Target = r.GetContext
  r.Target = r.RunMethod("getResources")
  r.Target = r.RunMethod("getDisplayMetrics")
  xdpi=r.GetField("xdpi")  'is xdpi an int or a float?
  ydpi=r.GetField("ydpi")
   If Xaxis Then
    If UnitInches Then Return xdpi Else Return dpi2dpmm(xdpi)
   Else
    If UnitInches Then Return ydpi Else Return dpi2dpmm(ydpi)
   End If
End Sub
 

Roycefer

Well-Known Member
Licensed User
Longtime User
The jAWTRobot library has a bunch of screen-related functions that allow you to get the resolutions of multiple-monitor setups, capture screenshots, etc...
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
If you just want the dpi you can use
B4X:
Dim screen As JavaObject
 Log(screen.InitializeStatic("javafx.stage.Screen").RunMethodJO("getPrimary",Null).RunMethod("getDpi",Null))
 
Upvote 0

udg

Expert
Licensed User
Longtime User
Hi all,
thank you for your hints. I still have to check Roycefer's lib.
In the meanwhile I try to explain better what is my need: to draw a line with exact given "dimensions", so a bar whose height is supposed to be 3.47mm and thick 0.33mm appears so on any device. The use of the code in post #1 let me do that on Android devices, but when it comes to B4J and java it seems there's no equivalent.
Please find below the getDisplayMetrics along with values from my Huawey Ascend Y550 phone
B4X:
'returns Display metrics in inches or millimeters
Private Sub getDisplayMetrics(Xaxis As Boolean, UnitInches As Boolean) As Float
  Dim xdpi, ydpi As Float
  Dim r As Reflector
  r.Target = r.GetContext
  r.Target = r.RunMethod("getResources")
  r.Target = r.RunMethod("getDisplayMetrics")
  xdpi=r.GetField("xdpi")  
  ydpi=r.GetField("ydpi")
   Log("------Android data -----")
   Log(r.GetField("densityDpi"))   '240 dpi
   Log(r.GetField("widthPixels"))   '480 px
   Log(r.GetField("heightPixels"))  '854 px
   Log(r.GetField("xdpi"))            '221.672  The exact physical pixels per inch of the screen in the X dimension.  
   Log(r.GetField("ydpi"))            '219.107  The exact physical pixels per inch of the screen in the Y dimension.
Note that widthPixels and heightPixels switch hwen rotating the phone, while other values stay the same.

When it comes to B4J and java I tried the following (my Aspire 5740G notebook display is set to 1366x768px) :
B4X:
Private Sub DisplayMetrics2
   Log("------ java.awt.Toolkit data -------")
   Dim jo As JavaObject
   jo.InitializeStatic("java.awt.Toolkit")
   Dim toolkit As JavaObject = jo.RunMethod("getDefaultToolkit", Null)
   Dim ScreenRes As Int = toolkit.RunMethod("getScreenResolution", Null)
   Log("screenRes: "&ScreenRes) '--> 96dpi
   Dim Screensize As JavaObject = toolkit.RunMethod("getScreenSize", Null)
   Dim jo2 As JavaObject = Screensize
   Log("width: "&jo2.RunMethod("getWidth",Null))  '1366px
   Log("height: "&jo2.RunMethod("getHeight",Null)) '768px
   Log("------ javafx.stage.Screen data -------")
   Dim screen As JavaObject
  Log(screen.InitializeStatic("javafx.stage.Screen").RunMethodJO("getPrimary",Null).RunMethod("getDpi",Null))
End Sub

Comparing these values with those from Android, it's like reading widthPixels, heightPixels and densityDpi (an approximate value). But nothing near xdpi and ydpi.
So, how am I supposed to draw a line with exact given stroke width and height?

Edit: I did a quick test making use of ScreenRes and it apparently worked. Tomorrow I hope to have some spare time to write a better test to upload here.

udg
 
Last edited:
Upvote 0

udg

Expert
Licensed User
Longtime User
Hi all,
please find attached a B4J project that should demonstrate how the Screen Resolution value (on a PC notebook) appears to be able to produce objects of a specified size.
My test was to draw a 7 x 2 cm rectangle and switch my monitor resolution from 800 x 600 px to 1366 to 768 px verifying with a ruler that the object stayed 7x2cm.
That surprised me. Can you confirm my findings?

BTW, should I believe that my notebook's monitor sports the same 96dpi res both horizontally and vertically?

udg
 

Attachments

  • TestFixedDimension.zip
    1.1 KB · Views: 259
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
Per proporzioni pixel si intende la larghezza (x) del pixel rispetto all'altezza (y). Un pixel quadrato ha una proporzione di 1:1, ma un pixel non quadrato (rettangolare) non ha larghezza e altezza uguali. Questo concetto è analogo al concetto di proporzioni dei fotogrammi, che indicano la larghezza totale di un'immagine rispetto all'altezza. Poiché in genere i pixel di una televisione sono rettangolari e quelli di un computer sono quadrati, le immagini...

[Microsoft]

(generally they are square)




https://it.wikipedia.org/wiki/Pixel
I pixel sugli schermi dei computer sono in genere quadrati, ma i pixel utilizzati nel video digitale hanno forma non quadrata,...
 
Upvote 0

DarkMann

Member
Licensed User
Longtime User
Hi all,
please find attached a B4J project that should demonstrate how the Screen Resolution value (on a PC notebook) appears to be able to produce objects of a specified size.
My test was to draw a 7 x 2 cm rectangle and switch my monitor resolution from 800 x 600 px to 1366 to 768 px verifying with a ruler that the object stayed 7x2cm.
That surprised me. Can you confirm my findings?

Just running it on my old monitor: get the following log

Program started.
------ java.awt.Toolkit data -------
screenRes: 96
width: 1400.0
height: 1050.0
------ javafx.stage.Screen data -------
87.0

Dimensions on the screen are 7.5 x 2.2 approx. definitely bigger than 7x2 though. For reference the screen is actually 16 inches x 12 inches exactly - 20 inch diagonal and that works out at 87.5dpi but reports at 96 - pretty close to the difference in size I measured for your 7x2 box.

BTW, should I believe that my notebook's monitor sports the same 96dpi res both horizontally and vertically?

I've always understood that 96dpi was just a guide figure that Microsoft picked for windows to use as a default. I've never expected it to be accurate except on certain displays by luck. I have even seen programs that allow you to set it yourself - Scribus springs to mind - so you can have accurate WYSIWYG for DTP, etc.

EDIT: Use the javafx.stage.screen.data figure and it comes out almost perfect on my screen here.

HTH, David
 
Last edited:
Upvote 0

udg

Expert
Licensed User
Longtime User
@DarkMann , @LucaMs : thank you guys!

From David's findings we should accept the idea that javafx.stage.screen is more accurate than java.awt.Toolkit when it comes to display resolution but both are not exact values as opposed to the ones provided by the Android APIs.
That leaves open the original question: how to draw a line or rectangle of a precise given size using java on a PC/MAC/Linux display.

For now, I'll use @Daestrum 's solution.

Thanks everybody.
 
Upvote 0
Top