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.
Related
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());
}
}
}
I want to put the name of the item that I selected in a JTable in a JLabel that every time that i click a new item in the table the text in the JLabel also change
can someone tell me what should I learn in java to produce that?
You should know very basic Swing programming, and a little deeper understanding of a TableModel, SelectionModel and ListSelectionListener (which is the key to your goal).
A working example:
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class TableSelectionToLabel {
private static JTable t = new JTable(new String[][]{{"1,1", "1,2"}, {"2,1", "2,2"}},
new String[]{"1", "2"});
private static JLabel l = new JLabel("Your selction will appear here");
private static JFrame f = new JFrame("Table selection listener Ex.");
private static ListSelectionListener myListener = new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
int col = t.getColumnModel().getSelectionModel().getLeadSelectionIndex();
int row = t.getSelectionModel().getLeadSelectionIndex();
try {
l.setText(t.getModel().getValueAt(row, col).toString());
} catch (IndexOutOfBoundsException ignore) {
}
}
};
public static void main(String[] args) {
t.getSelectionModel().addListSelectionListener(myListener);
t.getColumnModel().getSelectionModel().addListSelectionListener(myListener);
f.getContentPane().add(t, BorderLayout.NORTH);
f.getContentPane().add(l, BorderLayout.CENTER);
f.pack();
f.setVisible(true);
}
}
EDIT:
I modified the code to listen to both selection events from the model AND the column model to get a more accurate outcome.
First create the JLabel:
JLabel label = new JLabel();
Then add a listener to the table for selections:
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent event) {
label.setText(table.getValueAt(table.getSelectedRow(), table.getSelectedColumn()));
}
});
I have a show button to show a JTable on click but the table is not visible.
Note: when I remove the JScrollPane the code works properly but the header of the table is not shown, so any help please to make this code work properly without removing the JScrollPane
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
public class Training extends JFrame {
public Training() {
getContentPane().setLayout(new FlowLayout());
JTable table = new JTable();
table.setModel(new DefaultTableModel(new Object[][] { { "joe", "joe" },
{ "mickel", "mickel" }, }, new String[] { "LastName",
"FirstName" }));
final JScrollPane pane = new JScrollPane(table);
pane.setVisible(false);
getContentPane().add(pane);
JButton btn = new JButton("show");
add(btn);
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
pane.setVisible(true);
}
});
}
public static void main(String[] args) {
Training app = new Training();
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.setSize(600, 600);
app.setVisible(true);
}
}
After pane.setVisible(true); add the following:
getContentPane().validate();
getContentPane().repaint();
A few things to note:
Never extends JFrame class unnecessarily, or else you might need to extend another class which is very necessary but in java a single class may not extend more than one other class (no multiple inheritance).
Always create Swing components on Event Dispatch Thread via SwingUtilities.invokeLater(Runnable r) block.
Do not use setSize(..) call JFrame#pack() before setting JFrame visible
No need for getContentPane.add(..) or getContentPane().setLayout(..), simply call add(..) or setLayout(..) on JFrame instance as these calls are fowared to the contentPane.
The problem you have is you do not refresh you frame/container after setting pane visible. I disagree with #Dan. Do not use validate() (getContentPane() is not necesarry either) rather:
revalidate();
repaint();
as revalidate() covers validate(). Also validate is used when new JComponents are added to a visible component, whereas revalidate() is used when JComponent is removed/added from a visible component.
Here is a fixed version of the code with the above implemented:
After button pressed:
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
public class Training {
private JFrame frame;
public Training() {
frame = new JFrame();
frame.setLayout(new FlowLayout());
JTable table = new JTable();
table.setModel(new DefaultTableModel(new Object[][]{{"joe", "joe"},
{"mickel", "mickel"},}, new String[]{"LastName",
"FirstName"}));
final JScrollPane pane = new JScrollPane(table);
pane.setVisible(false);
frame.add(pane);
JButton btn = new JButton("show");
frame.add(btn);
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
pane.setVisible(true);
frame.pack();//this is so the frame will resize after adding pane
frame.revalidate();
frame.repaint();
}
});
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Training();
}
});
}
}
UPDATE:
Also for a more reusable Layout, why not add all components to a JPanel, and add that JPanel to the JFrame, thus if you ever need to add more stuff its simple.
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();
}
});
}
}
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