I want to set the size of a JFrame such that the contentPane is the desired size. JFrame.setSize() doesn't take the window decorations into account, so the contentPane is slightly too small. The size of the window decorations are platform and theme specific, so it's bad news to try to manually account for them.
JFrame.getContentPane().setSize() fails because it's managed.
Ideas?
Thanks!
In Java 5 and later this is the easiest method:
JFrame frame = new JFrame("Content Pane Size Example");
frame.getContentPane().setPreferredSize(new Dimension(400, 300));
frame.pack();
frame.setVisible(true);
As always the above should be executed in the EDT.
If you want to do it on your own then in your Frame type:
this.setLayour(null);
this.pack();
Insets insets = this.getInsets();
this.setBounds(0,0, insets.left + width + insets.right, insets.top + height + insets.bottom);
this.setLocationRelativeTo(null);
Related
I have a non-trivial Swing app running on Windows that has an issue with window resizing: when I maximize the window and then restore it, the main panel doesn't resize properly with the window. The panel stays between the fullscreen size and the current size until I drag the window border around and force a few more resize attempts. I found that the minimal repro case is close to the following:
JAVA
JFrame mainWindow = new JFrame("TEST");
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
mainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel outerPanel = new JPanel();
outerPanel.setLayout(new MigLayout("fill, insets 0", "[grow]", "[grow]"));
JPanel innerPanel = new JPanel();
innerPanel.setLayout(new MigLayout("fill, insets 10", "[75%:75%:100%]", "[grow]"));
JTextArea text = new JTextArea("text 1");
innerPanel.add(text, "cell 0 0, grow");
outerPanel.add(innerPanel, "cell 0 0, grow");
mainWindow.getContentPane().add(outerPanel);
mainWindow.pack();
mainWindow.setLocationRelativeTo(null);
mainWindow.setVisible(true);
If I put ComponentListeners on text, innerPanel, and outerPanel here and print out each component's width on resize, I can see that outerPanel resizes properly, but innerPanel and text both only shrink by an amount proportionate to how far they are from the correct size each update. This seems to be caused by the minimum-size column constraint on innerPanel being set to a value such that the minimum width when in fullscreen is larger than the maximum width of the window when not in fullscreen. When I run this code, I get a 120px-wide window that maximizes to 2560px; it doesn't repro if the minimum-size constraint is 1% (25.6px when maximized), but it does if the minimum-size is 5% (128px).
My question is, why? Why does the resize not initially work properly but eventually converge to the right value if I make enough incremental changes to the stretched dimension? And how can I get my minimum-size constraints to work when maximizing and restoring the window?
For the places in my actual program that are exhibiting the problem, there's a RecordingListPanel inside of a JTabbedPane inside of the mainPanel JPanel in MainWindow inside of the metaPanel JPanel in MainWindow. Here are the relevant excerpts:
JAVA
// RecordingListPanel
setLayout(new MigLayout("fill, insets 2", "[75%:75%:90%]2[10%::300]", "[][grow]"));
//tabbedPane
tabbedPane.add("Recordings", recordingListPanel);
// mainPanel
mainLayout = new CardLayout();
mainPanel.setLayout(mainLayout);
mainPanel.add(tabbedPane, "mainView");
// metaPanel
metaPanel.setLayout(new MigLayout("fill, insets 0 0 0 0", "[grow]", "[grow][30!]"));
metaPanel.add(mainPanel, "cell 0 0, grow");
mainFrame.getContentPane().add(metaPanel);
Problem: Windows are cloned on screen, when set the position of the window.
In my ApplicationAdapter.create() I create a Window and add it to the stage:
window = new Window("titleWindow", skin);
stage.addActor(window);
in the ApplicationAdapter.render() I reposition the window as follow:
if(rendercount % 100 == 0){
window.setPosition(100 + count,300);
}
rendercount++
Why my window is cloned on my screen ? I just wanted to move it.
Are you clearing your screen in the beginnig of the render() method?
Gdx.gl.glClearColor(0, 0, 0.5f, 0.6f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
Helllo, im new to libgdx, i need some help, if my desktoplauncher resolution is 480x320, sprite takes 80% of the screen, but if 1280x720, sprite is small, i need to make it look the same at all resoltions so how do i do this? may be easy for you, but not for my, im using libgdx 1.3.1
this is my libgdx code:
SpriteBatch batch;
Texture img;
Sprite mysprite;
#Override
public void create ()
{
batch = new SpriteBatch();
img = new Texture("badlogic.jpg");
mysprite = new Sprite(img);
stage = new Stage(new StretchViewport(480, 320));
}
StretchViewport myviewport = new StretchViewport(480, 320);
public void resize(int width, int height)
{
// use true here to center the camera
// that's what you probably want in case of a UI
stage.setViewport(myviewport);
stage.getCamera().position.set(640/2, 480/2, 0);
}
private Stage stage;
#Override
public void render ()
{
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
mysprite.draw(batch);
batch.end();
}
You are allready using the right thing: Viewport.
There are different Viewport classes, some of them support working with a virtual screen size, which is what you are looking for.
What is a virtual screen size? Well it is the screen size your code is working with and which is then scaled up to match the real resolution.
Basicly you can work with your own units and they are then automatically scaled up to match pixels.
I guess in your case there are 2 possible Viewport-types:
- StretchViewport supports virtual screen sizes and scales it up to match the real screen size and the real aspect ratio. If the real aspect ration does not match the virtual one the Sprites will be stretched, which could look strange.
- FitViewport is the same as the StretchViewport, but it will keep the aspect ratio. If the real aspect ration does not match the virtual one, black borders will appear.
How to use it:
First you need to create it:
myViewport = new StretchViewport(VIRTUAL_WIDTH, VIRTUAL_HEIGHT);
Then set the Stages Viewport:
stage = new Stage(myViewport);
In the resize method you need to update your Viewport:
myViewport.update(width, height);
Thats all.
The stage now uses the Viewport and its camera to render. You don't need to touch the camera, unless you need to move it arround.
So your errors are:
stage = new Stage(new StretchViewport(480, 320));
Which creates a new StretchViewport you don't store/use.
stage.setViewport(myviewport);
You only need to set it once, when you create the stage
You never call update(width, height) for the Viewport.
I'm attempting to use LibGDX Stage for my GUI elements, but I'm having loads of difficulty getting it to render properly. Right now, I'm attempting to render a chat window in the lower left corner of the screen.
Here is the construction of the GUI objects:
stage = new Stage();
stage.setCamera(controller.getCamera());
uiSkin = new Skin(Gdx.files.internal("res/gui/skin/uiskin.json"));
Table table = new Table(uiSkin);
stage.addActor(table);
table.setSize(300, 260);
table.setPosition(0, 0);
table.setFillParent(false);
table.bottom();
table.left();
table.pad(10);
lblChatLabel = new Label("", uiSkin);
lblChatLabel.setWrap(true);
final ScrollPane scroll = new ScrollPane(lblChatLabel, uiSkin);
txtChatBar = new TextField("do a chat", uiSkin);
txtChatBar.setName("txtChatBar");
table.add(txtChatBar).width(300f);
table.row();
table.add(scroll).expand().fill().colspan(4);
txtChatBar.addListener(new InputListener() {
public boolean keyDown(InputEvent event, int keycode) {
if (keycode == Input.Keys.ENTER) {
sendMessage();
// Close the chat bar
showChat = false;
return true;
}
return false;
}
});
And here is my render() method:
Log.debug("void", "x: " + stage.getCamera().position.x + ", y: " + stage.getCamera().position.y);
stage.act();
for (Actor a : stage.getActors()) {
a.draw(spriteBatch, 1);
}
In another section of code elsewhere, the game's camera object is translated to center on the player:
camera.translate(targetPosition.x, targetPosition.y);
camera.update();
So that all said, the chat window renders properly, but it only does so at 0, 0. I've also changed called stage.draw() rather than iterate through the Actors individually, but that causes the same issue. Here is a screenshot illustrating the issue:
http://i.imgur.com/8uz5lV6.jpg
Finally, I've tried to translate the stage manually by setting the viewport, but that causes an even weirder issue.
float cx = controller.getCamera().getX();
float cy = controller.getCamera().getY();
float width = controller.getCamera().viewportWidth;
float height = controller.getCamera().viewportHeight;
stage.act();
stage.setViewport(width, height, true, cx, cy, width, height);
stage.draw();
Image here:
http://i.imgur.com/JpSLq1s.jpg
Certainly I am doing something wrong, but I have no idea at this point. I would have assumed that the stage follows the Camera translation, but that doesn't appear to be the case. Any suggestions are welcome! Thanks!
I believe the issue is this line of code:
stage.setCamera(controller.getCamera());
If I'm reading correctly, you want the chat window to always render from (0,0), no matter where the camera is on the screen. If that's the case, then the stage shouldn't have any relation with the camera, which moves around and just further complicates getting the stage in the right position to be rendered properly.
Without that line of code, you should be able to just call
stage.act();
stage.draw();
and it should work fine.
I'm trying to add an image to a sprite then add it to the grid. The original size of the image is 276x202. However when it's been added to the grid it increases in size.
http://i.imgur.com/P1Jlq.png
The result is
http://i.imgur.com/0UPBH.png
public class main extends MovieClip
{
public function main()
{
var view:IsoView = new IsoView();
view.setSize((stage.stageWidth), stage.stageHeight);
view.clipContent = true;
addChild(view);
var gridHolder:IsoScene = new IsoScene();
view.addScene(gridHolder);
var scene:IsoScene = new IsoScene();
view.addScene(scene);
graphics.beginFill(0x000000, 1);
graphics.drawRect(0, 0, 800, 600);graphics.endFill();
var grid:IsoGrid = new IsoGrid();
grid.cellSize = 40;
grid.setGridSize(20, 20, 0);
gridHolder.addChild(grid);
gridHolder.render();
//var box:IsoBox = new IsoBox();
//box.setSize(40, 40, 40);
//box.moveTo(80, 80, 0);
//scene.addChild(box);
var player:IsoSprite;
var myLoader:Loader;
myLoader=new Loader();
myLoader.load(new URLRequest('imgs/DesertTankNE.png'));
//myLoader.width = 5; //Makes image disappear no matter what value is set.
//myLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, OnComplete); //Doesn't change anything if we say on completion of loading image add it to the sprite.
player = new IsoSprite();
player.sprites = [myLoader];
//player.setSize(1,1,0); //Doesn't seem to affect anything no matter what size specified.
//player.width = 2; //Same as above
scene.addChild(player);
scene.render();
}
}
I've tried setting the width and height of the image when loading it and also tried setting the size of the sprite. The former makes the image not appear no matter what value is set and the latter doesn't seem to affect anything.
There is absolutely nothing wrong with your as3isolib code, and the image is not being resized in any way by code. Compare the tank image to the size of the grid cells (which should be 20 pixels width by 20 pixels height) and you should see that their relative sizes are ok.
The only problem there is that the whole flash stage is being resized. Are you testing your flash movie on the browser perhaps? Make sure you aren't setting the flash movie's width and height as 100% of its container in the HTML. If the flash movie is in a div and flash is told to be a width and height of 100%, it will stretch out to whatever size the div is.
Seeing your code I think you want your stage size to be 800x600; set your flash movie to those dimensions using the metatag SWF, for example:
[SWF(width="800", height="600", frameRate="30", backgroundColor="#FFFFFF")]
If you are using Flash Builder, you might need to clean your project a couple of times (Project -> Clean) to clear the previous compiler settings. Test your SWF movie outside of the broswer (double click the SWF file to open it on your local flash player) and make sure it has the proper dimensions. You should see the tank and the grid cells the right size now.
If you want to test it in the browser, don't use the HTML wrapper generated by Flash Builder (or Flash Pro). Make your own html using swfobject and set the correct width and height, for example:
<script type="text/javascript">
swfobject.embedSWF("myIsoTank.swf", "flash_container_div", "800", "600", "10", "expressInstall.swf");
</script>
This should get rid of your problem.