I have a JTable in a JScrollPane. If the screen shows half of a row in the JTable, when clicking on the JTable, the JScrollPane scrolls automatically to show the entire row.
How do I stop that behavior, such that a click will not scroll the JScrollPane.
Thanks!
The behavior is enforced by calling scrollRectToVisible() from the table's UI delegate, typically derived from BasicTableUI. Short of supplying your own delegate, you can use setPreferredScrollableViewportSize() to make the height of enclosing Container an intergral multiple of the rowHeight, as shown below and in this example.
private static final int N_ROWS = 8;
private JTable table = new JTable();
...
Dimension d = new Dimension(
table.getPreferredScrollableViewportSize().width,
N_ROWS * table.getRowHeight());
table.setPreferredScrollableViewportSize(d);
add(new JScrollPane(table));
Related
I have a tablePanel which is a JScrollPane,and initialized with a JTable, the JTable initialized with a defaultTableModel.When I trying to add some rows to the table, but didn't see the scroll bar, appriciated for any reply.
JFrame jFrame = new JFrame();
//rows will be added dynamically.
DefaultTableModel defautTableModel = new DefaultTableModel(null,columnNames){
#Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
JTable jTable = new JTable(defautTableModel);
jTable.setLocation(20,60);
jTable.setSize(950,450);
jTable.setRowHeight(25);
jTable.getColumn("No.").setMaxWidth(45);
jTable.getColumn("position").setMaxWidth(45);
...
JTableHeader jTableHeader = jTable.getTableHeader();
jTableHeader.setLocation(20,30);
jTableHeader.setSize(950,30);
jTableHeader.setFont(new Font(null, Font.BOLD, 16));
jTableHeader.setResizingAllowed(true);
jTableHeader.setReorderingAllowed(true);
JScrollPane tablePanel = new JScrollPane(jTable);
tablePanel.setLayout(null);
tablePanel.add(jTableHeader);
tablePanel.add(jTable);
jFrame.setContentPane(tablePanel);
tablePanel.setLayout(null); is the primary cause of your problem. A JScrollPane has its own layout manager which is used to manage the scrollbars, view port and headers.
tablePanel.add is your next problem, as you shouldn't be adding components to the JScrollPane. Instead, you should be setting the JScrollPane's JViewPort.
But, since you're using JScrollPane tablePanel = new JScrollPane(jTable);, there's actually no need for the three lines which follow it.
I would highly recommend that you take a closer look at:
How to us tables
How to use scroll panes
Laying Out Components Within a Container
Now, before you tell me how nothing I've suggested actually works, go and re-read Laying Out Components Within a Container - this is the corner stone concept you will need to understand and master before Swing really begins to work for you
JScrollPane tablePanel = new JScrollPane(jTable);
// No need for the below code
/*tablePanel.setLayout(null);
tablePanel.add(jTableHeader);
tablePanel.add(jTable);*/
jFrame.setContentPane(tablePanel);
I have a JScrollPane with a number of JLabel objects in a panel using a GridBagLayout. Each of the labels is displaying HTML text with rich elements which varies at run time.
I would like all labels to have the same width (driven by the width of the scroll pane) but vary in height depending on their content with the text wrapping (as is handled automatically by JLabel). If the labels exceed the scroll pane's height then a vertical scroll bar should appear.
Here is some sample code to demonstrate the problem:
public class ScrollLabels extends JFrame {
private final JPanel labelPanel = new JPanel(new GridBagLayout());
private final GridBagConstraints c = new GridBagConstraints();
public ScrollLabels() throws HeadlessException {
super("Scroll Labels");
}
public void createUI() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JScrollPane scroller = new JScrollPane(labelPanel);
add(scroller);
c.gridx = 0;
c.gridy = GridBagConstraints.RELATIVE;
c.fill = GridBagConstraints.HORIZONTAL;
addLabel("Here is <em>Rich Text</em>");
addLabel("Here is <ul><li>A</li><li>List</li></ul>");
addLabel("Here is <table><tr><th>A</th><th>Table></th></tr></table");
addLabel("Here is more <em>Rich Text</em>");
addLabel("Here is even more <b>Rich Text</b>");
addLabel("Here is a long sentence that should wrap when the panel "
+ "is too small for the text.");
pack();
}
private void addLabel(String text) {
JLabel label = new JLabel("<html>" + text + "</html>");
label.setBorder(BorderFactory.createEtchedBorder());
labelPanel.add(label, c);
}
public static void main(String[] args) {
ScrollLabels frame = new ScrollLabels();
frame.createUI();
frame.setVisible(true);
}
}
It correctly resizes the labels horizontally and shows scroll bars where appropriate. What it doesn't do is resize labels vertically to fit them within the scroll pane.
Here are the various things I have tried:
Changing the GridBagConstraint values. There are good controls for how to expand and contract components but I can't see any way to set a min or max width.
Setting the JScrollPane scroll bar policy to never show horizontal scroll bars. This just cuts off the label text rather than wrapping the text.
Manually setting the label size - i.e. setting the width from the scroll pane and the height depending on the text. I can't see an easy way to get the correct height of rich HTML text given a fixed width. In any case I'd prefer to have a layout manager that can do the job rather than manually coding preferred sizes.
The one thing I haven't tried yet is creating a custom layout manager. I suspect this might be the right answer but would like to see if any of you have an easier solution that I'm not seeing.
I would like all labels to have the same width (driven by the width of the scroll pane) but vary in height depending on their content
You need to implement the Scrollable interface on your panel and override the getScrollableTracksViewportWidth() method to return true. You will also need to provide default implementations for the other methods of the interface.
Or you can use the Scrollable Panel which provides method that allow you to set the scrolling properties.
I created a JFrame with Java Swing using a BorderLayout. Both east and west layout are fixed with some components, while BorderLayout at the center can change depending on what the user does. At the beginning there is a picture,
panelDinamycCenter = new JPanel ();
JScrollPane = new JScrollPane (panelDinamycCenter);
panelDinamycCenter.add (new JLabel ( "", new Imagelcon ( "......."), JLabel.CENTER));
jFrame.getContentPane (). add (JScrollPane, BorderLayout.CENTER);
Then a data entry screen, for which I used a GridBagLayout. In order to remove the picture and to insert the new screen I used this:
panelDinamycCenter.removeAll (),
then I add the various components. After
setVisible (true);
I have now created a JTable, to be included in panelDinamycCenter,
panelDinamycCenter.removeAll ();
String [] [] matrixValori = new String [arrayOggCreaJTableDeroghe.length] [arrayJTableNomeColumnDeroghe.length];
for (int i = 0; i <arrayOggCreaJTableDeroghe.length; i ++) {
matrixValori [i] = arrayOggCreaJTableDeroghe [i] .creaArrayString ();
}
DefaultTableModel model = new DefaultTableModel (matrixValori, arrayJTableNomeColumnDeroghe);
JTable JTable = new JTable (model);
jTable.setAutoResizeMode (JTable.AUTO_RESIZE_OFF);
panelDinamycCenter.add (JTable);
jFrame.setVisible (true);
All right, but I can not see the names of the columns. Why?
As shown in How to Use Tables: Adding a Table to a Container, "The scroll pane automatically places the table header at the top of the viewport." At a minimum, you need to replace the JScrollPane removed by removeAll():
JTable jTable = new JTable(model);
panelDinamycCenter.add(new JScrollPane(jTable));
Among alternatives, consider these:
Add the table header to PAGE_START, as suggested here.
Instead of removing and restoring, use CardLayout to switch between views.
I am trying to make a JTable that has a width of 500. The problem is that the JScrollPane associated with the table doesn't appear next to the table.
Here is the relevant code:
// Create authorsPanel
JPanel authorsPanel = new JPanel(new BorderLayout(5,5));
authorsPanel.setBorder( new TitledBorder("Author Selection") );
// Configure author table
DefaultTableModel authorstableModel = new DefaultTableModel(new String[80][1], new String[]{"Authors"}) {
#Override
public boolean isCellEditable(int row, int column) {
//all cells false
return false;
}
};
JTable authorsTable = new JTable(authorstableModel);
authorsTable.getColumnModel().getColumn(0).setPreferredWidth(500);
authorsTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
try {
authorsTable.setAutoCreateRowSorter(true);
} catch(Exception continuewithNoSort) {
}
JScrollPane tableScroll = new JScrollPane(authorsTable);
Dimension tablePreferred = tableScroll.getPreferredSize();
tableScroll.setPreferredSize(new Dimension(500, tablePreferred.height/3));
authorsPanel.add(tableScroll);
Here is a screenshot:
When I get rid of the line:
authorsTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
Then the table returns to being the full width of the panel, so it seems like I need this line.
The java docs on BorderLayout states :
The components are laid out according to their preferred sizes and the
constraints of the container's size. The NORTH and SOUTH components
may be stretched horizontally; the EAST and WEST components may be
stretched vertically; the CENTER component may stretch both
horizontally and vertically to fill any space left over.
You have used authorsPanel.add(tableScroll) to add the JScrollPane to the JPanel. So you are basically adding it to the center. So this is going to occupy the whole space that is lying vacant.
The solution to your problem lies in choosing a different layout. I could suggest MigLayout which is very versatile and you can get all kinds of effects using it.
You add your scroll pane to a panel with BorderLayout. BorderLayout does not care about preferred size. Use e.g GridBagLayout with proper constraints or you can BoxLayout (with horizontal flow) placing the table first and an empty panel second as place holder.
I have a BoxLayout (in a panel of a BorderLayout) in which I've put a JTable and a button vertically. I would like the table to have a fixed width and that the height should resize itself up to filling the panel. At the moment, I'm fine with the displayed width but not that it's filling up the whole panel height. For example, if there are zero data in the table, I would like only the column names to be shown. I've tried things like setViewportView() and setPreferredSize(), but can't really make it work. Any suggestions? Is it in the layout or scrollpane?
String[] columnNames = { "Date", "Type"
};
Object[][] data = {
};
JTable myTable = new JTable(data, columnNames);
JButton okButton = new JButton("OK");
JPanel panWest = new JPanel();
panWest.setLayout(new BoxLayout(panWest, BoxLayout.PAGE_AXIS));
JScrollPane scrollPane = new JScrollPane(myTable);
panWest.add(scrollPane);
panWest.add(okButton);
EDIT
This is what ended up working:
Dimension dimension = new Dimension();
dimension.height = (myTable.getRowCount()*myTable.getRowHeight())+
myTable.getTableHeader().getPreferredSize().height;
dimension.width = myTable.getColumnModel().getTotalColumnWidth();
scrollPane.setMaximumSize(dimension);
I would like the table to have a fixed width and that the height
should resize itself up to filling the panel.
and
I have a BoxLayout (in a panel of a BorderLayout) in which I've put a
JTable and a button vertically.
there are three (mentioned only simple) ways
use built_in LayoutManager for JPanel - FlowLayout (FLowLayout.CENTER),
override FLowLayout.LEFT or RIGHT in the case that you want to aling,
JComponent laid by FlowLayout never will be resizable without programatically to change XxxSize and notified by revalidate & repaint,
set proper size for JScrollPane by override JTable.setPreferredScrollableViewportSize(new Dimension(int, int));,
JScrollPane accepts this Dimension as initial size, required is usage of JFrame.pack(), before JFrame.setVisible(true)
BoxLayout accepts min, max and preferred size, override all these three sizes for JScrollPane
(half solution, but most comfortable) change LayoutManager for JPanel to BorderLayout,
put JScrollPane with JTable to BorderLayout.EAST/WEST area,
then override JTable.setPreferredScrollableViewportSize(new Dimension(int, int));,
JScrollPane will occupy whole area for BorderLayout.EAST/WEST and will be resizeable only on heights coordinates
use MigLayout, here are a few posts about MigLayout and JScrollPane (with JTextArea, JTable)