Java Swing component interaction (BoxLayout and Label) - java

OK, several questions about the test code below... I don't have the full working program to post, but I'm hoping people know Swing well enough to take a stab at it. This is a JLabel inside of a JPanel(BoxLayout), and I'm working on the sizing of the label in the lower right.
What I get with the code as shown is a status box 300 width by 30 height. I have fiddled with the preferred size and the label minimum size, and it does not seem to behave in any rational way.
Why does the JPanel Preferred Size affect the height but not the
width? If I change the x dimension in setPreferredSize() to 0 or
500, it still comes out 300 from the label.
Why does the JLabel Minimum Size affect the width but not the
height? If I comment the setPreferredSize() call and increase the
label height to 30, nothing happens.
I started out with JPanel setMinimumSize (commented), but it no longer has any
effect - why does the JPanel require setPreferredSize()?
If I change the label text from "" to " ", this increases the height
of the label. Since the label is not controlling the height here,
why does this have any effect at all?
By the way, the createRigidArea() call is to force the separator to the right, rather than sticking to the left hand side of the screen. If there are any less kludgy ideas for this, I'd be grateful.
private JComponent makeStatusBarTest() {
JPanel statusPanel = new JPanel();
statusPanel.setLayout(new BoxLayout(statusPanel, BoxLayout.LINE_AXIS));
statusPanel.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
// statusPanel.setMinimumSize(new Dimension(0, 30));
statusPanel.setPreferredSize(new Dimension(500, 30));
JLabel statusLabel = new JLabel();
Border emptyBorder = BorderFactory.createEmptyBorder(5, 10, 5, 10);
statusLabel.setBorder(emptyBorder);
statusLabel.setText("");
statusLabel.setMinimumSize(new Dimension(300, 20));
statusPanel.add(statusLabel);
statusPanel.add(new JSeparator(SwingConstants.VERTICAL));
statusPanel.add(Box.createRigidArea(new Dimension(5000,0)));
return statusPanel;
}

I can explain #1 and #2:
From the BoxLayout javadocs: "BoxLayout attempts to arrange components at their preferred widths (for horizontal layout) or heights (for vertical layout)."
In other words, BoxLayout uses the internal components (in your case, statusLabel) to decide the widths, but the JPanel itself (within reason) to decide the heights.
You can usually use Glue instead of RigidArea to move stuff around, but I agree that it takes some getting used to.
#4 is Swing being too efficient - if the JLabel is empty the text rectangle is 0x0. Ultimately determined in SwingUtilities.layoutCompoundLabelImpl().
I think #3 is because BoxLayout is trying to respect the preferred size of the internal components. Since setMinimumSize, arguably, overrides their preferred sizes.

Related

The size of a JTextArea

I have a set of JPanel's within a JFrame. One of the panels contains a JTextArea. At the moment I create this like so:
JTextArea = new JTextArea(5, 40);
And this gives me a text area which is 5 rows by (roughly) 40 columns.
Vertically this works as I'd like it to, the area fills the entire height of the parent container - probably because the parent is the only element positioned in that row.
Horizontally the parent width is determined by elements underneath and it is (usually) wider than the JTextArea is. So I end up with a text area with large margins on either side. What is worse, when I resize the frame smaller to the point where the text area is exactly the width of the parent container, it suddenly 'flicks' and changes into a text area that is 1 row high and is then the width of the parent.
Excuse the crude drawing below which hopefully illustrates the issue.
In short: How to I create a JTextArea that always fills the maximum space available to it? (and if possible with a minimum width after which a scrollbar appears if the user sizes the frame even smaller)
In the parent container of the JTextArea (denoted as Panel 1 in your drawing), call the function:
panel1.setLayout(new BorderLayout());
For reference, see this documentation page:
https://docs.oracle.com/javase/7/docs/api/java/awt/BorderLayout.html
As you only have a single child in panel1, the BorderLayout layout manager of panel1 will by default stretch the text area to use all available space in the parent container.
You may want to take away the constructor parameters specifying the size of your TextArea. The BorderLayout should take care of sizes for you :)
You can request that Swing respects a certain minimum size for the text area by calling:
textArea.setMinimumSize(new Dimension(minimum_width, minimum_height));
You have to use layout manager, for start see oficial Oracle docu about layout managers. For your situation, BorderLayout or GridBagLayout should work fine.
Start with:
panel1.setLayout(new BorderLayout());
or
panel1.setLayout(new GridBagLayout());
With GridBagLayout you can more preciselly do layouting (with BorderLayout you have five areas - no more, no less). With GridBagLayout you can do more complicated layouts.

Java Swing (BoxLayout) alignment issues

I am extremely new to Java Swing, and I'm having quite a bit of issues getting a nice layout going. I have checked out google, and even other answers on this website, but no information I find seems to solve the issue. Here is the result of my efforts:
As you can see, the label, text field, and button are all out of alignment. It is my goal for all of them to have the same left-hand border, and for the button and text field to have the same right-hand border, with these left and right hand borders being each the same distance from the left and righthand sides of my window.
Here are the important parts of my code:
public void run()
{
JFrame frame = new JFrame("Arduino Server");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
InstancePanel = new ServerGUIPanel();
frame.getContentPane().add(InstancePanel);
frame.pack();
frame.setVisible(true);
}
And, in ServerGUIPanel.java:
public ServerGUIPanel()
{
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
setPreferredSize(new Dimension(500, 500));
setBorder(new EmptyBorder(10, 10, 10, 10));
StatusLabel = new JLabel("STATUS: BOOTUP");
add(StatusLabel);
PortField = new JTextField();
PortField.setPreferredSize(new Dimension(5000, 20));
PortField.setMaximumSize(PortField.getPreferredSize());
PortField.setActionCommand("PortChanged");
add(PortField);
ConnectionButton = new JButton();
ConnectionButton.setPreferredSize(new Dimension(5000, 20));
ConnectionButton.setMaximumSize(ConnectionButton.getPreferredSize());
ConnectionButton.setActionCommand("ConnectionClicked");
add(ConnectionButton);
}
Does anyone have a simple solution to this? What am I doing wrong here?
Thank you very much!
--Georges Oates Larsen
Read the section from the Swing tutorial on How to Use BoxLayout for the basics of using a BoxLayout as well as a section on alignment issues.
Basically you need to make sure the alignmentX value of all components is set to be left aligned.
Also:
Don't use setPreferredSize() to set the size of a component. Each Swing component will determine its own preferred size.
Use Java naming conventions. Variable names should NOT start with an upper case character.
I would not recommend using setPreferredSize() AND setMaximumSize(). The latter will cause problems when stretching your main frame. [Your components will likely not want resize]
You should be using layout managers to handle all the alignments itself. I would stay away from using BoxLayout in this case, as different components want to size differently, and that will sway the alignment when added into your BoxLayout panel.
Moreover, you might want to give your main frame a layout as well.
Can you post how you used your GridBagLayout?

Showing specific part of an image in a limited space?

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.

How to reduce the space between the 3 swing checkboxes?

I want to reduce the size between the components with in the Formatting group (left side on the image). How to do this?
JPanel formattingGroup = createGroupWithName("Formatting");
formattingGroup.setMinimumSize(new Dimension(250, 20));
formattingGroup.setLayout(new GridLayout(5, 0));
add(formattingGroup);
final JCheckBox showSurface = new JCheckBox("Show surface");
showSurface.setSelected(true);
formattingGroup.add(showSurface);
final JCheckBox showTerrain = new JCheckBox("Show terrain");
showTerrain.setSelected(true);
formattingGroup.add(showTerrain);
final JCheckBox showVehicleStatus = new JCheckBox("Show vehicle status");
showVehicleStatus.setSelected(true);
formattingGroup.add(showVehicleStatus);
JPanel pnl = createGroupWithName("Depth Stretch");
formattingGroup.add(pnl);
JSlider slider = new JSlider(0, 10);
pnl.add(slider);
When using a GridLayout all components are made the same size.
You are adding a JPanel with a TitledBorder and a JSlider to the grid. Therefore the checkboxes will take the same vertical height as that panel.
You need to use a different layout manager for the panel. Maybe a vertical BoxLayout.
You might look at available size variants, discussed in Resizing a Component.
Use gridbaglayout because that gives you the opportunity to give weights, to columns or rows and set spacing and padding values.
I made a Swing application that contains out of 12 Frames and they all are made with GridBagLayout.
I also tried other before that but they all had limits. That's where the GridBagLayout kicks in. It's a bit harder in begin to understand how it works, but once you get feeling with it, it really is best thing to get the components where you want.
If you want i'll give you a cool example of a frame created with GridBagLayout.

Java Swing Panel Size

Hi I have been learning Java Swing for creating a chess game to practice my Java programming skills.
I've added a JPanel to the east of the JFrame with BorderLayout and I've used the setPrefferedSize(new Dimension(x,y)) method to set the width and height.
After that I have created 4 JPanel and added them with BoxLayout on the previously created panel.
I have tried to set the size of the 4 panels with the setSize(x,y) and setPreferredSize(new Dimension(x,y)) but it dosent work the 4 panels automaticly changed there size to fit the main JPanel and after adding a JLabel on one of them the size of it increased automaticly .
This is my code:
this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
JPanel a = new JPanel();
a.setPreferredSize(new Dimension(50, 50)); //this dosent work
a.add(min);
a.setBackground(Color.red);
this.add;
JPanel b = new JPanel();
b.setBackground(Color.blue);
this.add(b);
JPanel c = new JPanel();
this.add(c);
JPanel d = new JPanel();
d.setBackground(Color.black);
this.add(d);
How can I change the size of each of these panels?
BoxLayout is best for laying out components with varying sizes along a single axis. From the Javadocs:
"BoxLayout attempts to arrange components at their preferred widths (for horizontal layout) or heights (for vertical layout)."
The idea is that they may have different heights (for a horizontal layout) and it will take the maximum height. And, they definitely may have different widths. Also, BoxLayout works with some, er, "interesting" filler pieces like Box.createHorizontalGlue(). These are actually quite useful for flexible, resizeable layouts once you get the hang of it. But, all in all, BoxLayout is for flexible, resizable layout of items with differing sizes.
For simpler cases, especially if you want both preferred width and preferred height to be "respected", use GridLayout as everybody else has suggested.

Categories

Resources