Java Swing one-row scrollable container? - java

I'm writing an app, that needs some kind of one-row JList to store formula objects. I first tried with just buttons as objects with text on them, but it was not good. Then I made one-row JList but all it's cells have the same width, and it looks like this
(a scrollable area). So "<" will have the same width as others and it looks bad.
Is there a way to force list cells to use their real width? Or there is any cool container that just can store objects(just text) with scrolling over them?
With buttons it looks like

How about you use the JTable which you can configure it to have a single row?
Example Code:
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
public class JTableTest {
JFrame f;
JTable j;
JTableTest()
{
f = new JFrame();
f.setTitle("JTable Example");
String[][] data = {
{ "F=ma", "e=mc^2", "a^2=b^2+c^2" }
};
String[] columnNames = { "Newton", "Einstein", "Pythagoras" };
j = new JTable(data, columnNames);
j.setBounds(30, 40, 200, 300); //Position x,y & Size of JTable height,width
JScrollPane sp = new JScrollPane(j);
f.add(sp);
f.setSize(500, 200);
f.setVisible(true);
}
public static void main(String[] args)
{
new JTableTest();
}
}
By default, the width of JTable cells are fixed. You can change them, however, using:
j.getColumnModel().getColumn(0).setPreferredWidth(5); //Set Width=5 for first column

Related

Java fit JDialog to JTable if table size is less than a set value

I have a JDialog with two panels: a JTable and a button. I want to set JDialog so that (maxHeight= 600 pixels):
(1) If table height is less than maxLength it shows table fully with no blank space, but all rows fit in.
(2) If the height is greater than maxHeight it restricts the height to maxHeight and shows scrollbar on the side.
So far I have most of the JDialog working, but I can't figure out how to control the height of the JTable.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
public class TestGUI {
public static void main(String[] args) {
int a=10;
Object[][] data = new Object[a][2]; //Fill table with some data
for (int i = 0; i < a; i++) {data[i][0]=i; data[i][1]=i*i; }
JDialog dialog = new JDialog();
dialog.setLayout(new BorderLayout());
String[] header = {"Number", "Square"};
DefaultTableModel model = new DefaultTableModel(data, header);
JTable table = new JTable(model);
table.setPreferredScrollableViewportSize(new Dimension(450, 600));
table.setFillsViewportHeight(true);
JScrollPane js = new JScrollPane(table);
js.setVisible(true);
dialog.add(js, BorderLayout.CENTER);
JButton okButton = new JButton(new AbstractAction("OK") {
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
dialog.setVisible(false);
}
});
JPanel buttonPanel = new JPanel();
buttonPanel.add(okButton);
dialog.add(buttonPanel, BorderLayout.SOUTH);
//dialog.setSize(new Dimension(300, 600));
dialog.setMinimumSize(new Dimension(255, 175));
dialog.setVisible(true);
}
}
Hard-coded pixel sizes are almost never a good idea. Other users won’t have the same fonts as you, and even those who do may be using different font sizes. (A 12 point font is a font whose lines of text are 12⁄72 inch high, so even if the user has the same font, the dot pitch of the user’s monitor may affect how many pixels each character uses.)
Instead of maxHeight, define a maxVisibleRows variable. Your table should use getRowHeight to compute its size based on the desired number of rows:
int visibleRows = model.getRowCount();
visibleRows = Math.max(1, visibleRows);
visibleRows = Math.min(maxVisibleRows, visibleRows);
Dimension size = table.getPreferredScrollableViewportSize();
size.height = table.getRowHeight() * visibleRows;
table.setPreferredScrollableViewportSize(size);
Now your JTable, and its enclosing JScrollPane, will have a preferred size consistent with what I think you’re seeking, which means you can (and should) use pack().
dialog.pack();
dialog.setResizable(false);
If your table may potentially have a lot of rows, you should consider avoiding any restrictions on the size of the JDialog. If there are hundreds of rows, users will not appreciate being forced to look at only eight at a time.

JTable auto resizing to JScrollPane height and width

I have been reading all over the internet to try to find a solution to my problem.
Can anyone help me. How can I auto resize Jtable's height to fit parent container when there aren't enough rows for scrollbar to show. thanks
UPDATE: code that shows my problem, and how suggested solution is not helping.thanks
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JScrollPane;
import javax.swing.JTable;
public class t extends JFrame {
private JPanel contentPane;
private JTable table;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
t frame = new t();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public t() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(new BorderLayout(0, 0));
JScrollPane scrollPane = new JScrollPane();
contentPane.add(scrollPane, BorderLayout.CENTER);
table = new JTable(10,10);
table. setFillsViewportHeight( true );
scrollPane.setViewportView(table);
}
}
How can I auto resize Jtable's height to fit parent container when there aren't enough rows for scrollbar to show.
I think you are looking for:
table. setFillsViewportHeight( true );
Edit:
but doesn't seem to work...
Add the following lines of code to your example:
contentPane.setBackground(Color.RED);
scrollPane.getViewport().setBackground(Color.BLUE);
and you will see a red border.
Then remove:
table. setFillsViewportHeight( true );
and you will see red and blue, indicating that the table height was originally increased.
If you are expecting to see empty cells painted then it won't work. The table can only paint what is in the model. If you want more rows of data painted, then you need to add more rows of data to the model. And if the height decreases you need to remove data from the model.
Of course now you need to track which is "valid" rows of data and which is "filler" rows of data. So you would need to create a custom TableModel to manage this. You would then add a ComponentListener to the table to handle the height changes in the table and then do your manipulation of the TableModel.

How do I remove the A on the top of the JTable inside a JScrollPane?

Why is there an A on the top of the table?
I placed a JTable inside a JScrollPane to make it scrollable.
Are there methods that I need to place?
I did not place a letter A though so I cant track.
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import javax.swing.BoxLayout;
import javax.swing.JTable;
import javax.swing.border.LineBorder;
import java.awt.Color;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
public class Rawr {
private JFrame frame;
private JScrollPane scrollPane;
private JTable table;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Rawr window = new Rawr();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public Rawr() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
frame.getContentPane().add(panel, BorderLayout.CENTER);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
scrollPane = new JScrollPane();
scrollPane.setToolTipText("");
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
panel.add(scrollPane);
table = new JTable(100, 1);
table.setBorder(new LineBorder(new Color(0, 0, 0)));
scrollPane.setViewportView(table);
}
}
How do I remove it? Thanks!
Set the column name explicitly using:
String[] colNames = new String[]{"Your Column Name"};
DefaultTableModel defaultTableModel = new DefaultTableModel(colNames, 100);
table = new JTable(defaultTableModel);
If you create a table using new JTable(100, 1) you will see the A, B and so on column headers because the constructor javadoc says:
Constructs a JTable with numRows and numColumns of empty cells using DefaultTableModel.
Since the JTable constructor does not have any information about the column headers. It can only create a DefaultTableModel that does not know any column header names.
The DefaultTableModel extends AbstractTableModel and the javadoc of AbstractTableModel.getColumnName() says
Returns a default name for the column using spreadsheet conventions: A, B, C, ... Z, AA, AB, etc. If column cannot be found, returns an empty string.
Add the following code after the creation of your table.
String[] columns = new String[]{"Column Name"};
((DefaultTableModel)table.getModel()).setColumnIdentifiers(columns);
How do I remove it?
A JTable is designed to display data with a header to describe the data in the column.
Since you only have a single column of data, if you don't want the header then don't use a JTable. Instead you can use a JList.
Read the section from the Swing tutorial on How to Use Lists for more information and examples.

Adding rows of JTextFields to a JScrollPane

I need some advice on which Swing Components to choose in order to achieve the following:
I have something like a "table" structure, that every time that I click the "Add" button, another "row" should be inserted on the "table". Each row is composed of 2 JTextField. The problem I am having with the GridLayout (the layout used in the pictures below) is that if I add another row, then the heights of the text fields will be shortened and I don't want that (picture on the right), I want to preserve the same height for every row.
What I would like to happen is to have the extra row appear below the last one, so that I could use the JScrollPane and scroll to see it.
Should I use another layout rather than the GridLayout? Maybe the AbsoluteLayout or even using the Table Component?
Thanks.
I would use a JTable and set the row height to whatever you desire. For example:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
public class TableEg {
private static final int ROW_HEIGHT = 40;
private static final String[] TABLE_COLUMNS = {"Foo", "Bar"};
private static void createAndShowGui() {
final DefaultTableModel tableModel = new DefaultTableModel(TABLE_COLUMNS, 2);
JTable table = new JTable(tableModel );
table.setRowHeight(ROW_HEIGHT);
JScrollPane scrollpane = new JScrollPane(table);
JButton addRowBtn = new JButton(new AbstractAction("Add Row") {
#Override
public void actionPerformed(ActionEvent arg0) {
tableModel.addRow(new String[]{"", ""});
}
});
JPanel btnPanel = new JPanel();
btnPanel.add(addRowBtn);
JFrame frame = new JFrame("TableEg");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(scrollpane, BorderLayout.CENTER);
frame.getContentPane().add(btnPanel, BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Let's say that you add your JTextField in a Jpanel, and you Jpanel in a JScrollPane. Now you would set a preferredSize for you JScrollPane (since you want a fixed displayable area), but you modify the height of the JPanel dinamically based in the amount of JTextField you are placing at that time.
In other words, if you have 2 JTextField in a Jpanel set with GridLayout of 2 columns; you JTextField would take the entire height of the Jpanel; but if you include 2 more they would have to make room for this two and therefore shortening.
Notice that you have 2 rows in a JPanel set to "100" height each row would use "50". if you add another row but also modify the height of the JPanel to "150" each JTextField would still take "50" pixels.
I am a newbie, and it is a possibility that i am not 100% right; if that it is the case "Sorry". I just wanted help.
Try this....
JScrollPane scroll = new JScrollPane(Your_Table);
This will make your table to scroll....

How to change column width of a table

For the following code, I am not able to set the column size to a custom size. Why is it so?Also the first column is not being displayed.
import java.awt.BorderLayout;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.table.TableColumn;
public class Trial extends JFrame{
public void create(){
JPanel jp = new JPanel();
String[] string = {" ", "A"};
Object[][] data = {{"A", "0"},{"B", "3"},{"C","5"},{"D","-"}};
JTable table = new JTable(data, string);
jp.setLayout(new GridLayout(2,0));
jp.add(table);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
TableColumn column = null;
for (int i = 0; i < 2; i++) {
column = table.getColumnModel().getColumn(i);
column.setPreferredWidth(20); //custom size
}
setLayout(new BorderLayout());
add(jp);
}
public static void main(String [] a){
Trial trial = new Trial();
trial.setSize(300,300);
trial.setVisible(true);
trial.setDefaultCloseOperation(Trial.EXIT_ON_CLOSE);
trial.create();
}
}
You've got a couple of issues here. First and foremost, Always initialize your JFrame from the Swing EDT as such:
public static void main(String[] a) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Trial trial = new Trial();
trial.setSize(300, 300);
trial.setDefaultCloseOperation(Trial.EXIT_ON_CLOSE);
trial.create();
}
});
}
Failure to do so will lead to subtle errors. Second: JTables like to exist within JScrollPanes. That's why you don't see the column headers:
JScrollPane pane = new JScrollPane();
pane.setViewportView(table);
jp.add(pane);
With the above done, I see your tiny little columns, each 20 pixels wide.
When autoresize mode is set to off the column widths will not be adjusted at all when the table is layed out. From JTable's doLayout() documentation:
AUTO_RESIZE_OFF: Don't automatically
adjust the column's widths at all. Use
a horizontal scrollbar to accomodate
the columns when their sum exceeds the
width of the Viewport. If the JTable
is not enclosed in a JScrollPane this
may leave parts of the table
invisible.
Try adding the JTable to a JScrollPane and then adding that to the panel.

Categories

Resources