Question 1:
I am writing a program to use an absolute layout because I need to reposition a JLabel at runtime. I have tried to understand the following java demo program (from Oracle Java Tutorials):
http://docs.oracle.com/javase/tutorial/displayCode.html?code=http://docs.oracle.com/javase/tutorial/uiswing/examples/layout/AbsoluteLayoutDemoProject/src/layout/AbsoluteLayoutDemo.java
It suggests the following:
//Size and display the window.
Insets insets = frame.getInsets();
frame.setSize(300 + insets.left + insets.right, 125 + insets.top + insets.bottom);
frame.setVisible(true);
The frame is not set to be visible before the insets values are calculated, so they are all 0 (zero), am I getting it right?
I have tried to use frame.setSize(300, 125); to replace the code and Eclipse gives me the same result (the same window size as I have observed). Is it wrong to have setSize before setVisible?
Question 2:
In my own program, I have the following code segment:
JFrame frame = new JFrame();
JPanel panel = new JPanel();
JLabel moving_label = new JLabel();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
panel.setLayout(null);
frame.add(panel);
panel.add(moving_label);
moving_label.setBounds(150, 150, 50, 50);
moving_label.setIcon(img);
frame.setVisible(true);
frame.setBounds(100, 100, 300+frame.getInsets().left+frame.getInsets().right,
300+frame.getInsets().top+frame.getInsets().bottom);
//I don't need to have panel.validate() or panel.repaint(), right?
a) Is the above code segment in a correct order (I am a newbie of java's Swing GUI)?
b) I am using Eclipse on my MacBook Pro to run Java programs. I have 40 JLabels (each with an ImageIcon) in a JPanel in a JFrame. If I use the above codes to generate the GUI, it takes half a second to show all JLabels after the window is displayed. Why aren't the JLabels shown at the same time the window is displayed?
Any help will be appreciated. Thank you so much for your time :)
The frame is not set to be visible before the insets values are calculated, so they are all 0 (zero), am I getting it right?
Correct, components do not have a size until the frame has been realized, which means the native objects on the OS you are running on have been created. This is done when you pack() the frame or make the frame visible.
If you are trying to make the panel that contains the label a size of (300, 125) then the easier approach would be to do:
JPanel panel = new JPanel();
panel.setPreferredSize( new Dimension(300, 125) );
panel.add(...);
frame.add( panel );
frame.pack();
//frame.setLocation(...);
//frame.setLocationByPlatform();
frame.setVisible( true );
Now the pack() method will determine the size of the frame based on the preferred size of all the components added to the frame. No need to worry about insets.
Note: as a general rule you should not invoke setPreferredSize() on a component, since each component is responsible for determining its own size.
Related
I'm creating MTG game for school Java class and I run into problem. I'm currenty testing something... I have my game GUI (extends from JFrame), and when I doublclick on exile "pile" I create a new JFrame, then I add my cards into this JFrame (Card extends JPanel) and I tried to setsize based on frame.getComponentCount()
But problem is, it returns 1, whether a card was added or not.. like my card wasn't even counted as a component.
Code:
JFrame frame=new JFrame();
Image cardImage;
cardImage = ImageIO.read(new File("pics/background.png")).getScaledInstance(this.getWidth(),this.getHeight(),Image.SCALE_SMOOTH);
frame.setLayout(new FlowLayout(FlowLayout.LEFT));
frame.add(new Card(cardImage,false));
frame.add(new Card(cardImage,false));
frame.add(new Card(cardImage,false));
frame.setSize(frame.getComponentCount()*80, frame.getComponentCount()*80);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setVisible(true);
So my frame.setSize doesn't work, because of wrong return.
...
Can anyone help me identify a problem? I don't get it, because frame.add input parameter is component (according to javadoc), but when I try getComponentCount is isn't counted as a component.
Just to be clear, everything else work, I get the new window, there are 3 cards as they supposed to be, I just have to manually resize it to see them.
You're getting back the count from the JFrame's single contentPane component. To get the sub components, call the method on the contentPane itself.
frame.getContentPane().getComponentCount()
But regardless, your design for setting size this way seems brittle, and is not how I would do things. Instead, have your components return their own best preferred sizes and call pack() on your JFrame after adding components.
This is my first swing application. I'm trying to create an window and add a button. On clicking the button, it should display some value on the console. Everythign works fine, but the window is very small. I've specified 800*600, but then also the window size is small, that is its wrapping the button size only.
Here is my code snippet:
JFrame frame = new JFrame("My Application");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container contentPane = frame.getContentPane();
contentPane.setLayout(new BorderLayout());
contentPane.add(new MyClass(), BorderLayout.CENTER);
frame.setSize(800, 600);
frame.pack();
frame.setVisible(true);
Snippet from MyClass.java:
setLayout(new GridBagLayout());
JButton button = new JButton("Button");
button.addActionListener(this);
add(button);
How to make the window size as 800*600?
The pack() method should always be called on a GUI based on a JFrame, so leave that in. It reduces the GUI to the smallest size needed to display the components in it. But don't go calling setSize(Dimension) after that, before checking it is larger than the minimum size.
Remove frame.pack(); from your code.
More information:
http://docs.oracle.com/javase/tutorial/uiswing/components/frame.html
http://docs.oracle.com/javase/6/docs/api/java/awt/Window.html#pack%28%29
You are calling pack method. The api said: "It causes this Window to be sized to fit the preferred size and layouts of its subcomponents"
You haven't specified the preferred size. Try it doing this:
frame.setPreferredSize(new Dimension(800,600));
I have a frame of 100x100 and an image of 400x400, I have a layered pane on the entire frame and the image inside the layered pane. As you can notice the image is bigger than the frame so only a part of the image i.e. the top-left part of the image will be shown. Suppose there is a man in the image at X=32 and y=40 and width = 10 and height = 10 (basically a rectangle) w.r.t. the frame.
Questions
the image is 400x400 right? That means at runtime I can only see 100x100 part of the image and the part of the image that has been shown is the top-left part right? But suppose I want to show a building that is situated at 350x350 w.r.t. the image, then how do I do it (since it is located in the bottom part of the image so it wont be shown)?
suppose the first question is solved, then assume there is a building at 350x350 with width = 20 and height = 20 w.r.t the 'frame'. Now when at runtime I show the image (now the bottom part of the image is visible, assuming question 1 is solved) the co-ordinates of the building w.r.t. frame should not change i.e. they should remain 350x350 w.r.t. the frame.
Point 1) I'm guessing you're adding the image in a JPanel and then into the JFrame or the image into a JPanel which goes into a JScrollPane which finally lands inside the JFrame. JPanels and JScrollPanes both support programmatic scrolling through the use of #scrollRectToVisible.
Here's a (kind of) working sample of the scrollRectToVisible
JPanel panel = new JPanel();
JPanel panel2 = new JPanel();
panel2.setPreferredSize(new Dimension(200, 11000));
SpringLayout layout = new SpringLayout();
panel2.setLayout(layout);
for (int i = 0; i < 100; i++) {
JLabel textField = new JLabel();
textField.setText("textfield number " + i);
textField.setPreferredSize(new Dimension(150, 100));
layout.putConstraint(SpringLayout.NORTH, textField, i * 110, SpringLayout.NORTH, panel2);
panel2.add(textField);
}
JScrollPane scrollPane = new JScrollPane(panel2, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scrollPane.setPreferredSize(new Dimension(200, 500));
panel2.scrollRectToVisible(new Rectangle(0, 800, 150, 100));
panel.add(scrollPane);
Add the panel variable to a JFrame and you're good to run this code. Also, please note that this is meant to be sample code, not the actual way code should be written to add components to panels :P
Point 2) I still don't fully understand this query so I'll give you an answer in 2 parts.
a) I don't see why relative calculations matter? Can you try the sample I provided and see if it does what it needs to? If not, read option b
b) the Rectangle object has a setLocation(int, int) (Reference: Java documentation) that you should play around with. I can't give you a more accurate answer or a code sample since I don't full understand what you're trying to do and I don't have a code sample that I can play with.
Assuming a normal JFrame, I'm trying to get the inset values before the frame is made visible. I can get these values fine once the frame is made visible (and i suppose I could create the jframe offscreen), but was wondering if there is some way to tickle Java into setting the insets before visibility. Prior to this call, all inset values are zero.
Net, I'm trying to get the exact dimensions of a frames client area -- or said better, I'm trying to create a JFrame that has very specific client area dimensions.
Thanks in advance.
Will this help?
frame.pack();
System.out.println("Frame Insets : " + frame.getInsets() );
I'm trying to create a JFrame that has
very specific client area dimensions.
Then you set the preferred size of the panel added to the frame:
panel.setPreferredSize( new Dimension(...) );
frame.add( panel );
frame.setResizable( false );
frame.pack();
frame.setVisible(true);
So, I'm trying to learn Java Swing and custom components. I've created a JFrame, given it a background color, and added a JPanel:
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1000, 2000);
frame.setBackground(Color.WHITE);
JPanel jp = new JPanel();
jp.setBackground(Color.BLUE);
jp.setSize(40, 40);
frame.add(jp);
frame.setVisible(true);
The result is a 1000x2000 window colored blue (as opposed to a white window with a 40x40 blue box inside it). Why is the JPanel expanding beyond its specified size?
Using your code, simply add one line to change the LayoutManager of the JFrame. Then, when you add the component, it will keep it's preferred size.
Also, instead of calling jp.setSize(40,40), call jp.setPreferredSize(new Dimension(40,40)).
And, you need to call pack() on the JFrame to tell it to layout its components.
JFrame frame = new JFrame("Testing");
frame.setLayout(new FlowLayout()); // New line of code
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(1000, 2000)); // Modified line of code
frame.setBackground(Color.WHITE);
JPanel jp = new JPanel();
jp.setBackground(Color.BLUE);
jp.setPreferredSize(new Dimension(40, 40)); // Modified line of code
frame.add(jp);
frame.pack(); // added line of code
frame.setVisible(true);
Also, you should read up on all of the different LayoutManagers available to you. Here is a great tutorial.
The default layout manager for a JFrame is BorderLayout. When you add a component to the frame without constraints, it uses BorderLayout.CENTER as the default constraint. This means the component takes up all available space, regardless of its requested size.