using JTable as JScrollPane's columnHeader while maintaining width of each column - java

just looking for a quick answer: is it possible to use a JTable as a JScrollPane's columnHeader?
I have a configed JTable with different column width and column title, and plan to use the header as the columnHeader of a scrollpane. How can I achieve this? I set the table with
scrollPane.setColumnHeaderView(table);
but it doesn't show up.
so thanks to Guillaume Polet, it should be
scrollpane.setColumnHeaderView(table.getTableHeader());
but all the columns have the same width now although I set them with different values in my table. How could I let the table columns show different width?

If I understand you correctly, you want the column headers of your table to appear in the column headers of the viewport but you want something else in the viewport view?
Then you need to grab the table header and set it as the column header of the viewport.
Here is an example:
import java.awt.BorderLayout;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestTableHeader {
protected void initUI() {
Vector<Vector<Object>> data = new Vector<Vector<Object>>();
Vector<String> colNames = new Vector<String>();
for (int i = 0; i < 5; i++) {
colNames.add("Col-" + (i + 1));
}
table = new JTable(data, colNames);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
scrollpane = new JScrollPane();
scrollpane.setColumnHeaderView(table.getTableHeader());
scrollpane.setViewportView(new JLabel("some label in the viewport view"));
frame.add(scrollpane, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
private JTable table;
private JScrollPane scrollpane;
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException,
UnsupportedLookAndFeelException {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestTableHeader().initUI();
}
});
}
}

Related

Small Gap between Table and ScrollPane Border Java Swing

I'm trying To insert a JTable into a JScrollPane and I see a small gap between the borders of the table and the scroll Pane.And on the left side the table looks to be aligned to extreme left.Can someone please help me fix this.?
Removing setAutoResizeMode(JTable.AUTO_RESIZE_OFF) is fixing that.But I Need to turn that off.
this.dataTable = new SortableTable(this);
this.dataTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
this.dataTable.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
scrollPane = new JScrollPane(dataTable,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scrollPane.setPreferredSize(new Dimension(900,250));
scrollPane.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
You simply need to set the resize mode in a listener, when the component is resized. Here is an example:
import java.awt.Window;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import javax.swing.table.TableColumn;
public class TableTest implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new TableTest());
}
#Override
public void run() {
JTable table = new JTable(10, 3);
final JScrollPane scroller = new JScrollPane(table);
// update the resize mode when scroller is resized and window is shown
scroller.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
Window win = SwingUtilities.windowForComponent(scroller);
if (win != null && win.isVisible()) {
updateColumns(table);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
}
}
});
JFrame frm = new JFrame("Table");
frm.add(scroller);
frm.setSize(600, 400);
frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frm.setLocationRelativeTo(null);
frm.setVisible(true);
}
// Transfer column widths from autoresize mode
private void updateColumns(JTable table) {
for (int i = 0; i < table.getColumnCount(); i++) {
TableColumn col = table.getColumnModel().getColumn(i);
col.setPreferredWidth(col.getWidth());
}
}
}

Change background behind JTable TableHeaders

I have an application with a few tables and a white application background to blend in with used logos. I have set all the backgrounds to white but there is one space that I could not reach so far.
With the standard JTable I am using it is possible to move columns and this is totally fine. However when moving the columns you are still able to see the standard applications color behind the TableHeaders. As displaying in a JScrollPane I thought setting the background of the ScrollPane.getContentHeader() would help but I get an NPE.
Below is a small program that should display the problem:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
public class testsforSO extends JFrame {
private static final long serialVersionUID = -3890178393751567629L;
private JTable table;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
testsforSO frame = new testsforSO();
frame.setSize(300, 300);
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public testsforSO() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setLayout(new BorderLayout(0, 0));
JScrollPane scrollPane = new JScrollPane();
getContentPane().add(scrollPane, BorderLayout.CENTER);
String[] columns = new String[] { "ABC", "DEF", "XYZ" };
TableModel tm = new DefaultTableModel(columns, 3);
table = new JTable();
table.setModel(tm);
table.getTableHeader().setBackground(Color.WHITE); //Does its job
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
scrollPane.setViewportView(table);
}
}
When moving one of the three columns you will notice the standard background of your LAF (for me it is the Standard Windows LAF with its beige like color) instead of white eventhough the background of the TableHeader is set to white.
The color is set as well for the parts of the scrollPane width where no tableheaders are displayed and sets the color of the header to the correct color but I cannot figure out how to do so for the space behind the headers.
EDIT: After this seems to get misunderstood, I made a screen of my problem:
Unfortunately you cannot see the cursor, but I am holding the column at its header and dragging it to the right.
your problem are based on code line (because I think that JTable aren't designated to be non_resizable, maybe this is bug maybe its feature)
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
you can to override this painting artefact by, then override the desired Color in Renderer
table.getTableHeader().setBackground(scrollPane.getBackground());
I'd be use JTable.AUTO_RESIZE_OFF, in most case there isn't reason to be restricted to fixed size, my view is to use LayoutManager in all cases, without any restriction(s), e.g.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
//http://stackoverflow.com/questions/40969405/change-background-behind-jtable-tableheaders
public class testsforSO extends JFrame {
private static final long serialVersionUID = -3890178393751567629L;
private JScrollPane scrollPane = new JScrollPane();
private String[] columns = new String[]{"ABC", "DEF", "XYZ"};
private TableModel tm = new DefaultTableModel(columns, 3);
private JTable table = new JTable(tm);
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
testsforSO frame = new testsforSO();
frame.pack();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public testsforSO() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JScrollPane scrollPane = new JScrollPane();
String[] columns = new String[]{"ABC", "DEF", "XYZ"};
TableModel tm = new DefaultTableModel(columns, 3);
table.getTableHeader().setBackground(Color.WHITE); //Does its job
table.getTableHeader().setBackground(scrollPane.getBackground());
table.getTableHeader().setOpaque(true);
table.setFillsViewportHeight(true);
//table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setPreferredScrollableViewportSize(new Dimension(300, 100));
scrollPane.setViewportView(table);
add(scrollPane);
}
}
EDIT
Try your program you gave as an answer (including scrollPane.getViewport().setBackground(Color.BLACK);) and run it. Black shows the problem better.
to see
from code (again to use Renderer for painting the Color inside JTables view)
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
//http://stackoverflow.com/questions/40969405/change-background-behind-jtable-tableheaders
public class testsforSO extends JFrame {
private static final long serialVersionUID = -3890178393751567629L;
private JScrollPane scrollPane = new JScrollPane();
private String[] columns = new String[]{"ABC", "DEF", "XYZ"};
private TableModel tm = new DefaultTableModel(columns, 3);
private JTable table = new JTable(tm);
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
testsforSO frame = new testsforSO();
frame.pack();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public testsforSO() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JScrollPane scrollPane = new JScrollPane();
String[] columns = new String[]{"ABC", "DEF", "XYZ"};
TableModel tm = new DefaultTableModel(columns, 3);
//table.getTableHeader().setBackground(Color.WHITE); //Does its job
table.getTableHeader().setBackground(Color.BLACK);
table.setFillsViewportHeight(true);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setBackground(Color.BLACK);
table.setPreferredScrollableViewportSize(new Dimension(300, 100));
scrollPane.getViewport().setBackground(Color.BLACK);
scrollPane.setViewportView(table);
add(scrollPane);
}
}
none of them worked, where the last one brings up an NPE.
The table header is not actually added to the frame until the frame is visible. At this time the scrollpane will get the table header from the table and add the header to the column header of the scrollpane.
So, AFTER the frame is visible you can do:
JTableHeader header = table.getTableHeader();
header.getParent().setBackground(Color.YELLOW);
So the above is required in addition to setting the four levels as suggested by #mKorbel.
You can also check out: Setting JTableHeader holder background colour for a more detailed answer.

Unable to get hidden JTable column

I use a JTable with two buttons(Active & Inactive Buttons) . When I click on the Inactive button I hide the first column of the table. Also I try to show the first column when I click on the Active button. But the problem is , when I click on the Active button I couldn't display the first column with its preferred size .
This is the code for hide the first column,
expTable.getColumnModel().getColumn(0).setMinWidth(0);
expTable.getColumnModel().getColumn(0).setMaxWidth(0);
expTable.getColumnModel().getColumn(0).setWidth(0);
This is the code for get back fist column,
expTable.getColumnModel().getColumn(0).setMinWidth(0);
expTable.getColumnModel().getColumn(0).setMaxWidth(300);
expTable.getColumnModel().getColumn(0).setWidth(100);
First I click on the Inactive button and then I click on the Active button . But this is not working .
Have any idea to how to do above .
private void inactiveButtonActionPerformed(java.awt.event.ActionEvent evt){
expTable.getColumnModel().getColumn(0).setMinWidth(0);
expTable.getColumnModel().getColumn(0).setMaxWidth(0);
expTable.getColumnModel().getColumn(0).setWidth(0);
}
private void activeButtonActionPerformed(java.awt.event.ActionEvent evt)
{
expTable.getColumnModel().getColumn(0).setMinWidth(0);
expTable.getColumnModel().getColumn(0).setMaxWidth(300);
expTable.getColumnModel().getColumn(0).setWidth(100);
}
Don't attempt to "hide" a TableColumn by playing with the width. The TableColumn is still part of the table so when the user tabs from column to column, focus will go to the hidden column and disappear from the users view which is very confusing.
Instead you should remove the TableColumn from the TableColumnModel. Then you can add the TableColumn back to the TableColumnModel when needed.
Check out the Table Column Manager which manages this concept for you. If you don't use the full functionality of the class you can use the hideColumn(...) and showColumn(...) to do a simple toggle on the first column.
In the past when I've need to do something like, I've simply removed and re-added the TableColumn
This is a pretty crude example of the concept...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JToggleButton;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new BorderLayout());
DefaultTableModel model = new DefaultTableModel();
model.addColumn("Column 1");
model.addColumn("Column 2");
model.addColumn("Column 3");
model.addColumn("Column 4");
model.setRowCount(100);
JTable table = new JTable(model);
add(new JScrollPane(table));
JToggleButton toggle = new JToggleButton("Toggle");
toggle.addActionListener(new ActionListener() {
private TableColumn column;
#Override
public void actionPerformed(ActionEvent e) {
TableColumnModel columnModel = table.getColumnModel();
if (toggle.isSelected()) {
column = columnModel.getColumn(0);
table.getColumnModel().removeColumn(column);
} else if (column != null) {
columnModel.addColumn(column);
columnModel.moveColumn(columnModel.getColumnCount() - 1, 0);
}
}
});
add(toggle, BorderLayout.SOUTH);
}
}
}
I actually spent sometime putting together a custom TableModel which provide the ability to hide and show columns, which basically wrapped this functionality up in a nice reusable package

java.net BalloonTip is not showing up

I saw the BallonTip at java.net and I tried to integrate it into my application to be displayed when a user clicks a table cell. When a table cell is clicked, the BalloonTip is showing up as intended, but when you scroll it out of the current viewport, you can click another cell without the BalloonTip showing up. When you scroll the table, the BallonTip is shown again.
Here is an example:
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import net.java.balloontip.BalloonTip;
import net.java.balloontip.TablecellBalloonTip;
import net.java.balloontip.styles.EdgedBalloonStyle;
public class TableTest2 extends JFrame {
static final int LENGTH = 40;
TablecellBalloonTip tip;
JTable mainTable;
JPanel main;
JLayeredPane layeredPane;
JScrollPane mainScroll;
TableTest2() {
mainTable = new JTable(LENGTH, LENGTH);
CustomListSelectionListener clsl = new CustomListSelectionListener(mainTable);
mainTable.getColumnModel().getSelectionModel().addListSelectionListener(clsl);
mainTable.getSelectionModel().addListSelectionListener(clsl);
mainTable.setTableHeader(null);
mainTable.setColumnSelectionAllowed(true);
mainScroll = new JScrollPane(mainTable);
add(mainScroll);
tip = new TablecellBalloonTip(mainTable, new JLabel("Hello World!"), -1, -1, new EdgedBalloonStyle(Color.WHITE,
Color.BLUE), BalloonTip.Orientation.LEFT_ABOVE, BalloonTip.AttachLocation.ALIGNED, 5, 5, false);
setPreferredSize(new Dimension(500, 400));
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
}
public static void main(String[] args) {
new TableTest2();
}
protected class CustomListSelectionListener implements ListSelectionListener {
private int row, column, lead, anchor;
private JTable table;
public CustomListSelectionListener(JTable table) {
this.table = table;
}
#Override
public void valueChanged(ListSelectionEvent evt) {
if (evt.getSource() == table.getSelectionModel() && table.getRowSelectionAllowed()) {
// row selection changed
row = table.getSelectedRow();
column = table.getSelectedColumn();
tip.setCellPosition(row, column);
tip.refreshLocation();
} else if (evt.getSource() == table.getColumnModel().getSelectionModel()
&& table.getColumnSelectionAllowed()) {
// column selection changed
lead = table.getColumnModel().getSelectionModel().getLeadSelectionIndex();
anchor = table.getColumnModel().getSelectionModel().getAnchorSelectionIndex();
if (lead <= anchor) {
column = anchor;
} else {
column = lead;
}
row = table.getSelectedRow();
tip.setCellPosition(row, column);
tip.refreshLocation();
}
}
}
}
How can I force the BalloonTip to be shown after I click a cell in the table? I think there is a listener, which is listening for the scrolling event and manages the painting of the BallonTip, but I do not have a clue which one it is.
best regards
htz
According to this mailing list, there was a bug in the BallonTip version 1.2.1. Now, with version 1.2.3, this is fixed.

button size and position

Hi I want to put my button at the South position! How can I do that? Here is my code:
import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.io.*;
import java.util.*;
import javax.swing.JButton;
public class TableDemo extends JPanel {
private static Icon leftButtonIcon;
private boolean DEBUG = false;
// added static infront becuase got non static referencing error
static List<String[]> rosterList = new ArrayList<String[]>();
public TableDemo() {
super(new GridLayout(1,0));
JTable table = new JTable(new MyTableModel());
table.setPreferredScrollableViewportSize(new Dimension(500, 70));
table.setFillsViewportHeight(true);
JButton button=new JButton("Buy it");
button.setSize(30,60);
button.add(button);
//Create the scroll pane and add the table to it.
JScrollPane scrollPane = new JScrollPane(table);
//Add the scroll pane to this panel.
add(scrollPane);
//create a button
}
class MyTableModel extends AbstractTableModel {
private String[] columnNames = { "Κωδικός", "Ποσότητα", "Τιμή", "Περιγραφή", "Μέγεθος", "Ράτσα"};
public int getColumnCount() {
return columnNames.length;
}
public int getRowCount() {
return rosterList.size();
}
#Override
public String getColumnName(int col) {
return columnNames[col];
}
public Object getValueAt(int row, int col)
{
return rosterList.get(row)[col];
}
}
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("TableDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
TableDemo newContentPane = new TableDemo();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
//Display the window.
frame.pack();
frame.setVisible(true);
}
Something like this?
See the comments in the code.
import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.border.EmptyBorder;
import java.awt.Dimension;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.io.*;
import java.util.*;
import javax.swing.JButton;
public class TableDemo extends JPanel {
private static Icon leftButtonIcon;
private boolean DEBUG = false;
// added static infront becuase got non static referencing error
static List<String[]> rosterList = new ArrayList<String[]>();
public TableDemo() {
super(new BorderLayout(3,3));
JTable table = new JTable(new MyTableModel());
table.setPreferredScrollableViewportSize(new Dimension(500, 70));
table.setFillsViewportHeight(true);
JButton button=new JButton("Buy it");
// Rarely has the intended effect.
// also best not to presume we can guess the size
// a component needs to be.
//button.setSize(30,60);
// cannot add a button to itself!
//button.add(button);
JPanel buttonCenter = new JPanel( new FlowLayout(FlowLayout.CENTER) );
// allow the button to be centered in buttonCenter,
// rather than stretch across the width of the SOUTH
// of the TableDemo
buttonCenter.add(button);
add(buttonCenter, BorderLayout.SOUTH);
//Create the scroll pane and add the table to it.
JScrollPane scrollPane = new JScrollPane(table);
//Add the scroll pane to this panel.
add(scrollPane, BorderLayout.CENTER);
//create a button
// add a nice border
setBorder(new EmptyBorder(5,5,5,5));
}
class MyTableModel extends AbstractTableModel {
// apologies about the column names
private String[] columnNames = { "??d????", "??s?t?ta", "??µ?", "?e????af?", "???e???", "??tsa"};
public int getColumnCount() {
return columnNames.length;
}
public int getRowCount() {
return rosterList.size();
}
#Override
public String getColumnName(int col) {
return columnNames[col];
}
public Object getValueAt(int row, int col)
{
return rosterList.get(row)[col];
}
}
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("TableDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
TableDemo newContentPane = new TableDemo();
// JPanels are opaque by default!
//newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
// Should be done on the EDT.
// Left as an exercise for the reader.
TableDemo.createAndShowGUI();
}
}
You add the button to itself, and you should use BorderLayout, if you want to place the components in Center / North / South / etc. manners:
setLayout(new BorderLayout());
add(scrollPane, BorderLayout.CENTER);
add(button, BorderLayout.SOUTH);
"Hi i want to put my button at the South posotion! how can i?"
If you want to place something in a BorderLayout location, it would make sense to have the container use a ... BorderLayout, n'est-ce pas?
But seriously, most of your recent questions in this forum suggest you're coming here before reading the tutorials. You've already been given the links several times, so please do yourself a favor and learn Swing right -- study the layout tutorials and other tutorials and you will save yourself a lot of grief and guessing.
try this:
JFrame frame = new JFrame();
frame.add(yourbutton,BORDERLAYOUT.SOUTH)
and for give position and size to button,do this
yourbutton.setBounds(10,15,120,200) --> (x,y,height,width) , x , y set possition

Categories

Resources