I'm aware there are several questions with the same title, and I've tried their answers but to no avail.
I'm getting the following result with my code:
It does not scroll as it should, and there's this empty little space to the right.
Here is the main code for the frame, mainpanel, list panel and the buttons panel that are inside the mainpanel.
public Tester2() {
JPanel mainPanel = new JPanel(); /////// MAIN PANEL
mainPanel.setLayout(new BorderLayout());
mainPanel.setPreferredSize(new Dimension(200, 400));
JPanel upperListPnl = new JPanel(); ////// LIST PANEL
upperPnlSetup(upperListPnl);
JPanel lowerBtnsPnl = new JPanel(); ///// BUTTONS PANEL
lowerBtnsPnl.setLayout(new BorderLayout());
JButton testButton = new JButton("Test the list");
testButton.addActionListener(e -> {
exampleModel.addElement("List has been tested");
updateExampleData();
});
lowerBtnsPnl.add(testButton);
mainPanel.add(upperListPnl, BorderLayout.CENTER);
mainPanel.add(lowerBtnsPnl, BorderLayout.SOUTH);
JFrame frame = new JFrame();
frame.add(mainPanel);
frame.setVisible(true);
frame.pack();
frame.setLocationRelativeTo(null);
}
Here is the code for the JList and the JScrollpane (upper panel):
public void upperPnlSetup(JPanel panel) {
panel.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
exampleList = new JList<>(exampleModel);
JScrollPane jsp = new JScrollPane(exampleList, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
c.fill = GridBagConstraints.BOTH;
c.weighty = 1;
c.weightx = 0.75;
panel.add(exampleList, c);
c.weightx = 0.25;
panel.add(jsp, c);
}
And then the JList and model list as well as the data updating method:
private JList<String> exampleList;
private DefaultListModel<String> exampleModel = new DefaultListModel<>();
public void updateExampleData() {
exampleList.setModel(exampleModel);
}
I tried a FloatLayout, a BorderLayout, and a GridLayout (0,2 and 0,1) all of which didn't work. Finally, I settled for the GridBagLayout since it's seemingly always used for JLists and/or JScrollpanes, and I played with the GridBagConstraints as well as the positioning of the code but seem to always land on the same problem. I've tried giving the scroll pane a preferredSize, didn't do anything.
Okay so, apparently the problem was that I was adding the list to the panel. Adding it to the scrollpane, then adding the scrollpane to the panel was enough, so commenting out the
panel.add(exampleList, c);`
fixed the whole thing.
In most of the GUI programs, when the user resizes it, the components of the program, such as text fields, buttons, etc. tend to increase or decrease their size depending on the decisions of the user. I'm trying to implement this idea into my GUI program. I'm a little bit lost about how I can do it. By the way, I created my program without the usage/help of the Eclipse Swing or Netbeans' GUI.
import javax.swing.*;
import java.awt.*;
import java.io.IOException;
public class CodeReviewerFrame extends JFrame {
EditorAreaPanel display = new EditorAreaPanel();
// FileOptionsPanel fileOptionsPanel = new FileOptionsPanel( display );
JPanel p = new JPanel();
JPanel panel = new JPanel();
public CodeReviewerFrame(String title) throws IOException {
super(title);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setPreferredSize(new Dimension(1500, 1000));
setLayout(new BorderLayout());
ImageIcon img = new ImageIcon("icon.png");
setIconImage(img.getImage());
p.setLayout(new BorderLayout());
p.add(new HomeOptionsPanel(display), BorderLayout.LINE_START);
p.add(new NewCommentPanel(display), BorderLayout.CENTER);
p.add(new CommentOptionsPanel(display), BorderLayout.LINE_END);
add(p, BorderLayout.PAGE_START);
panel.setLayout(new BorderLayout());
panel.add(new FileExplorerPanel(), BorderLayout.LINE_START);
panel.add(new FileOptionsPanel(display), BorderLayout.CENTER);
panel.add(new CommentShowPanel(display), BorderLayout.LINE_END);
add(panel, BorderLayout.CENTER);
pack();
setResizable(true);
setVisible(true);
/**
* Everything Under This is experimental
*/
GridBagConstraints constraints = new GridBagConstraints();
constraints.gridx = 0;
constraints.gridy = 0;
//add ( fileOptionsPanel, constraints );
}
}
There are components on each Panel that have been added, such as buttons in HomeOptionsPanel, huge JTextArea in the center of FileOptionsPanel plus four buttons up on the JTextArea, etc. Should I use new Layout type, or commands known as "repaint/revalidate," or implement changeListener? And should I only implement the code to the JFrame, or do it for each of the JPanels?
The behaviour of your UI upon window resizing depends (also) on the Layout Manager you are using.
Some Layout Managers (like BorderLayout) resize the components when the windows is resized, while others (like FlowLayout) don't.
It is not clear what LM you are using inside your panels, but most likely your issue stands in there.
I was wondering if there is a way to change the size of a JPanel when creating one.
My code looks like this:
add(scoreArea, BorderLayout.NORTH);
add(gameArea, BorderLayout.CENTER);
add(new JPanel(), BorderLayout.WEST);
add(new JPanel(), BorderLayout.EAST);
add(new JPanel(), BorderLayout.SOUTH);
I used the JPanels to create a border, but I would like to make them thinner. I am new to swing and I was just wondering if you could change the size in the same statement or if I would have to make JPanel objects and set the size there?
I tried this but it doesn't seem to work:
add(new JPanel(){
setPreferredSize(new Dimension(10, 300));
}, BorderLayout.EAST);
Is there a way to do something like this?
Edit: Really downvotes? Just asking a question, I dont see the need for a downvote. What a community.
You can set margin for JPanel (contaiter) using EmptyBorder class:
EmptyBorder margin = new EmptyBorder(top, left, bottom, right);
getContentPane().setBorder(border);
Proper way to setup prefered size is:
Dimension size = new Dimension(width, height);
JPanel panel;
add(panel = new JPanel(), BorderLayout.WEST);
panel.setPreferredSize(size);
add(panel = new JPanel(), BorderLayout.EAST);
panel.setPreferredSize(size);
add(panel = new JPanel(), BorderLayout.SOUTH);
panel.setPreferredSize(size);
I am not sure how I could create a panel like this. I could have the main panel as a borderlayout and set the login screen panel to the page_end but then the forums and faqs also have to be on the page_end..... somehow the login screen panel and the forums and faqs panel has to share the page_end together. Is there someway I could do this or maybe some BETTER way? This has been confusing me for about 2 hours and I don't understand how I would do this.
Right now I have 3 panels and 1 frame. 1 is the main panel that is added to the main frame. The 2 other panels are the loginscreen panel and the forums and faqs panel. Here is the code.
private void createView() {
//Created essential details for the frame
JFrame frame = new JFrame();
frame.setTitle("Name of the game");
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Defining layouts and panels + giving them layouts
JPanel pMain = new JPanel();
frame.getContentPane().add(pMain);
pMain.setLayout(new BorderLayout());
JPanel pLogin = new JPanel(new GridBagLayout());
pMain.add(pLogin, BorderLayout.PAGE_END);
JPanel pInfo = new JPanel(new GridBagLayout());
pMain.add(pInfo, BorderLayout.PAGE_END);
frame.setVisible(true);
}
Here is the component layout
Source
JFrame frame = new JFrame();
frame.setTitle("Name of the game");
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Defining layouts and panels + giving them layouts
JPanel pMain = new JPanel();
frame.getContentPane().add(pMain);
pMain.setLayout(new BorderLayout());
JPanel bottomComponentsPanel = new JPanel(new GridBagLayout());
JPanel pLogin = new JPanel();
pLogin.setBackground(Color.ORANGE);
pLogin.setPreferredSize(new Dimension(100, 100));
JPanel pInfo = new JPanel(new GridBagLayout());
pInfo.setBackground(Color.ORANGE);
pInfo.setPreferredSize(new Dimension(70, 70));
GridBagConstraints constraints = new GridBagConstraints();
constraints.anchor = GridBagConstraints.PAGE_END;
constraints.gridx = 0;
constraints.gridy = 0;
bottomComponentsPanel.add(pLogin, constraints);
constraints.gridx = 1;
constraints.gridy = 0;
bottomComponentsPanel.add(pInfo, constraints);
JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
bottomPanel.add(bottomComponentsPanel);
pMain.add(bottomPanel, BorderLayout.SOUTH);
frame.setVisible(true);
Display
I have some questions on positioning components and some questions on text fields and text areas (Java Swing). Any help is greatly appreciated.
Right now I am trying to have two text fields beside each other with a different label above each describing what that text field does. To achieve this I have placed them in a GridLayout(2, 2).
Is this the best way? It is the only way I know to have a label directly over another component. Is there a better way? What about if there is just one label above one button. Is it sensible to position this through a GridLayout(2, 1)? I am visually impaired so I do not think positioning buttons just by their pixel position is an option unless there is a simple way to place components at a relative number of pixels to another component.
That leads me to my next question.
What is the best way to have the same UI as above but with another component (button) centered under it. Essentially the UI should compose of two Named text fields with a calculate button under. The way I did this is by putting the above components in a panel, and adding that plus the calculate button to a surrounding panel with a GridLayout(2, 1). The problem is that the button becomes as big as the panel above it (I'm assuming). How can I adjust this and still have the button perfectly aligned under the panel of text fields/labels? Similarly with labels above text areas. The label should be small but have a larger space for the text area under.
(text field):
Again referring to the UI above, if the user types many characters into the first text field, will the letters go over the text field on the right? If so how can I prevent this?
If I append text to a text area and it is already full, will it automatically allow the user to scroll? If not what is a simple way to make the text area scrollable?
Right now I am not setting a size of the text area. Does it just grow as I add text? Does it have a default size as in number of characters?
There are a number of layout managers that might be capable of providing you with what you need.
MigLayout
JGoodies FormLayout
GridBagLayout
For, GridBagLayout would be my choice (I'm biased, as I've been using this layout manager for the past 12 years ;))
public class TestLayout17 {
public static void main(String[] args) {
new TestLayout17();
}
public TestLayout17() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = new Insets(2, 2, 2, 2);
add(new JLabel("Label 1"), gbc);
gbc.gridx++;
add(new JLabel("Label 2"), gbc);
gbc.gridx = 0;
gbc.gridy++;
gbc.fill = GridBagConstraints.HORIZONTAL;
add(new JTextField(10), gbc);
gbc.gridx++;
add(new JTextField(10), gbc);
gbc.gridx = 0;
gbc.gridy++;
gbc.fill = GridBagConstraints.NONE;
gbc.gridwidth = 2;
add(new JButton("Click"), gbc);
}
}
}
I also agree with Eng.Fouad's suggestion of using compound containers to make your life easier in the long run
You might find Laying Out Components Within a Container a worth while read.
Right now I am trying to have two text fields beside each other with a
different label above each describing what that textfield does. To
achieve this I have placed them in a GridLayout(2, 2). Is this the
best way? It is the only way I know to have a label directly over
another component. Is there a better way? What about if there is just
one label above one button. Is it sensible to position this through a
GridLayout(2, 1)?
Myself, I always do it via nested panels with BorderLayout. For example:
JFrame frame = new JFrame("The Title");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panOuter = new JPanel(new BorderLayout());
JPanel panLeft = new JPanel(new BorderLayout());
panLeft.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JPanel panRight = new JPanel(new BorderLayout());
panRight.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
panOuter.add(panLeft, BorderLayout.WEST);
panOuter.add(panRight, BorderLayout.EAST);
JLabel lblLeft = new JLabel("Label 1", JLabel.CENTER);
JLabel lblRight = new JLabel("Label 2", JLabel.CENTER);
JTextField txtLeft = new JTextField(10);
JTextField txtLright = new JTextField(10);
panLeft.add(lblLeft, BorderLayout.NORTH);
panLeft.add(txtLeft, BorderLayout.CENTER);
panRight.add(lblRight, BorderLayout.NORTH);
panRight.add(txtLright, BorderLayout.CENTER);
frame.setContentPane(panOuter);
frame.pack();
frame.setVisible(true);
Note that, you can manipulate the gaps between the components with setting empty borders. Also, you may use BorderLayout.LINE_START and BorderLayout.LINE_END instead of using BorderLayout.WEST and BorderLayout.EAST, and this will add support for RTL languages (e.g Arabic).
That leads me to my next question. What is the best way to have the
same UI as above but with another component (button) centred under it.
Essentially the UI should compose of two Named text fields with a
calculate button under. The way I did this is by putting the above
components in a panel, and adding that plus the calculate button to a
surrounding panel with a GridLayout(2, 1). The problem is that the
button becomes as big as the panel above it (I'm assuming). How can I
adjust this and still have the button perfectly aligned under the
panel of textfields/labels?
I would do it via nested panels as I did earlier, but now the bottom panel has a FlowLayout layout manager to get a good size for the button:
JFrame frame = new JFrame("The Title");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panOuter = new JPanel(new BorderLayout());
JPanel panLeft = new JPanel(new BorderLayout());
panLeft.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JPanel panRight = new JPanel(new BorderLayout());
panRight.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JPanel panBottom = new JPanel(); // default is FlowLayout
panBottom.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
panOuter.add(panLeft, BorderLayout.WEST);
panOuter.add(panRight, BorderLayout.EAST);
panOuter.add(panBottom, BorderLayout.SOUTH);
JLabel lblLeft = new JLabel("Label 1", JLabel.CENTER);
JLabel lblRight = new JLabel("Label 2", JLabel.CENTER);
JTextField txtLeft = new JTextField(10);
JTextField txtLright = new JTextField(10);
JButton btnBottom = new JButton("Press it!");
panLeft.add(lblLeft, BorderLayout.NORTH);
panLeft.add(txtLeft, BorderLayout.CENTER);
panRight.add(lblRight, BorderLayout.NORTH);
panRight.add(txtLright, BorderLayout.CENTER);
panBottom.add(btnBottom);
frame.setContentPane(panOuter);
frame.pack();
frame.setVisible(true);
Similarly with labels above text areas. The label should be small but
have a larger space for the text area under.
I would suggest you to use TitledBorder:
JFrame frame = new JFrame("The Title");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panOuter = new JPanel(new BorderLayout());
JPanel panLeft = new JPanel(new BorderLayout());
panLeft.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JPanel panRight = new JPanel(new BorderLayout());
panRight.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JPanel panBottom = new JPanel(); // default is FlowLayout
panBottom.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JPanel panInput = new JPanel(new BorderLayout());
panInput.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JPanel panConsole = new JPanel(new BorderLayout());
Border outsideBorder = BorderFactory.createEmptyBorder(5, 5, 5, 5);
Border insideBorder = BorderFactory.createTitledBorder("The Console");
Border theBorder = BorderFactory.createCompoundBorder(outsideBorder, insideBorder);
panConsole.setBorder(theBorder);
panInput.add(panLeft, BorderLayout.WEST);
panInput.add(panRight, BorderLayout.EAST);
panInput.add(panBottom, BorderLayout.SOUTH);
panOuter.add(panInput, BorderLayout.NORTH);
panOuter.add(panConsole, BorderLayout.CENTER);
JLabel lblLeft = new JLabel("Label 1", JLabel.CENTER);
JLabel lblRight = new JLabel("Label 2", JLabel.CENTER);
JTextField txtLeft = new JTextField(10);
JTextField txtLright = new JTextField(10);
JButton btnBottom = new JButton("Press it!");
JTextArea txtConsole = new JTextArea(5, 10);
panLeft.add(lblLeft, BorderLayout.NORTH);
panLeft.add(txtLeft, BorderLayout.CENTER);
panRight.add(lblRight, BorderLayout.NORTH);
panRight.add(txtLright, BorderLayout.CENTER);
panBottom.add(btnBottom);
panConsole.add(txtConsole, BorderLayout.CENTER);
frame.setContentPane(panOuter);
frame.pack();
frame.setVisible(true);
third (text field): Again referring to the UI above, if the user types
many characters into the first text field, will the letters go over
the text field on the right? If so how can I prevent this?
Try the above code, and see how it acts :)
Fourth: If I append text to a text area and it is already full, will
it automatically allow the user to scroll? If not what is a simple way
to make the text area scrollable?
You need to use something called JScrollPane:
JFrame frame = new JFrame("The Title");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panOuter = new JPanel(new BorderLayout());
JPanel panLeft = new JPanel(new BorderLayout());
panLeft.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JPanel panRight = new JPanel(new BorderLayout());
panRight.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JPanel panBottom = new JPanel(); // default is FlowLayout
panBottom.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JPanel panInput = new JPanel(new BorderLayout());
panInput.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JPanel panConsole = new JPanel(new BorderLayout());
Border outsideBorder = BorderFactory.createEmptyBorder(5, 5, 5, 5);
Border insideBorder = BorderFactory.createTitledBorder("The Console");
Border theBorder = BorderFactory.createCompoundBorder(outsideBorder, insideBorder);
panConsole.setBorder(theBorder);
panInput.add(panLeft, BorderLayout.WEST);
panInput.add(panRight, BorderLayout.EAST);
panInput.add(panBottom, BorderLayout.SOUTH);
panOuter.add(panInput, BorderLayout.NORTH);
panOuter.add(panConsole, BorderLayout.CENTER);
JLabel lblLeft = new JLabel("Label 1", JLabel.CENTER);
JLabel lblRight = new JLabel("Label 2", JLabel.CENTER);
JTextField txtLeft = new JTextField(10);
JTextField txtLright = new JTextField(10);
JButton btnBottom = new JButton("Press it!");
JTextArea txtConsole = new JTextArea(5, 10);
JScrollPane srcPane = new JScrollPane(txtConsole,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
panLeft.add(lblLeft, BorderLayout.NORTH);
panLeft.add(txtLeft, BorderLayout.CENTER);
panRight.add(lblRight, BorderLayout.NORTH);
panRight.add(txtLright, BorderLayout.CENTER);
panBottom.add(btnBottom);
panConsole.add(srcPane, BorderLayout.CENTER);
frame.setContentPane(panOuter);
frame.pack();
frame.setVisible(true);
I hope I answered all of your questions :)