I have this code for show some data inside a JTable:
public class ShowResults extends JFrame {
public ShowResults(List<String> list) {
setSize(1000, 1000);
setLocationRelativeTo(null); //center
setVisible(true);
String[][] table_data = new String[pics.size()][table_header.length];
for (int i = 0; i < pics.size(); i++) {
//Fill table with data
}
JTable table = new JTable(new DefaultTableModel(table_data, table_header)) {
#Override
public boolean isCellEditable(int row, int column) {
//disable table editing
return false;
}
};
JScrollPane scroll_pane = new JScrollPane(table);
table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
table.getTableHeader().setReorderingAllowed(false);
table.getTableHeader().setResizingAllowed(false);
this.setLayout(new FlowLayout());
this.add(scroll_pane);
}
}
But table doesn't look as i expect. I would that scroll bar in only vertical (now is horizontal) and header of table show entire header names (now table is wrapped for some reason i don't know).
How can i do?
I would that scroll bar in only vertical (now is horizontal) and header of table show entire header names (now table is wrapped for some reason i don't know).
The reason is you set a new FlowLayout as the content pane's layout manager. This layout manager honors the components preferred size and therefore prevents the scroll pane resizes as you wish. I'd leave the default layout manager, which is BorderLayout, and add the scroll pane to the CENTER location.
On the other hand, you should make your frame visible after adding all your components to its content pane.
I would use a grid layout. Also try removing the scroll_pane for now and see if that makes a difference. I ran into problems using JScrollPane myself.
Related
I have a JScrollPane inside of a JTabbedPane tab. Into that JScrollPane I place a JPanel whose background is red and whose size is explicitly set.
This is what I get:
Note that in the second image, where the container frame has been resized, the component is being drawn under the scrollbar elements.
What's going on here? I've tried just about every combination of layout managers for all the components involved (as well as components besides JPanel - ultimately I want several JEditorPane here), and I cannot get anything to draw except under a big, blank, rectangle (is it a background? which?)
Code:
In main JFrame subclass:
// Called once on startup/layout.
public void refreshGUIState() {
for (int i = 0; i < client.getFrameStackLength(); i++) {
InferenceFrame frame = client.getFrame(i);
JScrollPane pane = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
JPanel wtf = new JPanel();
pane.setBackground(Color.YELLOW);
wtf.setBackground(Color.red);
wtf.setSize(100,100);
wtf.setPreferredSize(wtf.getSize());
pane.add(wtf);
workspace.addTab(Integer.toString(i), pane);
}
}
public GuiClient() throws CliException, ParticleSourceException {
super("L4 Interactive Prover");
setSize(800,600);
mainArea = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true);
mainArea.setDividerSize(2);
mainArea.setBackground(Color.DARK_GRAY);
getContentPane().add(mainArea);
/* ... menu bar init ... */
toolspace = new JPanel();
workspace = new JTabbedPane();
mainArea.add(toolspace);
mainArea.add(workspace);
this.validate();
refreshGUIState();
}
Edit: under the suspicion that JScrollPane was somehow not creating a viewport when its first child was added, as expected, I also tried the three-argument constructor. Same behavior.
Re-edit: Except I erred and left in the add() call. Whoops. Looks like that's it.
Instead of
pane.add(wtf);
you need
pane.setViewportView(wtf);
You can also do it when initialising the JScrollPane:
JScrollPane pane = new JScrollPane(wtf);
Or, in your case:
JScollPane pane = new JScrollPane(wtf, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
I got a JTable, which i applied AUTO_RESIZE_LAST_COLUMN to. It auto resizes last column when i drag the columns left or right..
However, the JTable are attached to a JPanel with a BorderLayout manager. When i resize the JFrame, the JPanel resize, and since the JTable fills the JPanel, the JTable resizes too. But when i resize the JFrame, the AUTO_RESIZE_LAST_COLUMN doesnt works, but instead it resizes all the columns.
I want it to only auto_resize the last column, when the JFrame changes size, instead of resize all columns.
code:
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
public class JTableResize extends JFrame {
private JTable table;
private JPanel panel;
private JScrollPane pane;
DefaultTableModel model = new DefaultTableModel();
public JTableResize() {
super("JTable - Resize Problem");
setLayout(new BorderLayout());
panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.setBackground(Color.red);
add(panel, BorderLayout.CENTER);
table = new JTable(model);
//panel.add(table);
model.addColumn("Resize");
model.addColumn("Problem");
model.addColumn("........");
model.addColumn("This should resize");
pane = new JScrollPane(table);
panel.add(pane);
//this is supposed to resize last column.. It works when you drag in the columns, but not when frame are resized
table.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
table.getTableHeader().setReorderingAllowed(false);
table.setShowVerticalLines(false);
for (int i = 0; i <= 50; i++) {
model.addRow(new Object[] {i, i, i, i});
}
}
public static void main(String[] args) {
JTableResize jtr = new JTableResize();
jtr.setSize(500, 500);
jtr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jtr.setVisible(true);
}
}
Check out the API documentation from the doLayout() method of JTable.
Before the layout begins the method gets the resizingColumn of the tableHeader. When the method is called as a result of the resizing of an enclosing window, the resizingColumn is null. This means that resizing has taken place "outside" the JTable and the change - or "delta" - should be distributed to all of the columns regardless of this JTable's automatic resize mode.
So this behaviour is not support by default.
Overriding the doLayout() method of the JTable and setting the "resizing column" to the last column seems to do the trick:
#Override
public void doLayout()
{
if (tableHeader != null)
{
TableColumn resizingColumn = tableHeader.getResizingColumn();
// Viewport size changed. Increase last columns width
if (resizingColumn == null)
{
TableColumnModel tcm = getColumnModel();
int lastColumn = tcm.getColumnCount() - 1;
tableHeader.setResizingColumn( tcm.getColumn( lastColumn ) ) ;
}
}
super.doLayout();
}
My prob is this....
JFrame ActualFrame = new JFrame("Actual frame");
JScrollPane pane = new JScrollPane(new JTable(data, columns));
ActualFrame.add(pane);
ActualFrame.add(PrintPreviewBtn);
PrintPreviewBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JFrame PreviewFrame = new JFrame("Preview");
PreviewFrame.add(pane, BorderLayout.CENTER);
}
When i run the program everything seems to b fine but when i press print preview button the preview frame shows off and when i maximize or resize the ActualFrame the table gets disappeared....
NOTE:
I m adding the pane to the preview frame to show as if it is a preview of the table displayed.....is ter any other method for print preview
A component can only belong to a single parent. When you add it to the PreviewFrame, it is been removed, automatically, from the ActualFrame.
Instead of using the previous panel, create a new JTable, using the model from the previous one.
Update
Printing tables is a little more complicated, as includes the headers, and the columns need to be resized to meet the requirements of the available space.
Take a look at the Printing Tables tutorial for some examples
For printing there is the java.awt.PrinterJob class. To show the standart print preview you should call:
PrinterJob job = PrinterJob.getPrinterJob();
job.printDialog();
The Reason for disappearance of JScrollPane from the ActualFrame is that: You are adding the same instance of pane in PreviewFrame. So the actual container of the pane is now PreviewFrame instead of ActualFrame. When you maximize or resize the ActualFrame,it repaint its child components. Since the pane now no longer belongs to the ActualFrame it does not show the pane now.
The best way to avoid this situation is to create a seperate JTabel instance first, instead of passing anonymous JTable class object within the constructor of JScrollPane while creating the object pane . Get the TableModel and TableColumnModel of that JTable instance. In previewFrame add a new instance of JScrollPane that will contain the new instance of JTable with same TableModel and TableColumnModel objects.
The Code would look something like this:
final JTable table = new JTable(data,columns);
JScrollPane pane = new JScrollPane(table);
ActualFrame.add(pane);
ActualFrame.add(PrintPreviewBtn);
PrintPreviewBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JFrame previewFrame = new JFrame("Preview");
javax.swing.table.TableModel tabModel = table.getModel();
javax.swing.table.TableColumnModel colModel = table.getColumnModel();
JScrollPane previewPane = new JScrollPane(new JTable(tabModel,colModel));
previewFrame.getContentPane().add(previewPane, BorderLayout.CENTER);
previewFrame.pack();previewFrame.setVisible(true);
}
I am putting a JTable into a JScrollPane
But When I set JTable Auto Resizeable, then it won't have horizontal scroll bar.
if I set AUTO_RESIZE_OFF, then the Jtable won't fill the width of its container when the column width is not big enough.
So how can I do this:
when the table is not wide enough, expand to fill its container width
when the table is wide enough, make it scrollable.
Thanks
You need to customize the behaviour of the Scrollable interface.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
public class TableHorizontal extends JFrame
{
public TableHorizontal()
{
final JTable table = new JTable(10, 5)
{
public boolean getScrollableTracksViewportWidth()
{
return getPreferredSize().width < getParent().getWidth();
}
};
table.setAutoResizeMode( JTable.AUTO_RESIZE_OFF );
final JScrollPane scrollPane = new JScrollPane( table );
getContentPane().add( scrollPane );
}
public static void main(String[] args)
{
TableHorizontal frame = new TableHorizontal();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setSize(400, 300);
frame.setVisible(true);
}
}
The above code basically sizes the component at its preferred size or the viewport size, whichever is greater.
If for some reason customising JTable is not an option (e.g. it might be created in third-party code), you can achieve the same result by setting it to toggle between two different JTable AUTO_RESIZE modes whenever the containing viewport is resized, e.g.:
jTable.getParent().addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(final ComponentEvent e) {
if (jTable.getPreferredSize().width < jTable.getParent().getWidth()) {
jTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
} else {
jTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
}
}
});
I found that all that is needed is to include
table = new JTable(model);
// this enables horizontal scroll bar
table.setAutoResizeMode( JTable.AUTO_RESIZE_OFF );
and then when the required viewport width and height have been calculated, include
frame.getContentPane().add(new JScrollPane(table))
table.setPreferredScrollableViewportSize(new Dimension(width,height));
If you set the Layout of its container to BorderLayout with a BorderLayout.CENTER layout constraint, then the JTable will auto resize to fit its container.
If you want to make a component scrollable, you can wrap the JTable with a JScrollPane.
setLayout(new BorderLayout());
add(new JScrollPane(new JTable()), BorderLayout.CENTER);
I am working inside of a quite complex eclipse based application, and having a problem with a JTable based custom component inside of a JSplitPane. The part of the application that I actually have access to is a panel, within a tab, within a panel, within the actual application, so there are a lot of things that can go wrong.
The specific problem that I'm having right now is that the table component is selecting the wrong cell when I click on it. If I select a cell in row 0, column 0, the cell that actually gets selected is at row 2, column 0, which is about 20 pixels below the actual click. This only happens if the table is in a JSplitPane though: if I just add the table itself to a panel, cell selection is correct.
What it seems like to me is that because the table is in a JSplitPane, the boundaries of the table (or maybe the viewport of the scroll pane containing the table?) are off by about 20 pixels somewhere. Another problem that I had which can back this theory up, is that scrolling the table caused repaints above the table: so for example, as I scrolled down, instead of the table scrolling, it actually moved upwards (painting over the components above the table) about 20 pixels before scrolling. I was able to workaround this problem by adding
jscrollpane.getViewport().setScrollMode(JViewport.BACKINGSTORE_SCROLL_MODE);
to the scrollpane that contained the table.
Because of all the custom components involved, I can't actually get a small app that shows the problem, but I have the next best thing, which is an app that shows the layout that I have (of course, it doesn't actually have the same problems). Any ideas on what might be causing the problem?
//Test class showing layout of table/splitpane
import javax.swing.*;
import java.awt.*;
public class SplitTest
{
private static JFrame frame;
private static JPanel buildTable()
{
JPanel tblPanel = new JPanel();
tblPanel.setLayout(new BorderLayout());
String[] cols = new String[]{"one", "two", "three", "four", "five", "six", "seven"};
Object[][] data = new Object[30][7];
for(int x = 0;x < data.length;x++)
for(int y = 0;y < data[x].length;y++)
data[x][y] = x + ", " + y;
JTable tbl = new JTable(data, cols);
JScrollPane scrollPane = new JScrollPane(tbl);
tblPanel.add(scrollPane, BorderLayout.CENTER);
return tblPanel;
}
private static JPanel buildTab()
{
JPanel pnl = new JPanel();
pnl.setLayout(new BorderLayout());
JPanel menuPnl = new JPanel();
menuPnl.setLayout(new FlowLayout(FlowLayout.LEFT));
menuPnl.add(new JLabel("label"));
menuPnl.add(new JComboBox(new String[]{"one", "two"}));
menuPnl.add(new JButton("Button"));
pnl.add(menuPnl, BorderLayout.NORTH);
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
splitPane.setLeftComponent(buildTable());
JPanel bottomPnl = new JPanel();
bottomPnl.setPreferredSize(new Dimension(800, 200));
bottomPnl.setBackground(Color.RED);
splitPane.setRightComponent(bottomPnl);
splitPane.setDividerLocation(.5);
pnl.add(splitPane, BorderLayout.CENTER);
return pnl;
}
private static JTabbedPane buildGUI()
{
JTabbedPane topLevelTabbedFrame = new JTabbedPane();
topLevelTabbedFrame.addTab("Tab 1", buildTab());
topLevelTabbedFrame.addTab("Tab 2", new JPanel());
topLevelTabbedFrame.addTab("Tab 3", new JPanel());
return topLevelTabbedFrame;
}
private static void createAndShowGUI()
{
frame = new JFrame("Split Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(buildGUI(), BorderLayout.CENTER);
// frame.setSize(new Dimension(800, 600));
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) throws Exception
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}
Because of all the custom components involved, I can't actually get a small app that shows the problem, but I have the next best thing, which is an app that shows the layout that I have (of course, it doesn't actually have the same problems).
I was about to tell you the posted code workd just fine, and the I read this.
Anyway, it seems the problem lies in all the custom components you added to the mix. For JTable and JSplitPane work fine alone.
What I would do is to remove components one by one until it works ( probably I will work when the code is similar to the one posted and there is nothing else there )
Or you can go the opposite way which is easier. Start with your sample code and then add more and more components until it fail.
You can take this opportunity to refactor and clean your code and move unneeded components. And even ( why not ) add test cases in the process.
Good luck.
Have you tries running it on a different box to check if its hardware related.
May be related to this bug
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4763448
As it turns out, the problem was with the order that the components were initialized and added to the split pane. So the eventual fix was to delay adding the table to the split pane until after the split pane was actually added to the panel, rather than adding the table to the split pane before adding the split pane to the panel. Making that small change fixed the issue.