Displaying scrollable JTable - java

I'm having trouble displaying a scrollable JTable in my contentPane, the table should be underneath the label, but nothing shows up. However, when I remove the scrollPane, the table is displayed.
public void populateJTable(int resultCount, String[] closeNames, String[] closeCities) {
String[] columnTitles = {"Brewery", "City"};
String[][] data = new String[resultCount][columnTitles.length];
for(int i = 0; i < closeNames.length; i++) {
String tempBrewery = closeNames[i];
String tempCity = closeCities[i];
data[i][0] = tempBrewery;
data[i][1] = tempCity;
}
table = new JTable(data, columnTitles);
table.setBounds(20, 95, 580, 250);
JScrollPane scrollPane = new JScrollPane(table);
table.setFillsViewportHeight(true);
contentPane.add(scrollPane);
}

However, when I remove the scrollPane, the table is displayed.
table.setBounds(20, 95, 580, 250);
Based on the above code it looks like you are using a null layout since you see the table.
However, when you add the table to the scrollpane, the scrollpane doesn't have a size so there is nothing to paint.
Don't use a null layout!!!
Swing was designed to be used with layout managers. Learn how to use them and the code will be easier to code and work better.
JScrollPane scrollPane = new JScrollPane(table);
table.setFillsViewportHeight(true);
contentPane.add(scrollPane);
So now when you start using layout managers and you add a component to a visible GUI you need to revalidate() and repaint()` the panel that changed to invoke the layout manager on the panel. So you need to add:
contentPane.revalidate();
contentPane.repaint();
However, a better solution is to NOT keep creating a new JTable and JScrollPane. Instead you can create those components when you create the frame and add them to the frame.
Then when you do the search you just create a new TableModel with the search results and then you update the table using:
table.setModel( .... );
The table will repaint itself automatically.

Related

JComboBox showing only if it has a single item

I have a JPanel with a CardLayout and a JComboBox inside it. They are dinamically filled with data taken from a JTable. If the JComboBox has a single item it shows just fine, but if I fill it with more than one it doesn't show.
JPanel intervalPanel = new JPanel;
CardLayout intervalLayout = new CardLayout();
intervalPanel.setLayout(intervalLayout);
JComboBox intervalComboBox = new JComboBox();
for (int i = 0; i < table.getRowCount(); i++) {
String name = (String) table.getValueAt(i, 0);
intervalComboBox.addItem(name);
JPanel p = new JPanel();
p.setName(name);
p.add(intervalComboBox);
p.add(new JLabel(name));
intervalPanel.add(p, name);
}
A Swing component can only have a single parent.
p.add(intervalComboBox);
The above statement keeps removing the combo box from the previous panel and adds it to the current panel.
but if I fill it with more than one it doesn't show.
So the reason it doesn't show is because it is only visible on the last card, but you current see the first card.
The better solution is to NOT add the combo box to the panel in the CardLayout. Instead your main panel should use a BorderLayout. Then the basic logic would be something like:
JPanel main = new JPanel( new BorderLayout() );
JComboBox comboBox = new JComboBox(...);
main.add(comboBox, BorderLayout.PAGE_START);
JPanel card = new JPanel( intervalLayout );
main.add(card, BorderLayout.CENTER);
frame.add( main );
Then you just add child panels to the "card" panel as required.
Read the section from the Swing tutorial on How to Use CardLayout for a complete working demo that uses the above design concept.

JScrollPane, add to JPanel or JTable?

I have Googled for hours on this issue but nothing seems to work.
I have a JTable with a JPanel inside a frame. The table has data from a database but there is a considerable amount of data to store (hence require the JScrollPane)
Here is my code:
public GeneralDisplay()
{
Insets insets = getInsets();
panel = new JPanel();
scrollVert = new JScrollPane(panel);
scrollVert.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scrollHor = new JScrollPane(panel);
scrollHor.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
newSoftwareBtn = new JButton("New");
removeSofwtareBtn = new JButton("Remove");
editSofwtareBtn = new JButton("Edit");
ResultSet results;
try
{
results = statement.executeQuery("SELECT * FROM Software");
cSoftware = new JTable(buildTableModel(results));
}
catch(SQLException sqlEx)
{
JOptionPane.showMessageDialog(null, "Error: SQL error!");
//System.exit(1);
}
///////////////////////////////////////////////////
//Adding to form
///////////////////////////////////////////////////
getContentPane().add(panel);
cSoftware.setBackground(null);
cSoftware.getTableHeader().setBackground(null);
//pack();
panel.add(scrollVert);
panel.add(scrollHor);
panel.add(cSoftware.getTableHeader());
panel.add(cSoftware);
panel.add(newSoftwareBtn);
panel.add(removeSofwtareBtn);
panel.add(editSofwtareBtn);
panel.add(scrollVert);
panel.add(scrollHor);
panel.revalidate();
panel.repaint();
//////////////////////////////////////////////////////
//////////////////////////////////////////////////////
//Position on form
//////////////////////////////////////////////////////
Dimension size = newSoftwareBtn.getPreferredSize();
newSoftwareBtn.setBounds(5 + insets.left, 480 + insets.top, size.width, size.height);
size = removeSofwtareBtn.getPreferredSize();
removeSofwtareBtn.setBounds(55 + insets.left, 480 + insets.top, size.width, size.height);
size = editSofwtareBtn.getPreferredSize();
editSofwtareBtn.setBounds(105 + insets.left, 480 + insets.top, size.width, size.height);
In the image, the JScrollPane is visible in the area marked with a red square. I have more data in the table which is not visible, which is why I thought to add the JScrollPane to the table, but I also have buttons on my panel below the table which is why I wanted to add it to the panel.
My code might not be great as I have followed several tutorials on how to overcome the problem and kind of mashed them together.
Any help appreciated!
EDIT:
I have noticed that I added my scrolls to the panel twice. I have now removed that but still did not resolve the issue if that's what you thought it was
The other image is what happened when I added a GridLayout to the panel
Firstly, you don't need to create two JScrollPanes in order to have both a vertical and a horizontal scrollbar.
As far as the ScrollPane being seperated from the rest of your components, you need to add your JTable to the ScrollPane and then add that to the JPanel. Something like this:
JScrollPane scrollPane = new JScrollPane();
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
scrollPane.add(cSoftware);
panel.add(scrollPane);
//add buttons etc
In your original code, you added both your (empty) ScrollPanels as well as your table to the JPanel.
I think you confuse a JScrollPane for a JScrollBar:
A JScrollPane is a wrapper to which you add large content, and which will show JScrollBar (either vertical or horizontal, or both) when this content exceeds the size of the container.
A JScrollBar is the actual horizontal or vertical scroll bar that you click and scroll.
In general you should work with a JScrollPane and let it take care of the scroll bars for you.
Based on the above, the answer to your question is:
Add the JTable to the JScrollPane (new JScrollPane(table);). You need only one JScrollPane in your situation.
Add the JScrollPane to the JPanel (To which you can also add your buttons)
Add the JPanel to the JFrame
Additionally:
You should use layout managers (By default, a JPanel has a FlowLayout, which might not be very convenient).
You don't need to add your table and your table's header separately.
You don't need to use repaint() or revalidate()

Is it possible to change the way my data is currently displayed?

I am using a JTable and after it is filled with data, I have a search button at the bottom with a text input. Once I type in "Joe" it brings up all of joes details. However, these are displayed in one row going left to right (much like a spreadsheet row).
I was wondering if there was a way I can make it display this data in a different way? More like a table rather than going across in one individual row...
Please tell me if I need to show parts of my code as it is quite a bit and I'm unsure if I should paste it all in or not. (New to this site).
Thanks.
Code:
private void makeframe()
{
frame = new JFrame("Search");
frame.setPreferredSize(new Dimension(300, 300));
Container contentPane = frame.getContentPane();
contentPane.setLayout(new BorderLayout());
}
DefaultTableModel model = new DefaultTableModel();
model.addColumn("User");
model.addColumn("first name");
model.addColumn("surname");
//this goes on for a while
model.addRow(data);
JTable mainTable = new JTable(model);
contentPane.add(new JScrollPane (mainTable));
frame.setPreferredSize(new Dimension(1300, 200));
frame.pack();
frame.setVisible(true);
frame.setLocationRelativeTo(null);
You can try to create your panel in format you prefer, then use table with only 1 column. Place your pannel inside this column.

scrollpane blocks buttons in BorderLayout?

I have a really weird problem with a JScrollPane and a BorderLayout. For short explaination: i have a JTable which is inside the JScrollPane and this is with a JPanel and the JTableHeader on a JTabbedPane. Very Simple Layout. If i add just the JTable to my JPanel, the buttons are working. If i add the JScrollPane, the Buttons are not working anymore, so i cant click them! The ActionLister is never reached and i cant see the click-animation.
Some Sample code to explain:
d_pane = new JPanel();
d_button = new JPanel();
d_pane.add(table.getTableHeader(), BorderLayout.PAGE_START);
dl_scroll = new JScrollPane(table);
d_pane.add(dl_scroll, BorderLayout.CENTER);
// d_button is ridLayouted with 3 Buttons in there
d_pane.add(d_button, BorderLayout.PAGE_END);
1) The JScrollPane takes care of the table header itself. Don't add it to the pane.
2) the button does not seem to get the mouse events, probably because another component is above it - do you have other components/code in the setup?

How can I keep columns of a JTable from resizing when I resize the JFrame?

This code puts a JTable into a JFrame (sole component of the whole UI):
JFrame frame = new JFrame( "Title");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTable table = appender.createTable();
JScrollPane scrollPane = new JScrollPane(table);
table.setFillsViewportHeight(true);
frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
I also have some code to set the preferred size of the columns.
Nothing fancy. When the UI opens, the table takes up the whole view and I have no scroll bars. The combined preferred widths of the columns need more horizontal space than the windows is wide. Despite of that, there is no horizontal scroll bar and the columns are too narrow.
What do I have to do that
The columns are still resizable by the user
The current width is respected? I.e. when I change the width of one column, the width of the other columns should not change.
table.setAutoResizeMode( JTable.AUTO_RESIZE_OFF );
You can also add the scrollpane containing the table to a JPanel and then add the panel to the frame. That way the panel will change in size, not the scrollpane.

Categories