JTabbedPane Preferred Size increasing when adding tabs - java

I have a dialog with several JTabbedPanes that can be minimized/maximized. However I have an issue when the tab is in minimized mode.
A small example of the code:
JDialog dialog = new JDialog();
JPanel main = new JPanel();
main.setLayout(new BoxLayout(main, BoxLayout.Y_AXIS));
JPanel tabPanel = new JPanel();
JTabbedPane tabPane = new JTabbedPane();
for (int i = 0; i < 5; i++) {
tabPane.addTab("Test" + i, new JPanel());
System.out.println(tabPane.getPreferredSize().height);
}
tabPanel.add(tabPane, BorderLayout.NORTH);
main.add(tabPanel, BorderLayout.CENTER);
dialog.add(main);
dialog.setPreferredSize(new Dimension(50, 100);
dialog.pack();
dialog.setVisible(true);
What I expected was a tab pane to be the smallest size possible, but I noticed that as I added more tabs, the height of the tabbed pane was increasing. This was the result from the print statement:
37, 55, 73, 91, 109
The fact that the height is increasing when tabs are added does not seem right to me since according to the documentation in https://docs.oracle.com/javase/tutorial/uiswing/components/tabbedpane.html, "The preferred size of the tabbed pane is just big enough to display its tallest child at its preferred height, and its widest child at its preferred width." I would expect that since I'm adding empty panels, the size would not change, but this does not seem to be the case. Is there anyway around this?
FYI, I am using the latest version of Java.

Related

Java Swing - MigLayout: Docking a component in center isn't fully centering

I am attempting to design a panel with MiGFormat that has a label at the top, and two buttons at the bottom - a yes/no prompt.
I achieve this closely, but the label yesOrNoText (text is "TEST") is not fully centered:
I initialize the panel containing this prompt like so:
private JPanel createYesNoPrompt() {
JPanel panel = new JPanel(new MigLayout());
panel.setBorder(BorderFactory.createLineBorder(Color.red));
JButton yesButton = new JButton("Yes");
JButton noButton = new JButton("No");
yesOrNoText = new JLabel();
yesOrNoText.setText("TEST");
yesOrNoText.setFont(panel.getFont().deriveFont(Font.BOLD, 30f));
yesOrNoText.setHorizontalAlignment(SwingConstants.CENTER);
Dimension dimension = new Dimension(500, 125);
Font font = panel.getFont().deriveFont(Font.BOLD, 20f);
yesButton.setFont(font);
yesButton.setBackground(new Color(35, 138, 35));
yesButton.setPreferredSize(dimension);
noButton.setFont(font);
noButton.setBackground(new Color(183, 19, 19));
noButton.setPreferredSize(dimension);
yesButton.addActionListener(e -> isYes = true);
noButton.addActionListener(e -> isYes = false);
panel.add(yesOrNoText, "wrap, dock center");
panel.add(yesButton);
panel.add(noButton);
return panel;
}
Then, I add it to gamePanel, then gamePanel to mainPanel, then mainPanel to the frame.
gamePanel.add(YesOrNoPanel, "align center");
mainPanel.add(gamePanel);
add(mainPanel);
I'm unsure of what would be causing yesOrNoText to not become fully centered within the YesNoPanel. Please let me know if I need to clarify anything!
Thank you.
I needed to make the add call for the yesNo label span 2 cells. By adding one component in the first row, then adding two in the next, I essentially created a 2x2 grid.
panel.add(yesOrNoText, "wrap, align center, span 2 1");
panel.add(yesButton);
panel.add(noButton);
Notice that on the first component I add yesOrNoText I use span to tell MiGFormat to take up two cells for this component. I can then center that with the remaining two components because it becomes the only component in the row.

Generating java swing fields based on user input

Java beginner here.
I am trying to generate Labels based on user input(take input for the number of labels to generate between 0 to 50) in a JPanel inside a JScrollPane.
The labels are generating correctly but the problem is the panel cant be scrolled down to view all the Labels.
Is it because I am using absolute layout for the panel? If yes then what might be the solution? Please guide.
Note: I made the labels using an array of 50 JLabels in a for loop. Terrible programming practice maybe but works.
Here's the code snippet
frame = new JFrame();
frame.setSize(800, 800);
frame.getContentPane().setLayout(null);
JScrollPane scrollPane = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
scrollPane.setBounds(103, 37, 439, 350);
frame.getContentPane().add(scrollPane);
JPanel panel = new JPanel();
scrollPane.setViewportView(panel);
panel.setLayout(null);
JButton btnGenerateLabels = new JButton("Generate Labels");
btnGenerateLabels.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JLabel[] lab = new JLabel[50];
int y = 50;
for(int i=0; i<50; i++)
{
lab[i] = new JLabel();
lab[i].setText("Label "+(i+1));
panel.add(lab[i]);
lab[i].setBounds(180, y, 97, 25);
y += 30;
}
}
});
btnGenerateLabels.setBounds(129, 23, 152, 25);
panel.add(btnGenerateLabels);
Is it because I am using absolute layout for the panel?
Yes. Don't use a null layout. Swing was designed to be used with layout managers.
The solution is to use a layout manager, probably the GridLayout as was suggested.
After all the components have been added to the panel you then need to invoke revalidate() and repaint() on the panel. This will invoke the layout manager and each component will be given a size/location.
Scrollbars will then appear as required.

How to re-size JButton

I've bee teaching myself java and following along with the problems in the book. I'm trying to make a display for my calculator. In the example(I did not attach this) the buttons were a smaller size than what mine are and I can't figure out how to reformat them. I tried using the dimension class but it had no affect. Also, I can't get my text at the top of the calculator to align left.
Here is my code:
public class Calculator extends JFrame {
public Calculator() {
setTitle("Calculator");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setSize(300, 300);
setLayout(new BorderLayout());
JPanel numberPanel = new JPanel();
add(numberPanel, BorderLayout.CENTER);
numberPanel.setLayout(new GridLayout(4, 3, 3, 3));
for(int i = 1; i < 10; i++) {
JButton button = new JButton(String.valueOf(i));
numberPanel.add(button);
}
JButton zero = new JButton("" + 0);
JButton dot = new JButton(".");
JButton clear = new JButton("C");
numberPanel.add(zero);
numberPanel.add(dot);
numberPanel.add(clear);
JPanel keyPanel = new JPanel();
add(keyPanel, BorderLayout.EAST);
keyPanel.setLayout(new GridLayout(4, 1, 3, 3));
JButton plus = new JButton("+");
JButton minus = new JButton("-");
JButton times = new JButton("*");
JButton divide = new JButton("/");
keyPanel.add(plus);
keyPanel.add(minus);
keyPanel.add(times);
keyPanel.add(divide);
JPanel equalsPanel = new JPanel();
add(equalsPanel, BorderLayout.SOUTH);
equalsPanel.setLayout(new GridLayout(1, 1));
JButton equals = new JButton("=");
equalsPanel.add(equals);
JPanel textPanel = new JPanel();
add(textPanel, BorderLayout.NORTH);
JTextField inputBox = new JTextField("0.0");
inputBox.setHorizontalAlignment(JTextField.LEFT);
inputBox.setEditable(false);
Font font = new Font("MonoSpaced", Font.BOLD, 20);
inputBox.setFont(font);
textPanel.add(inputBox);
setVisible(true);
}
public static void main(String[] args) {
new Calculator();
}
}
Imports were left off for brevity
GridLayout will laugh at you when you try and set a dimension. It does respect preferred sizes. You should select a layout manager that will respect preferred sizes. Or you can simply pack() (after you add all your components) your frame instead of setSize() and all the components preferred sizes will kick in. (Disclaimer - because of GridLayout though, if you try and resize the frame after that, you components will resize again)
See more at How to use Layout Managers. For a quick view of which layout managers respect preferred sizes and which ones don't, have a look at this post.
A common approach is to nest panels with different layout managers also, as seen here
UPDATE
As mentioned preciously, you should just call pack on the frame instead of set size. With your current code, this would cause the frame to be very small because of the preferred sizes of the components. If you want the buttons to have a bigger preferred size, you can set the font to a bigger font and/or use button.setMargins(new Insets(w,x,y,x)); to make the margins bigger. But it is preferred to pack the frame.
I would recommend using the Window Builder add-on if you’re using Eclipse. This tool will help you with many aspects of Swing. Learn by doing.
WindowBuilder Dowload Link

Resize buttons using Grid Bag Layout

I want to resize my buttons to be the same size and place then in a Panel on a JApplet. I have tried using
public void init() {
// TODO start asynchronous download of heavy resources
JButton btnWestern=new JButton("Western");
JButton btnPop=new JButton("Pop");
GridBagConstraints c4=new GridBagConstraints();
JPanel jPanel1 = new JPanel();
getContentPane().setLayout(new java.awt.GridBagLayout());
jPanel1.setLayout(new java.awt.GridBagLayout());
c4.gridx = 0;
c4.gridy = 0;
c4.insets = new Insets(36, 10, 0, 249);
jPanel1.add(btnWestern, c4);
c4.gridx = 0;
c4.gridy = 1;
c4.insets = new Insets(33, 10, 0, 249);
jPanel1.add(btnPop, c4);
add(jPanel1, new java.awt.GridBagConstraints());
}
When I run, this is what I get
But I noticed that if I change the button text to be the same or have the same length, like
JButton btnWestern=new JButton("Button1");
JButton btnPop=new JButton("Button2");
I get the desired output
What can I do to make sure that even the text of the buttons are not the same length, the buttons are the same size?
I'd suggest reading through the How to Use GridBagLayout tutorial if you haven't already. GridBagLayout is powerful but it is also one of the more complex LayoutManagers available.
I believe you need to set the GridBagConstraints.fill property to get the behavior you desire.
In your case this should be something like
c4.fill = GridBagConstraints.HORIZONTAL;
Edit (A bit of explanation for the observed behavior) When you use the same text on both buttons, their calculated size ends up being the same, so they are rendered as you want. When you use different size text, the buttons will render in a size that fits the text by default. The default value for GridBagConstraints.fill is GridBagConstraints.NONE which indicates to the LayoutManger to not resize the component. Changing the fill to GridBagConstraints.HORIZONTAL tells the LayoutManger to resize the component horizontally to fill the display area.

How do i get vertical scrolling to JPanel?

I have written a code in java using swing, so that I will have a JscrollPane added to JPanel and then I will add buttons of fixed size to JPanel in vertical fashion
JPanel panel=new JPanel();
panel.setBackground(Color.WHITE);
int v=ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS;
int h=ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS;
JScrollPane jsp=new JScrollPane(panel,v,h);
jsp.setPreferredSize(new Dimension(600,600));
jsp.setBounds(150,670,850,200);
frame.add(jsp);
then I am adding buttons to it at run time.
for(i=0;i<n;i++)
{
button[i]=new JButton();
button[i].setBounds(20,y,120,120);
button[i].setSize(120,120);
button[i].setToolTipText(file[i].toString());
button[i].setIcon(Icon);
panel.add(button[i]);
y=y+140;
}
I want to add a buttons one below the other...(i.e I want a vertical scrollbar)
i.e. button1
button2
'
'
but above code is giving me buttons in a line (i.e. I am getting horizontal scrollbar)
i.e. button1 button2...
another problem is the size of the buttons. Using btn.setSize() is not affecting size at all...
can anybody help me?
You must use an appropriate Layoutmanager like GridLayout, Boxlayout or GridBagLayout for the panel.
It depends what else you want to put into the panel.
GridLayout is easier to use IMO:
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(0, 1)); // any number of rows, 1 column
...
panel.add(button[i]);
BoxLayout is almost as easy:
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
...
panel.add(button[i]);
GridBagLayout is more powerful, allowing more than one column, components spanning more than one cell, ... needs a GridBagConstraints to add the elements:
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
GridBagConstraints constraints = new GridBagConstraints(
0, RELATIVE, // x = 0, y = below previous element
1, 1, // cell width = 1, cell height = 1
0.0, 0.0 // how to distribute space: weightx = 0.0, weighty = 0,0
GridBagConstraints.CENTER, // anchor
GridBagConstraints.BOTH, // fill
new Insets(0, 0, 0, 0), // cell insets
0, 0); // internal padding
...
panel.add(button[i], constraints);
Have a look at this tutorial: Laying Out Components Within a Container (The visual guide is a good start point)
EDIT:
you can also lay out the components by hand, that is, specify the location and size of each component in the container. For this you must set the LayoutManager to null so the default manager gets removed.
JPanel panel = new JPanel();
panel.setLayout(null);
...
button[i].setLocation(x, y);
button[i].setSize(width, heigth);
// OR button[i].setBounds(x, y, width, height);
panel.add(button[i]);
You need to define an appropriate LayoutManager for your JPanel, which is responsible for how the Components added to it are positioned. The default LayoutManager is FlowLayout, which lays out Components left-to-right. For laying out Components vertically you should consider using BoxLayout or GridBagLayout.
You have to set LayoutManager for JPanel or use Box(BoxLayout.Y_AXIS) instead.
For the size of buttons use preferredSize
For your layout problem you need to change the layout manager to one that does a vertical layout. For playing around purposes you can use BoxLayout like this:
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
This is much easier if you let the layout manager do its work.
In Swing, the way the components are layout over other component ( a panel for instance ) is using a layout manager.
It is used to avoid having to compute the coordinates of all the components against each other each time the container component resizes, or a new component is added.
There are different layout mangers, the one that you need here is BoxLayout.
By using this layout you don't need to specify the button position, nor its size. The layout manager query each component and use that information to place them in the correct position and size.
For instance the following frame
Was created this ( modified version of your ) code:
import javax.swing.*;
import java.awt.*;
public class ScrollTest {
private JPanel panel;
private Icon[] icons = new Icon[3];
public void main() {
panel =new JPanel();
// Use top to bottom layout in a column
panel.setLayout( new BoxLayout( panel, BoxLayout.Y_AXIS ));
panel.setBackground(Color.WHITE);
int v=ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS;
int h=ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS;
JScrollPane jsp=new JScrollPane(panel,v,h);
jsp.setPreferredSize(new Dimension(600,600));
jsp.setBounds(150,670,850,200);
JFrame frame = new JFrame();
frame.add(jsp);
// my addition to load sample icons
loadImages();
// simulate dynamic buttons
addButtons();
frame.pack();
frame.setVisible( true );
}
void loadImages() {
icons[0] = new ImageIcon( "a.png" );
icons[1] = new ImageIcon( "b.png" );
icons[2] = new ImageIcon( "c.png" );
}
void addButtons() {
for( int i = 0 ; i < icons.length ; i++ ) {
JButton button = new JButton();
Icon icon = icons[i];
button.setIcon( icon );
// Set the button size to be the same as the icon size
// The preferred size is used by the layout manager
// to know what the component "better" size is.
button.setPreferredSize( new Dimension( icon.getIconWidth(),
icon.getIconHeight() ) );
// This is IMPORTANT. The maximum size is used bythe layout manager
// to know "how big" could this component be.
button.setMaximumSize( button.getPreferredSize() );
panel.add( button );
}
}
public static void main( String ... args ) {
new ScrollTest().main();
}
}
I hope this helps.
One can also get a vertical scrolling for JPanel with SpringLayout. It's possible if panel's vertical size will be defined by setting a constraint SpringLayout.SOUTH. This can be done like this:
JPanel panel = new JPanel();
SpringLayout panelLayout = new SpringLayout();
panel.setLayout(panelLayout);
// Adding components to the panel here
// .....
// That's what defines panel's exact size and makes its scrolling possible
panelLayout.putConstraint(SpringLayout.SOUTH, panel, 0,
SpringLayout.SOUTH, lastComponentOfThePanel);
JScrollPane panelScrollPane = new JScrollPane(panel);
where lastComponentOfThePanel is a component at the bottom of a panel.
Hope this will help somebody. In my opinion, SpringLayout is very powerful layout manager, and sometimes it's very difficult or almost impossible to replace this one with GridBagLayout.
What about?
JScrollPane scrollPane = new JScrollPane(yourpanel);
container.add(scrollPane);

Categories

Resources