I have an undecorated window that needs to be centered, using this configuration:
Lwjgl3ApplicationConfiguration configuration = Lwjgl3ApplicationConfiguration()
configuration.setIdleFPS(60)
configuration.setBackBufferConfig(8,8,8,8,16,0,0)
configuration.setWindowedMode(1920,1080)
configuration.setTitle("Title")
configuration.setDecorated(false)
configuration.setResizable(false)
Later, in app, through options you can change the size of the window with presets defined from a specific aspect ratio. The resizing is made with this call:
Gdx.graphics.setWindowedMode(width, height)
This seems to keep the window in its original top left corner position (which can be at a random position on screen), but I want it to be centered on the monitor, or a way to move the window to any desired position at will.
The question:
How can I keep the window created by LibGDX with LWJGL3Application centered when changing window size with SetWindowedMode()
#Tenfour04 stated in response to the old answer below that you can get the LWJGL3Window instance with
Lwjgl3Window window = ((Lwjgl3Graphics)Gdx.graphics).getWindow();
You can then use that to set the position during a resize event for example
window.setWindowPos(x, y)
Old answer:
I solved this by reflection
public void setWindowSize(int width, int height) {
Lwjgl3Application app = (Lwjgl3Application) Gdx.app
Field windowfield = app.class.getDeclaredField("currentWindow")
if(windowfield.trySetAccessible()) {
Lwjgl3Window window = windowfield.get(app)
Gdx.graphics.setWindowedMode(width, height)
// Can use context size because of no decorations on window
window.setWindowPos(Gdx.graphics.width/2 - width/2, Gdx.graphics.height/2 - height/2)
}
}
Warning: Even though this works, this is not a good solution. The field of the class is kept private for a reason and not exposing it to the API means that it can change at any update, leaving you with a mess.
That being said, I'm posting this solution for people as desperate as me and because I'm not sure there's another proper solution yet. I will eagerly await a better solution though.
Related
New to Codename One, moving over from Android "native" java development.
I'm trying to create a SideMenu design that loosely resembles the Material side menu, as seen in just about every Google app (e.g. Play Store). Starting with a header image, I can't seem to get rid of some padding on the top and bottom:
The white bars on the top and bottom are unwanted. Current code:
public void start() {
if (current != null) {
current.show();
return;
}
home = new Home();
// SideMenu header BG image
Image headerImage = theme.getImage("bg_navdrawer_header.png");
ScaleImageLabel sideMenuHeaderBg = new ScaleImageLabel(headerImage);
sideMenuHeaderBg.setBackgroundType(Style.BACKGROUND_IMAGE_SCALED_FIT);
// SideMenu header app title
Label sideMenuHeaderLabel = new Label("Title");
sideMenuHeaderLabel.setUIID("SideMenuHeaderTitle");
Container sideMenuHeader = new Container();
sideMenuHeader.add(LayeredLayout.encloseIn(sideMenuHeaderBg, FlowLayout.encloseBottom(sideMenuHeaderLabel)));
home.getToolbar().addComponentToSideMenu(sideMenuHeader);
home.show();
}
The white bars disappear if I use BACKGROUND_IMAGE_SCALED_FILL, but then it doesn't keep aspect ratio - it stretches to fill those two white spaces. (EDIT: It does keep aspect ratio, but it clips the longer dimension). I've tried setting the UIID to "Container" to... everything, makes no difference.
Any ideas?
UPDATE:
For some reason, calling setWidth on the ScaledImageView immediately after setting the background type solved it. Doesn't matter what the width is, any number at all and the "letterboxing" is gone and the height is as it should be.
ScaleImageLabel sideMenuHeaderBg = new ScaleImageLabel(headerImage);
sideMenuHeaderBg.setBackgroundType(Style.BACKGROUND_IMAGE_SCALED_FILL);
sideMenuHeaderBg.setWidth(0);
Going to leave this open in case somebody has a better solution or can at least explain why this is the case, or exactly what is happening since my solution is more of a hack than an actual answer.
BACKGROUND_IMAGE_SCALED_FILL should keep aspect ratio. It resizes the image to "fill" the space's shorter dimension. The longer dimension is clipped.
BACKGROUND_IMAGE_SCALED will stretch to fill the space, but won't keep aspect ratio.
BACKGROUND_IMAGE_SCALED_FIT will also keep aspect ratio. It resizes the image to "fill" the space's longer dimension. The shorter dimension is "letterboxed", as you see in your screenshot.
So I am attempting to make my game to where when launched (from browser), will take up all of the screen in the browser. In my HTML launcher code I have to feed it a width and a height, so I have been trying to access the width and height of the browser frame to initialize the game. So far I haven't gotten anything to work. These are the attempts I made to access the width and height in order.
Gdx.graphics.getWidth() and Gdx.graphics.getHeight()
Gdx.app.getGraphics().getWidth() and Gdx.app.getGraphics().getHeight()
this.getGraphics().getWidth() and this.getGraphics().getHeight()
All of these when used on this code: return new GwtApplicationConfiguration(int width, int height); display nothing. Only when I hard-code a value in does it show anything, and hard-coding doesn't seem like a good way to go for a browser that could be any size.
Alternatively, can these values be set as the resolution (like 1920x1080) and then just use css to strech the game across the entire screen, or is this not the way to go?
In the future I want to make the game resize when the browser re-sizes as well, so I will be adding the same code to the resize event.
You have to use platform specific code...
return new GwtApplicationConfiguration(Window.getClientWidth(), Window.getClientHeight());
source: LibGDX Automatically Scaling GWT Window to Monitor Resolution
Recently we got a issue regarding stretching an ImageButton in LibGDX's Stage API.
We have a graphics-heavy game that can pick a textureatlas based on your screen (either HDPI, MDPI or LDPI etc)
We build our game with 480x854 as virtual resolution and scale nicely using viewports on devices that differ from that.
We explicitly set each sprite size to make sure it scales well regardless what size the source texture is.
However, sometimes it could happen that a texture is slightly larger or smaller than the actual size it is displayed (for instance, a resolution of 320x480 will pick ldpi but the image is slightly smaller than the sprite it's displayed on)
For some reason the ImageButton can't work very well with that.
Here is an example of what I tried (in an imagebutton subclass):
#Override
public void setSize(float w, float h) {
super.setSize(w, h);
if (this.getImage() != null) {
//this.getImageCell().expand().fill();
this.getImage().setSize(w, h);
this.getImage().setScaling(Scaling.stretch);
//this.getImage().invalidate();
this.invalidate();
}
}
What I'm trying to achieve is that when I call button.setSize(300, 320) it will actually stretch the image to become 300x320. But instead, it either shows the button using the original size of the source image (without workaround above) or shows it completely washed / stretched out (also out of proportions) using the workaround above.
I hope someone might have a good fix for this, I'm banging my head on this one for 2 days now :(
Thanks a lot! Have a nice weekend!
Update
I managed to display the image button correctly now but outside a panel I used to have it in. Inside the panel it goes showing up weird again. I'll keep this up-to-date and when I find it myself I'll post a valid answer.
I have some tabs with scrollable panels that contain a series of labels. The labels may be "focused", in which case they are to remain perfectly centered, as tabs are switched, the window is resized, or font size is changed. I have all the math for that done. The only issue is when the code runs. The following function...
public void fixMargins() {
//Top margin:
final int top = (this.getHeight() - this.getVerseBlock(1).getHeight()) / 2;
//Bottom margin:
final int bottom = (this.getHeight() -this.getVerseBlock(this.view.getComponentCount()).getHeight()) / 2;
this.view.setBorder(new EmptyBorder(top, 0, bottom, 0));
//Set scroll bar accordingly:
this.jumpCenter(this.focused);
}
... will work sometimes. Seemingly every time when the window resizes, because dragging it causes an update every pixel. On maximizing, or on switching tabs after a redraw, it is not properly focused because it's using outdated numbers. I've confirmed this with console output.
I know exactly what needs to happen, but I only know an easy way in Node.js, which this certainly is not. Basically:
External value updates - resize, font change, etc;
Wait for layout to be 100% complete, all labels and parents settled into new size;
Apply margins according to new size;
Wait for layout to update 100% again, scrollable range finalized;
Move scroll bar to determined position using current numbers.
The following do not wait for the UI to fully update, for reasons I am unsure of:
revalidate()
doLayout()
SwingUtilities.invokeLater()
I'm about to just throw in a hack job that pauses a thread for one millisecond before running the code, but I figured I'd ask and see if there is any sort of convenient waitForLayoutUpdate() function that I just haven't found yet.
Upon further research, I have discovered that the JLabels specifically are not reporting a correct height at the time that it is checked. This is a known issue with them, but I have yet to find a work-around.
LibGDX uses LWJGL as its backend, so LwjglApplicationConfiguration is used to set the properties of the window (such as resizable, width, height, etc) --- but there doesn't seem to be any setting to be able to set the window's position on the screen.
My game runs on a 1280x720 resolution. My laptop's resolution is 1366x768. When I run the game, a small portion of the game window is hidden at the bottom of the screen out of view. This is easily fixed by dragging the window up, but it would be better if dragging the window weren't necessary, and this could be handled by being able to set the window position.
So if there is any way to set the window's position so that it launches exactly where I want it to be, that would be great. Thanks!
You can set the position of the windo with
config.x = 0;
config.y = 0;