False SWING Component Placement in Java with 4K Monitor - java

I have a component placement problem. First I'll try to give (possibly useful) information and then tell you about the main problem:
My System: Windows 8.1 64bit, Java 1.8.0_60 32bit
What I'm trying to do is: After I learn screen resolutions of all connected screens, I'm placing some swing components around the screen. This means that I need to know the resolutions of the screens.
I'm using multiple monitors.
3840 x 2160 (main monitor)
1920 x 1080 (secondary)
I use:
graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();
devices = graphicsEnvironment.getScreenDevices();
And for the main screen device:
devices[i].getDefaultConfiguration().getBounds()
returns [0, 0, 2560, 1440]. Instead of the right values 3840 x 2160.
Interesting thing is;
devices[i].getDisplayMode().getWidth() and getHeight()
returns the right 3840 and 2160 values.
Note: This difference does not happen in any other resolution selection of the screen. For example, if I select 1920 x 1080 for the main screen, both "getDefaultConfiguration().getBounds()" and "getDisplayMode().getWidth()" returns the right values.
Now,
You can say that I'm already getting the right dimensions. So, what is the matter?
The thing is, when I try to position my SWING components, they are placed in wrong positions. For example, an element at [3750, 0, 10, 10] ends up inside the second monitor, while It should have been on the right upper corner of the first screen.
Another example: As you know, a fixed sized component would appear smaller in higher resolutions. Since its pixel percentage related to screen gets smaller, the component itself also looks smaller. For example; When I increase my screen's resolution from 1920x1080 to 2560x1440, my components gets smaller. But, when I increase the resolution from 2560x1440 to 3840x2160; they stay in the same size.
I hope I was clear about the problem.

I know of one Windows 8+ specific feature, which might manifest in that way: per-display DPI setting. The feature is supposed to keep application window at the same size physically, even when dragging them across displays with different density.
This is achieved by rendering the application's window into a intermediate buffer, which then is scaled by the DWM taking the target screen DPI into account.
This feature can be disabled, using following dialog:
It has to be done on the file containing the executable program, which displays any frames. In Java, it's somewhat convoluted, since it's a hosting application. Changing this on java(w).exe should alter the behavior globally.
Typically, this kind of flag adjustment is done by a software installer. It's possible to wrap the java jar into a exe with a thin wrapper. I like launch4j the most for this task. The wrapper exe and the jar file can be wrapped into a installer script, which sets the flag at installation time.

Related

How does default location work? / What is the default monitor?

I'm working on some app that gets the users width for their multiple monitors, assume they don't have any monitors on top, and then provide them with multiple buttons/frames, so that they can black out whichever monitors they wish.
MY ISSUE
All's well and good, apart from location compatability stuff.
If someone has 4 1920 width monitors, how can I position my reference/starting frames at the leftest monitor, so that I can say "proceed 1920 pixels, make a frame, ..."?
You'd think "Use setLocationtoNull, but how does that work?? You'd think it's simply the middle monitor, length/2; but what is the middle monitor!? It can't be totalScreensLength/2, because that'd mean the program is split in half between the monitors! (so it's most likely the middle of the main manitor).
And not using any setLocations, the program is at the top left of the main monitor.... BUT WHAT IS THE MAIN MONITOR??
If I knew how java figured which monitor was "main", that would solve my issue (and no, knowing merely the main monitors resolution via Toolkit.getScreenSize() would not be enough info).
//creating invis black frames
for(int c=0;c<inArr.length;c++){
int xLoc=0;
for(int i=0;i<c;i++){
/**/ xLoc+=resList[i];
}System.out.println(xLoc);
JFrame blackOut=new JFrame();
blkList.add(blackOut);
blackOut.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
blackOut.getContentPane().setBackground(Color.BLACK);
blackOut.setUndecorated(true);
blackOut.setSize(resList[c],5000);
/**/blackOut.setLocation(xLoc-1280,-2000);
blackOut.setVisible(false);
}
This is the code that makes the program work, because it's hardcoded for my setup of 1280,1920,1440.
The issue is at blackOut.setLocation(xLoc-1280,-2000); I must know where exactly the starting frame would be, so I can move the frame to the left, so 'scaling' works. This is what's happening here:
the frame starts at the top left of my middle, 1920 monitor, so I move the frame 1280 pixels left so it is at the top left of my leftest monitor.
Sorry if this is too verbose, just want to give enough detail.
Also, recently discovered this and went into its documentation, but I don't understand how I could use the data, and am unsure if it's able to provide me the information necessary (know what monitor is main, and be able to differentiate monitors, even if they're the same resolution)
This might be a partial answer.
From the linked discovery of yours, you can get the default configuration and bounds of each device by calling graphicsDevice.getDefaultConfiguration().getBounds(). This includes the coordinates / offset of each screen as well as the individual screen size.
In the implementation for GraphicsEnvironment.getScreenDevices() by SunGraphicsEnvironment screen devices are created by iterating over the number of screens and creating a device for each index - the index is passed to each device.

How do you utilize SWT's Hi-DPI support for widget sizing?

Does SWT (or JFace) have a public convenience method for converting conventional units to their scaled counterparts? I've found mention of a DPIUtil class but that's part of an internal namespace
If there's not a convenience method available, then is there a reliable way to access the zoom level? I see there's Device#getDeviceZoom() but that is protected. There is Device#getDPI() which is public so it might be useful. Does that take scaling into consideration, or is it naïve and just declares that DPI is 96 for everything?
I'm applying default sizing hints to some panels and I'd like them to take the monitor scaling setting into consideration. E.g., Say on a regular display I want the default to be 300px, but at 150% scaling I want to calculate it to be 450px. The calculation is obviously simple but I need the multiplier.
NOTE: This is related but different from my previous question How do you utilize SWT's Hi-DPI support for icons? because SWT provides classes to specifically handle this with images.
I haven't found anything other than DPIUtil for determining the scale (zoom) factor.
But you don't normally need this information. Specifying a size of 300px will be automatically scaled to 450px by SWT on a 150 scaled device (and any 150 scaled image you provide will be used). I have an iMac with two screens - a 5k screen scaled at 200 and a 2.5k screen not scaled - SWT apps appear the same size on both.
The scaling is actually done in the OS rather than SWT (at least that is how it works on macOS). The OS scales up the sizes, renders fonts at the higher resolution and uses the high resolution images if available. So programs don't need to do anything other than provide hi-res images.
This way even old programs that don't know about zoomed displays still appear at a sensible size.

Why is OpenGL fixed-function pipeline seeming to occasionally only partially render individual draw calls?

I realize that the OpenGL fixed-function pipeline is thoroughly deprecated by this point, but the engine I'm working with is built upon an old codebase that had never demonstrated any problem of this sort until I upgraded my development machine this month and I'd really rather not rewrite all the rendering architecture when it still fits my needs completely, aside from this bug.
Essentially, while everything in the game I'm developing renders correctly 99.999% of the time, every now and again there will be a single-frame flicker (maybe one frame every 20 seconds or so?). I recorded video to catch a frame-by-frame comparison of what was flickering and discovered that on these sporadic frames, only part of what ought to be an indivisible sprite on my end is being rendered.
An example of what I mean
(correct output on the left, glitchy frame on the right)
And a larger example (note the errors on the left side of the screen)
The engine outputs these draw calls in a fixed order each frame, and yet sometimes some of them appear to be skipped such that things which are drawn later appear, while things which should always be drawn before them do not.
If one looks closely, you can see that all the text-rendering glitches involve skipping blocks of exactly 8 glyphs, but when I peered into the text-rendering code, each complete label is sent between a single pair of glBegin(GL_QUADS) and glEnd(), which to the best of my understanding should be an indivisible action. How can OpenGL render some of those vertices but not others?
Here's the actual code specifically for that label rendering:
glBegin(GL_QUADS);
for (int i = startChar * 8; i < endChar * 8; i+=2)
{
glTexCoord2f(texCoord[i], texCoord[i+1]);
glVertex3f(x + vertCoord[i], y + vertCoord[i+1], z);
}
glEnd();
And yet, 1 frame in 2000 or something will seemingly ignore groups of exactly 32 of these vertices.
I've been stymied trying to figure out any possible cause to this problem, as it's well out of my depth and appears to be essentially 'impossible', as best goes my limited understanding of OpenGL operation (and I want to stress that this code has been unchanged for ages and only began to demonstrate problems when run on my new PC). I'm wondering if anyone could potentially at least point me in the direction of something that could cause this sort of issue....
Edit: Since it was asked, I'm running Windows 10 with an GeForce GTX 1060. Previous system where this bug did not occur was Windows 7 with a Radeon HD 4850, in case this might be relevant.
Well after spending some time on test machine with AMD Radeon R7 to debug similar issue on one of my apps this helped me:
my app was combining transparent and solid objects (just few) using old GL 1.0 api due to compatibility reasons (as with VBO and other stuff there is always some problem in one card or another so the user can always switch to GL 1.0).
We usually use nVidia cards for control PC but this time we had to use AMD and after Installing drivers strange flickering occurs. Part of scene was changing color randomly on each frame render. All the objects where rendered with the same code (even function) and some where OK all the time and some where flickering all the time.
Removing transparency got no effect so that was not the point. AMD where picky about the number and type of vertexes rendered in the past and it seems the behavior returns (after some constant number of faces rendered). I also remembered on similar problem with Intel which was really picky about color description.
So I combined both errors and find the place where my App start to do strange thing and place there
glColor4f(0.0,0.0,0.0,0.0);
To reset the Alpha channel (which was not used in that part of code at all just in the transparency and reseted correctly there). And it solved my issues (at least for now).
Without MCVE I can only guess if your issue is related to this but you might try to add some dummy glColor4f calls through out your rendering code to see if the behavior changes ...
To help emphasize your problem try to increase the number of rendered faces per frame (without clear screen or buffer swap) as it tends to be tighted to number of rendered faces (processed vertexes).

Low quality icon in taskbar of a Stage. JavaFX

Why Stage icon so low quality? The original image is much better.
How to fix it?
I used this code to setting image as stage icon:
stage.getIcons().add(new Image("/res/app_icon.png"));
Screenshot:
Original icon:
Update
Unfortunately the implementation of the icon chooser in JavaFX 8 does not always choose the best icon size for the application from the list of available icons.
See:
JDK-8091186 Windows 7 taskbar icon is blurry.
JDK-8087459 Ugly icon in Windows task bar.
The issues are (currently) scheduled to be addressed in Java 9.
Some comments on those issues are:
Indeed, Glass currently supports assigning only one icon for a window, it won't allow one to assign a set of differently sized icons. This feature needs to be implemented in Glass.
--
I have noticed that when setting multiple icons, only the last one in the list returned by getIcons() is used. It doesn't matter if other icons, with better resolutions are in the list.
If you provide a list of icons of different sizes, try putting the size you expect to be used most last in the list (perhaps order the list from smallest to largest or place a 48x48 icon, which is the size used in the quick launch area on Windows 7, as the last or only element in the list). Unfortunately, I do not have access to a Windows machine to test the best icon size for that platform.
Icon Guidelines (but be aware of the information in the update above):
Provide a set of high quality icons of different sizes to the list
returned from
stage.getIcons().
The best fit size will be chosen by the runtime.
Use standard icon
sizes which most operating systems can work with without further scaling (for
instance item size is a power of two or 48x48).
Use high quality source images (the original source image in your question seems a bit blurry to me).
For very small icons, sometimes a pure scale of a larger icon to a smaller size is not best. Sometimes it is best for the icon designer to clean up and remove intricate details from the small icon, which might be OK in a larger icon - see the discussion on icon size on Pushing Pixels to help understand why.
Info on what icon sizes are used by what OSes is in this icon handbook.
stage.getIcons().addAll(
new Image("/res/app_icon64x64.png"),
new Image("/res/app_icon32x32.png"),
new Image("/res/app_icon16x16.png")
);
A great source of high quality icons in a variety of sizes is http://www.iconarchive.com, for example this refresh icon.

Get screen info in windows 7

In my app I'm using swing and awt. I am setting the size (and position) of the window I'm creating based on toolkit.getScreenSize() and this works fine. But I would like to deal with the size of the windows 7 task bar at the bottom (or wherever) of the screen. I can not seem to find out how to do this. Anyone know how I can get the size if the task bar?
You'll want to look at java.awt.GraphicsEnvironment#getMaximumWindowBounds(), which returns the bounds of the screen area excluding the area covered by "objects in the native windowing system such as task bars and menu bars".
Per Matthew's post I got going down the right path. I was able to determine the windows bounds of the task bar with:
Insets scnMax = getToolkit().getScreenInsets(getGraphicsConfiguration());
taskBarSize = scnMax.bottom;
and then subtracting that value from a getScreenSize() height value to help me position the app window correctly.
Don't have a multi monitor system so I'm not sure how this works there but I will have to test that out.

Categories

Resources