How to make a JTable fill entire available space? - java

I want to created a panel with a table, which fills the entire available space.
I do this using following code:
public class MyFrame extends JFrame {
public EconomyFrame() throws HeadlessException {
super("...");
final JTabbedPane tabbedPane = new JTabbedPane();
add(tabbedPane);
final JPanel companiesPanel = new JPanel();
final CompaniesTableModel companiesModel = new CompaniesTableModel
(ApplicationStateSingleton.INSTANCE.getPersistence().getCompanies());
final JTable companiesTable = new JTable(companiesModel);
ApplicationStateSingleton.INSTANCE.getEventBus().subscribeToPropertyChanges(companiesModel);
companiesPanel.add(new JScrollPane(companiesTable));
tabbedPane.addTab("Companies", companiesPanel);
}
}
But it doesn't work because when I resize the frame, the table fills only part of the available space (see screenshots below).
How can I fix (make the table fill the entire available space) ?

Use a layout manager that allows the JTable occupy the full area available rather than the default FlowLayout used by JPanel which only uses its components preferred sizes
JPanel companiesPanel = new JPanel(new GridLayout());

There are two issues:
1) first you need to use an appropriate layout manager to make sure that the scrollpane can resize to fill the available area. Typically people would add the scrollpane to the CENTER of a BorderLayout.
2) you need to let the table fill the available space in the viewport of the scrollpane. To do this you use:
table.setFillsViewportHeight(true);

Related

JCheckBox centereing

I have been searching for a while now, but couldnt find a solution so I have decided to ask here.
I am using Java Swing for my gui implementation of calculator. I have custom made layout(which works correctly 100%). I have added all buttons and all buttons are positioned correctly, always. Last component I have inserted is "Inv" and it is checkbox which I cant find a way to center it inside its area. I have tried putting it in panel,in panel with borderlayout.center, setting the horizontal and vertical text alignment, but nothing works.
invert = new JCheckBox("Inv");
invert.setBackground(Color.decode("#8DA336"));
invert.addActionListener(new CommandListener(this,"invert"));
container.add(invert, new RCPosition(5, 7));
This RCPosition is nothing more than object which says in which row and column this component is (nothing wrong with that).
Checkbox is by default left-aligned. Try make it center-aligned:
invert = new JCheckBox("Inv");
invert.setHorizontalAlignment(SwingConstants.CENTER);
// styling and add to container
If it don't help, then you should publish your layout manager.
You could try putting it in a JPanel with BoxLayout, then add horizontal glue on the left and right.
final JFrame frame = new JFrame();
final JPanel jp = new JPanel();
jp.setLayout(new BoxLayout(jp, BoxLayout.X_AXIS));
jp.add(Box.createHorizontalGlue());
final JCheckBox jcb = new JCheckBox("inv");
jp.add(jcb);
jp.add(Box.createHorizontalGlue());
frame.getContentPane().add(jp);
frame.pack();
frame.setLocationRelativeTo(null);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
frame.setVisible(true);
}
});
This is just one way to do it, setHorizontalAlignment should work as well.

BoxLayout Displaying Incorrectly

I'm trying to create a pretty simple application that has a JSplitPane (which is divided into a JTabbedPane and a JPanel) above a status bar panel. I want to use a simple layout (i.e. BoxLayout, FlowLayout, or BorderLayout), but I've tried and they all give me the same error. I've simplified the code as much as possible to show the error.
The error is that there should only be 2 regions in the main box layout (the frame): a top (with the JSplitPane, which has the black border) and a bottom (with the JPanel status bar). However, when I add the status bar, a third region is created in the upper left that contains nothing. Any ideas on how to get rid of it?
public static void main(String[] args) {
JFrame frame = new JFrame("Application");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS));
// Create left side of the application
JTabbedPane tabby = new JTabbedPane(JTabbedPane.LEFT);
// Create right side of the application
JPanel rightPanel = new JPanel(new BorderLayout());
// Create the status bar at the bottom
JPanel statusBar = new JPanel(new BorderLayout());
JPanel statusBarPanel = new JPanel();
statusBarLabel = new JLabel("Status Bar");
statusBarPanel.add(statusBarLabel);
parent.add(statusBarPanel);
JSplitPane mainPain = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, tabby, rightPanel);
frame.add(mainPain);
frame.add(statusBar);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
I'm trying to create a pretty simple application that has a JSplitPane (which is divided into a JTabbedPane and a JPanel) above a status bar panel.
Normally you would just use the default BorderLayout of the frame and then do:
frame.add(splitPane, BorderLayout.CENTER);
frame.add(statusBar, BorderLayout.PAGE_END);
A status bar is typically one or more labels that display information so they are display in a fixed size at the bottom.
The other panel will then contain the main components of the application. These components will then get any extra space available to the frame as it is resized.
but I've tried and they all give me the same error
parent.add(statusBarPanel);
The variable "parent" doesn't exist. Get rid of it. Add the status bar to the frame as shown above.
not sure if thats it, but it seems, like you add 2 Panels when adding the Statusbar.
You got a statusBarPanel which is added to "parent", and statusBar, which is added to the frame itself. Maybe thats your 3rd Panel.

Setting the preferred size of a JTextFieldis not working

I'm trying to set the size of JTextField, but for some reason it stays the same size and fills up the whole JPanel, I am using setPreferredSize, but this makes no difference:
JPanel loginJPanel = new JPanel(new BorderLayout());
JTextField usernameJTextField = new JTextField();
usernameJTextField.setPreferredSize(new Dimension(50, 100));
loginJPanel.add(usernameJTextField);
It does make a difference, but the layout may choose to ignore preferred size settings. The center area of BorderLayout gets as much of the available space as possible. See How to Use BorderLayout for more details.
Consider this example that packs the frame, as a result the preferred size of the text field is respected. But once the frame is resized, the text field is resized as well.
import javax.swing.*;
import java.awt.*;
class Demo {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JPanel loginJPanel = new JPanel(new BorderLayout());
JTextField usernameJTextField = new JTextField();
usernameJTextField.setPreferredSize(new Dimension(50, 100));
loginJPanel.add(usernameJTextField);
JFrame frame = new JFrame();
frame.add(loginJPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
});
}
}
Take a look at Visual Guide to Layout Managers and perhaps you would find a more suitable layout for your needs.
Also, see Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?.
EDIT:
Note that you're usually encouraged to specify the number of columns when initializing text fields. This number is used to calculate preferred width. For example textField = new JTextField(20); See How to Use Text Fields for more details:
If you do not specify the number of columns or a preferred size, then
the field's preferred size changes whenever the text changes, which
can result in unwanted layout updates.
Since you set layout manager of your jpanel to BorderLayout, it adds jtextfield to center by default. Use a null layout instead.
JPanel loginJPanel = new JPanel(null);

JScrollPanel JPanel and Layouts

What I have:
A split panel with a scroll panel in the right part.
In this scroll panel, I have a JPanel.
I want to have in this JPanel a series of others JPanels stacked one under the other one.
I set the Layout to be a BoxLayout. Now it stacks multiple JPanels, but I have 2 problems:
If my content from JPanel take less space then my frame, then will be lot of space between Jpanels.
If my content from JPanel it's bigger then my frame, the Pannels will go over each other and my scroll from scrollPanel wont activate.
frame = new Frame();
splitPane = new SplitPane();
scrollPane = new ScrollPane();
frame.add(splitPane);
scrollPane.setViewportView(new Lesson());
splitPane.setRightComponent(scrollPane);
splitPane.setLeftComponent(new JTree());
Where Frame, SplitPane, ScrollPane() are classes that extends JFrame, JSplitPane, JScrollPane. Atm they only have a constructor, after it will work, I want to make some customization there.
public class Lesson extends JPanel {
private static final long serialVersionUID = 1L;
public Lesson() {
customize();
String text = "text from pictures";
add(new Paragraph(text));
add(new Paragraph(text));
}
private void customize() {
BoxLayout boxLayout = new BoxLayout(this, BoxLayout.PAGE_AXIS);
setLayout(boxLayout);
}
}
public class Paragraph extends JPanel {
private static final long serialVersionUID = 1L;
public Paragraph(String text) {
setLayout(new FlowLayout(FlowLayout.LEFT));
setPreferredSize(new Dimension());
StringTokenizer splitStringTokenizer = new StringTokenizer(text, " ");
while(splitStringTokenizer.hasMoreTokens()){
add(label(splitStringTokenizer.nextToken().toString()));
}
}
private JLabel label(String string){
JLabel jlabel= new JLabel(string);
return jlabel;
}
}
Any hints about how I can resolve this ? Ty in advance.
A BoxLayout respects the maximum and minimum sizes of components added to it. You are using a FlowLayout o the Paragraph panel. The preferred size is always one line of components.
The panel will shrink until there is only one line displayed or grow to occupy all the space.
When there is more space the panels are allowed to grow.
Override the getMaximum/MinimumSize() of your Paragraph panel to return the preferred size.
The question is why are you using a panel of labels to display text. Why are you not using a text area.
Or another option may be to use the WrapLayout which will wrap components automatically and recalculate the preferred size based on the wrapping. You will still want to override the getMinimum/Maximum size calculations to return the preferred size.
I want later to add some mouse listener to some of jlabels.
Why? Again if you use a text area, you can add the MouseListener directly to the text area and then you can use the caret position (or convert the mouse position to an offset in the text area) to determine what word the mouse is over and then do your processing.

Automatically size JPanel inside JFrame

I have a JPanel subclass on which I add buttons, labels, tables, etc. To show on screen it I use JFrame:
MainPanel mainPanel = new MainPanel(); //JPanel subclass
JFrame mainFrame = new JFrame();
mainFrame.setTitle("main window title");
mainFrame.getContentPane().add(mainPanel);
mainFrame.setLocation(100, 100);
mainFrame.pack();
mainFrame.setVisible(true);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
But when I size the window, size of panel don't change. How to make size of panel to be the same as the size of window even if it was resized?
You can set a layout manager like BorderLayout and then define more specifically, where your panel should go:
MainPanel mainPanel = new MainPanel();
JFrame mainFrame = new JFrame();
mainFrame.setLayout(new BorderLayout());
mainFrame.add(mainPanel, BorderLayout.CENTER);
mainFrame.pack();
mainFrame.setVisible(true);
This puts the panel into the center area of the frame and lets it grow automatically when resizing the frame.
You need to set a layout manager for the JFrame to use - This deals with how components are positioned. A useful one is the BorderLayout manager.
Simply adding the following line of code should fix your problems:
mainFrame.setLayout(new BorderLayout());
(Do this before adding components to the JFrame)
If the BorderLayout option provided by our friends doesnot work, try adding ComponentListerner to the JFrame and implement the componentResized(event) method. When the JFrame object will be resized, this method will be called. So if you write the the code to set the size of the JPanel in this method, you will achieve the intended result.
Ya, I know this 'solution' is not good but use it as a safety net.
;)
From my experience, I used GridLayout.
thePanel.setLayout(new GridLayout(a,b,c,d));
a = row number, b = column number, c = horizontal gap, d = vertical gap.
For example, if I want to create panel with:
unlimited row (set a = 0)
1 column (set b = 1)
vertical gap= 3 (set d = 3)
The code is below:
thePanel.setLayout(new GridLayout(0,1,0,3));
This method is useful when you want to add JScrollPane to your JPanel. Size of the JPanel inside JScrollPane will automatically changes when you add some components on it, so the JScrollPane will automatically reset the scroll bar.
As other posters have said, you need to change the LayoutManager being used. I always preferred using a GridLayout so your code would become:
MainPanel mainPanel = new MainPanel();
JFrame mainFrame = new JFrame();
mainFrame.setLayout(new GridLayout());
mainFrame.pack();
mainFrame.setVisible(true);
GridLayout seems more conceptually correct to me when you want your panel to take up the entire screen.

Categories