Nested MigLayouts stretch out of bounds when restoring from fullscreen - swing

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);

Related

scala.swing: Trying to scale images to window size, but size returns 0

It should probably go without saying, but I'm fairly new to swing.
I'm trying to make a simple little thing which will display two images side by side, as large as the window will allow.
In theory what happening is:
We get an imageIcon, in this case 001.jpg.
We figure out the ratio of width/height of the imageIcon.
We turn the imageIcon into an image.
We turn that image into a new correctly sized image.
We turn that image back into an image icon.
This all breaks down because the only way I've found to get the window size is size, but that keeps returning 0s.
This is the code I have right now:
class UI extends MainFrame {
title = "Matt's window header"
preferredSize = new Dimension(1920, 1080)
var imageIcon = new ImageIcon("001.jpg")
val imgRatio = imageIcon.getIconWidth.toDouble / imageIcon.getIconHeight.toDouble
println(size)
pack()
println(imgRatio)
val image = imageIcon.getImage()
val newimg = image.getScaledInstance(size.width, (size.width * imgRatio.toInt), java.awt.Image.SCALE_SMOOTH)
imageIcon = new ImageIcon(newimg)
contents = new Label {
icon = imageIcon
}
}
As an aside, it would be great if someone could give me info about how to load a different image, instead of just 001.jpg.
sizeis not determined at the point you are accessing it.
However, preferredSizeis. If you add println(preferredSize) you will get the Dimensions you just set.

AS3 - Open several / multiple windows + Detect how many screens are on the system

I would like to know if it is possible to create an air desktop app that when opened detects the amount of screens connected to the computer, opens one "controller" window on the primary screen and one "presentation" window in full screen mode on the secondary screen.
At the moment the only work around I have found is to do two apps that communicate with each other through LocalConnection
To detect the amount of screens in AIR:
flash.display.Screen.screens.length //Screen.screens property is an array of all the screens on the system
//you can get things like the bounds, color depth etc
To open a second window from your main window, here is an example:
var myContent:Sprite = new Sprite(); //this would be whatever display object you want on the new window.
//SOME OPTIONAL WINDOW OPTIONS
var windowOptions:NativeWindowInitOptions = new NativeWindowInitOptions();
windowOptions.owner = stage.nativeWindow; //setting the owner to the main window means that if this main window is closed, it will also close this new window
windowOptions.renderMode = NativeWindowRenderMode.AUTO;
windowOptions.systemChrome = NativeWindowSystemChrome.STANDARD;
//Create the new window
var newScreen:NativeWindow = new NativeWindow(windowOptions);
newScreen.title = "My New Window";
newScreen.stage.addChild(content);
//the screen to put it on
var screen:Screen = Screen.screens[Screen.screens.length - 1]; //get a reference to the last screen
//move the new window to the desired screen
newScreen.x = (screen.bounds.left);
newScreen.y = (screen.bounds.top);
//focus the new window
newScreen.activate();
For full screen, you either maximize the window, or enter flash's full screen mode:
newScreen.maximize();
newScreen.stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
You can work with the content of the window just like any other display object. You can add as many things to the windows stage as you'd like.

Force JScrollPane and JPanel to repaint

I have a JScrollPane that holds a JPanel. The layout on the JPanel is a GridBagLayout. On that JPanel, I add a number of custom components - each is a JPanel with 3 JLabels.
The first time in the program I lay all of this out, it works fine. When I invoke the code to add another custom component to the JPanel, the panel appears empty, but I can determine by examining the contents of the JPanel that my components are actually there. If I resize the JDialog in which this all sites, the JPanel will paint properly. It also works if I scroll the JScrollPane horizontally even a tiny bit.
I use the same method for the initial layout as I do when adding an item.
I've tried various combinations of repaint(), invalidate() and doLayout() but nothing seems to work all the time. I've run into this situation before and have never been able to fully solve it. Any suggestions?
Running under OpenJDK 7u25. Below is the code that lays out the scroll pane and panel.
private void displayRelatedBug(ArrayList<Bug> a_bugs) {
// sort the bugs by ID
ArrayList<Bug> l_sorted = new ArrayList<>(a_bugs);
Collections.sort(l_sorted);
pnlRelatedBugs.removeAll();
pnlRelatedBugs.setLayout(new GridBagLayout());
GridBagConstraints l_gbc = new GridBagConstraints();
l_gbc.gridx = 0;
l_gbc.gridy = 0;
l_gbc.gridwidth = 1;
l_gbc.gridheight = 1;
l_gbc.anchor = GridBagConstraints.NORTHWEST;
l_gbc.fill = GridBagConstraints.NONE;
l_gbc.insets = new Insets(3, 4, 0, 0);
for (Bug r : l_sorted) {
pnlRelatedBugs.add(new RelatedBugDisplay(r, this), l_gbc);
l_gbc.gridy++;
}
// add a filler at the bottom to push it up
l_gbc.weighty = 1.0;
pnlRelatedBugs.add(new MMPanel(), l_gbc);
// add a filler on the right to push them left
l_gbc.weighty = 0.0;
l_gbc.weightx = 1.0;
l_gbc.gridx++;
pnlRelatedBugs.add(new MMPanel(), l_gbc);
// try in vain to make it show up!!!
pnlRelatedBugs.invalidate();
pnlRelatedBugs.doLayout();
pnlRelatedBugs.repaint();
scrollerRelatedBugs.doLayout();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
pnlRelatedBugs.repaint();
scrollerRelatedBugs.repaint();
// this seems to help if the scroll bar is showing
scrollerRelatedBugs.getHorizontalScrollBar().setValue(1);
scrollerRelatedBugs.getHorizontalScrollBar().setValue(0);
}
});
}
Whenever you add/remove components from a visible panel, the basic code is:
panel.remove(...);
panel.add(...);
panel.revalidate();
panel.repaint();
Without a proper SSCCE we can't really tell what your code is doing.
If you do add/remove/replace/others actions with components on showing container, you must to revalidate and repaint your container, to which you add components for proper displaying.

AS3 As3IsoLib Adding Sprite

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.

Setting the size of a ContentPane (inside of a JFrame)

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);