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.
Related
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
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.
I'm looking for a way to fill JTable from bottom to top, for example:
1 row:
[clean space]
row1
after adding 2nd row:
[clean space]
row2
row1
Looked at ComponentOrientation - seems it allows only right-to-left but not bottom-to-up
Also don't see any ways by using LookAndFill
Any ideas?
I found a solution, thank you guys!
It's pretty simple by extracting table header to BorderLayout.NORTH and adding table entries to BorderLayout.SOUTH. This allows to make table growing from bottom to top.
Table entries can further be reversed by entries decorator by this way.
Code snippet below:
final MyTableModel model = new ReverseOrderModelDecorator(new MyTableModel());
final JTable table = new JTable(model);
JTableHeader header = table.getTableHeader();
JPanel mainPanel = new JPanel(new BorderLayout());
mainPanel.add(header, BorderLayout.NORTH);
mainPanel.add(table, BorderLayout.SOUTH);
thank you guys!
I hope this is the behaviour you are looking for:
import java.awt.ScrollPane;
import java.util.Collections;
import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
/**
*
* #author Skynet
*/
public class JTableReverseFill {
public static void main(String[] args) {
Runnable r = new Runnable(){
#Override
public void run() {
JFrame frame = new JFrame("jtable-reverse");
frame.setSize(200,200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTable jt = new JTable();
MyReversedTableModel mtm = new MyReversedTableModel();
mtm.addColumn("col1");
mtm.addColumn("col2");
for(Integer i = 0; i < 1000; i++)
{
mtm.addRow(new Object[]{"cell" + i.toString(), "cell" + i.toString() + i.toString()});
}
jt.setModel(mtm);
ScrollPane sp = new ScrollPane();
sp.add(jt);
frame.add(sp);
frame.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
public static class MyReversedTableModel extends DefaultTableModel
{
public void reverse()
{
Collections.reverse(getDataVector());
}
#Override
public void addRow(Object[] rowData) {
reverse();
super.addRow(rowData);
reverse();
}
}
}
You can also call reverse() outside of the model to save some cpu time.
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.
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.