This should be simple, but I can't figure out what is going wrong. I need my table to display with a fairly large font size but the table painter is not honoring the height of the cell renderer.
I've seen this post and it's working brilliantly for when my preferences window has been given a changed font size. But although the renderer knows what font size to use, the table on initial display is using the standard row height (16). Surely the table painter should automatically take into account the preferred height of the renderer? Or do I actually have to manually tell it what height to use?
I've tried a call to doLayout() as shown below, but it doesn't make any difference.
Here's an SSCCE to demonstrate the problem:
public class IncorrectRowHeight extends JPanel
{
private class MyCellRenderer extends JTextField implements TableCellRenderer
{
private MyCellRenderer()
{
setFont(new Font("SansSerif", Font.PLAIN, 30));
setBorder(BorderFactory.createEmptyBorder());
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int column)
{
setText(value.toString());
return this;
}
}
public IncorrectRowHeight()
{
super(new BorderLayout());
add(new JTextField(25), BorderLayout.PAGE_START);
String[][] data = {
{"a", "b", "c", "d", "e"},
{"f", "g", "h", "i", "j"},
{"k", "l", "m", "n", "o"},
{"p", "q", "r", "s", "t"}
};
String[] cols = {"h1", "h2", "h3", "h4", "h5"};
JTable t = new JTable(data, cols);
t.setGridColor(Color.GRAY);
t.setPreferredScrollableViewportSize(new Dimension(300, 65));
TableColumnModel model = t.getColumnModel();
for (int i = 0; i < model.getColumnCount(); i++)
{
TableColumn column = model.getColumn(i);
column.setCellRenderer(new MyCellRenderer());
}
JScrollPane scroller = new JScrollPane(t);
add(scroller, BorderLayout.CENTER);
//t.doLayout(); // doesn't help matters
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("IncorrectRowHeight");
JComponent newContentPane = new IncorrectRowHeight();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args)
{
javax.swing.SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}
It produces the following:
This ain't rocket science! What am I doing wrong?
Probably this method help you
public static void updateRowHeight(JTable table, int margin) {
final int rowCount = table.getRowCount();
final int colCount = table.getColumnCount();
for (int i = 0; i < rowCount; i++) {
int maxHeight = 0;
for (int j = 0; j < colCount; j++) {
final TableCellRenderer renderer = table.getCellRenderer(i, j);
maxHeight = Math.max(maxHeight, table.prepareRenderer(renderer, i, j).getPreferredSize().height);
}
table.setRowHeight(i, maxHeight + margin);
}
}
Use this method after the table is populated with the data. margin parameter is used for additional increment of row height. If not required - use 0.
Here is your example with the correct cell height.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
/**
* <code>IncorrectRowHeight</code>.
*/
public class IncorrectRowHeight extends JPanel {
private class MyCellRenderer extends JTextField implements TableCellRenderer {
private MyCellRenderer() {
setFont(new Font("SansSerif", Font.PLAIN, 30));
setBorder(BorderFactory.createEmptyBorder());
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
setText(value.toString());
return this;
}
}
public IncorrectRowHeight() {
super(new BorderLayout());
add(new JTextField(25), BorderLayout.PAGE_START);
String[][] data = {{"a", "b", "c", "d", "e"}, {"f", "g", "h", "i", "j"}, {"k", "l", "m", "n", "o"}, {"p", "q", "r", "s", "t"}};
String[] cols = {"h1", "h2", "h3", "h4", "h5"};
JTable t = new JTable(data, cols);
t.setGridColor(Color.GRAY);
t.setPreferredScrollableViewportSize(new Dimension(300, 65));
TableColumnModel model = t.getColumnModel();
for (int i = 0; i < model.getColumnCount(); i++) {
TableColumn column = model.getColumn(i);
column.setCellRenderer(new MyCellRenderer());
}
updateRowHeight(t, 0);
JScrollPane scroller = new JScrollPane(t);
add(scroller, BorderLayout.CENTER);
}
public static void updateRowHeight(JTable table, int margin) {
final int rowCount = table.getRowCount();
final int colCount = table.getColumnCount();
for (int i = 0; i < rowCount; i++) {
int maxHeight = 0;
for (int j = 0; j < colCount; j++) {
final TableCellRenderer renderer = table.getCellRenderer(i, j);
maxHeight = Math.max(maxHeight, table.prepareRenderer(renderer, i, j).getPreferredSize().height);
}
table.setRowHeight(i, maxHeight + margin);
}
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("IncorrectRowHeight");
JComponent newContentPane = new IncorrectRowHeight();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowGUI();
}
});
}
}
Use table.setRowHeight(table.getFontMetrics(font).getHeight());
package com.logicbig.example;
import javax.swing.*;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import java.awt.*;
public class IncorrectRowHeight extends JPanel {
private static final Font font = new Font("SansSerif", Font.PLAIN, 30);
private class MyCellRenderer extends JTextField implements TableCellRenderer {
private MyCellRenderer() {
setFont(font);
setBorder(BorderFactory.createEmptyBorder());
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
setText(value.toString());
return this;
}
}
public IncorrectRowHeight() {
super(new BorderLayout());
add(new JTextField(25), BorderLayout.PAGE_START);
String[][] data = {
{"a", "b", "c", "d", "e"},
{"f", "g", "h", "i", "j"},
{"k", "l", "m", "n", "o"},
{"p", "q", "r", "s", "t"}
};
String[] cols = {"h1", "h2", "h3", "h4", "h5"};
JTable t = new JTable(data, cols);
t.setRowHeight(t.getFontMetrics(font).getHeight());
t.setGridColor(Color.GRAY);
t.setPreferredScrollableViewportSize(new Dimension(300, 65));
TableColumnModel model = t.getColumnModel();
for (int i = 0; i < model.getColumnCount(); i++) {
TableColumn column = model.getColumn(i);
column.setCellRenderer(new MyCellRenderer());
}
JScrollPane scroller = new JScrollPane(t);
add(scroller, BorderLayout.CENTER);
//t.doLayout(); // doesn't help matters
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("IncorrectRowHeight");
JComponent newContentPane = new IncorrectRowHeight();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Related
I'm trying to set a button in enabled(false) when I create it, and when I select any row on the Jtable, that button goes enabled(true).
Logic is pretty simple here, but for some reason, it doesn't quite work, the button never gets into enabled(true).
JButton btnIniciarReparacin = new JButton("INICIAR REPARACI\u00D3N");
btnIniciarReparacin.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
tiempoStart = (int) (System.currentTimeMillis() / 1000L);
btnIniciarReparacin.setEnabled(false);
}
});
btnIniciarReparacin.setFont(new Font("SansSerif", Font.BOLD, 13));
btnIniciarReparacin.setBackground(new Color(231, 111, 81));
btnIniciarReparacin.setBounds(129, 625, 254, 50);
frame.getContentPane().add(btnIniciarReparacin);
int row = table.getSelectedRow();
//Comprobamos si hemos cogido algo de la tabla y si los botones están encendidos
if (table.isRowSelected(row)) {
btnIniciarReparacin.setEnabled(true);
} else {
btnIniciarReparacin.setEnabled(false);
}
Swing GUI's work by your adding listeners to events and then responding to state changes within the listener.
You appear to be checking the row selection state in code where you create your components, and that will never work since it only checks the state once, and before the user has had a chance to make a selection. Instead, you need to use a listener on your JTable, more specifically a ListSelectionListener that you add to the JTable's selection model that you get via table.getSelectionModel().addListSelectionListener(...)
Also note that this:
int row = table.getSelectedRow();
if (table.isRowSelected(row)) {
btnIniciarReparacin.setEnabled(true);
} else {
btnIniciarReparacin.setEnabled(false);
}
can be shortened to:
int row = table.getSelectedRow();
btnIniciarReparacin.setEnabled(table.isRowSelected(row));
e.g. something like:
table.getSelectionModel().addListSelectionListener(new ListSelectionListener(){
public void valueChanged(ListSelectionEvent event) {
int row = table.getSelectedRow();
btnIniciarReparacin.setEnabled(table.isRowSelected(row));
}
});
For example, if the button deletes a row:
import java.awt.BorderLayout;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;
#SuppressWarnings("serial")
public class Test01 extends JPanel {
private static final String[] COLUMNS = {"One", "Two", "Three", "Four"};
private DefaultTableModel tableModel = new DefaultTableModel(COLUMNS, 0);
private JTable table = new JTable(tableModel);
private JButton deleteRowButton = new JButton("Delete Row");
public Test01() {
int tableRows = 20;
for (int i = 0; i < tableRows; i++) {
Integer[] row = new Integer[COLUMNS.length];
for (int j = 0; j < row.length; j++) {
row[j] = (int) (100 * Math.random());
}
tableModel.addRow(row);
}
table.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
int row = table.getSelectedRow();
deleteRowButton.setEnabled(table.isRowSelected(row));
}
});
deleteRowButton.addActionListener(e -> {
int row = table.getSelectedRow();
tableModel.removeRow(row);
});
deleteRowButton.setEnabled(false);
JPanel bottomPanel = new JPanel();
bottomPanel.add(deleteRowButton);
setLayout(new BorderLayout());
add(new JScrollPane(table));
add(bottomPanel, BorderLayout.PAGE_END);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
private static void createAndShowGui() {
Test01 mainPanel = new Test01();
JFrame frame = new JFrame("Test01");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
}
I know there are a lot of questions on this subject but for some reason just cant find my way around this thing.
I need to change row color if two columns are not having the same values.
seen this link: http://tips4java.wordpress.com/2010/01/24/table-row-rendering/
but can't make it work....
tried this also:
public void colorRow(JTable table){
for(int column=0;column<table.getRowCount();column++){
for(int row=0;row<table.getRowCount();row++){
TableCellRenderer renderer = table.getCellRenderer(row, column);
Component comp = table.prepareRenderer(renderer, row, column);
Float sinh = (Float)table.getModel().getValueAt(row,6);
Float kol = (Float)table.getModel().getValueAt(row, 5);
if(!kol.equals(sinh)){
comp.setBackground(Color.YELLOW);
}
}
}
}
but it paints all the rows in the table if there is a row where columns 5 and 6 are not having the same value.
would appreciate any help
Update(SSCCE):
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.JScrollPane;
import javax.swing.JTable;
public class table extends JFrame {
private JPanel contentPane;
private JTable table;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
table frame = new table();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public table() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 495, 317);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(new GridLayout(1, 0, 0, 0));
DefaultTableModel model = new DefaultTableModel();
model.addColumn("ID");
model.addColumn("Value 1");
model.addColumn("Value 2");
int id1=1;
int id2=2;
int id3=3;
Float one1=3.0f;
Float two1=4.0f;
Float one2=2.0f;
Float two2=2.0f;
Float one3=1.0f;
Float two3=2.0f;
model.insertRow(0, new Object [] {id1, one1,two1});
model.insertRow(0, new Object [] {id2, one2,two2});
model.insertRow(0, new Object [] {id3, one3,two3});
JScrollPane scrollPane = new JScrollPane();
contentPane.add(scrollPane);
table = new JTable(model);
scrollPane.setViewportView(table);
colorRow(table);
}
public void colorRow(JTable table){
for(int column=0;column<table.getColumnCount();column++){
for(int row=0;row<table.getRowCount();row++){
TableCellRenderer renderer = table.getCellRenderer(row, column);
Component comp = table.prepareRenderer(renderer, row, column);
comp.setBackground(getBackground());
Float sinh = (Float)table.getModel().getValueAt(row,2);
Float kol = (Float)table.getModel().getValueAt(row, 1);
if(!kol.equals(sinh)){
comp.setBackground(Color.YELLOW);
}
}
}
}
}
I just tried the solution from this post with your SSCCE and it works. So delete the colorRow() method, then in your constructor replace the table initialization table = new JTable(model); with this:
table = new JTable(model) {
#Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
Component comp = super.prepareRenderer(renderer, row, column);
int modelRow = convertRowIndexToModel(row);
Float sinh = (Float) getModel().getValueAt(modelRow, 2);
Float kol = (Float) getModel().getValueAt(modelRow, 1);
comp.setBackground(kol.equals(sinh) ? getBackground() : Color.YELLOW);
return comp;
}
};
You fixed the problem I pointed out in the original code sample: for(int column=0; column < table.getRowCount(); column++){ by using the column count, but that didn't resolve the reason for your post.
This question already has answers here:
How can I change the width of a JComboBox dropdown list?
(7 answers)
Closed 8 years ago.
How can I set a fixed width of a JComboboxs popup-menu that is using GridBagLayout and fill=HORIZONTAL?
One of the things I tried is to just override the getSize() method but dose not work.
public class ComboBoxSize extends JFrame {
public static void main(String args[]) {
// THE COMBOBOX
String labels[] = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J" };
JComboBox<String> comboBox = new JComboBox<String>(labels) {
public Dimension getSize() {
Dimension d = getPreferredSize();
d.width = 50;
return d;
}
};
comboBox.setMaximumRowCount(comboBox.getModel().getSize());
// ADD COMBOBOX TO PANEL
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.weightx = 1;
c.fill = GridBagConstraints.HORIZONTAL;
panel.add(comboBox, c);
// ADD PANEL TO FRAME
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel);
frame.setSize(300, 200);
frame.setVisible(true);
}
}
Here is the solution, this worked for me, add this PopupMenuListener to your JComboBox:
import java.awt.Dimension;
import javax.swing.BorderFactory;
import javax.swing.JComboBox;
import javax.swing.JList;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import javax.swing.plaf.basic.ComboPopup;
public class CustomComboBoxPopupMenuListener implements PopupMenuListener {
// ==============================================================================
// Members
// ==============================================================================
private int bgTop = 0;
private int bgLeft = 0;
private int bgRight = 0;
private int bgBottom = 0;
// ==============================================================================
// Constructors
// ==============================================================================
public CustomComboBoxPopupMenuListener() {
super();
}
// ==============================================================================
// Methods
// ==============================================================================
public void popupMenuCanceled(PopupMenuEvent e) {
}
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
}
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
final JComboBox box = (JComboBox) e.getSource();
final Object comp = box.getUI().getAccessibleChild(box, 0);
if (!(comp instanceof JPopupMenu)) {
return;
}
final JPopupMenu popupMenu = (JPopupMenu) comp;
popupMenu.setBorder(null);
if (popupMenu.getComponent(0) instanceof JScrollPane) {
final JScrollPane scrollPane = (JScrollPane) popupMenu
.getComponent(0);
scrollPane.setBorder(BorderFactory.createEmptyBorder(bgTop, bgLeft,
bgBottom, bgRight));
scrollPane.setOpaque(false);
scrollPane.getViewport().setOpaque(false);
if (popupMenu instanceof ComboPopup) {
final ComboPopup popup = (ComboPopup) popupMenu;
final JList list = popup.getList();
list.setBorder(null);
final Dimension size = list.getPreferredSize();
size.width = Math.max(box.getPreferredSize().width + bgLeft
+ bgRight, box.getWidth());
size.height = Math.min(scrollPane.getPreferredSize().height
+ bgTop + bgBottom, size.height + bgTop + bgBottom);
scrollPane.setPreferredSize(size);
scrollPane.setMaximumSize(size);
}
}
}
}
Example in your code:
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ComboBoxSize extends JFrame {
public static void main(String args[]) {
// THE COMBOBOX
String labels[] = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J" };
JComboBox<String> comboBox = new JComboBox<String>(labels);
comboBox.setMaximumRowCount(comboBox.getModel().getSize());
comboBox.addPopupMenuListener(new CustomComboBoxPopupMenuListener());
// ADD COMBOBOX TO PANEL
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.weightx = 1;
c.fill = GridBagConstraints.HORIZONTAL;
panel.add(comboBox, c);
// ADD PANEL TO FRAME
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel);
frame.setSize(300, 200);
frame.setVisible(true);
}
}
Source: click here
I am making a GUI in which i tried to indent the column name.I am also pasting my source code. I am using the GridBagConstraints. This my code where i create a GridBagConstraints but nothing seems to happen
private final static Dimension VOLUME_FIELD_DIMENSION = new Dimension(200, 25);
private final static Dimension NAME_FIELD_DIMENSION = new Dimension(200, 25);
private final static Dimension IMAGE_FIELD_DIMENSION = new Dimension(200, 25);
private final static Dimension DATE_FIELD_DIMENSION = new Dimension(150, 25);
private final static Dimension STATUS_FIELD_DIMENSION = new Dimension(100, 25);
private final static Dimension IMAGE_PANEL_DIMENSION = new Dimension(1000,250);
private static void ImagePanel(ArrayList<ResourceListObject> arr, JPanel imagelist)
{
for(int i=0 ; i < arr.size();i++)
{
try {
// column 1: name
JTextField t1 = createTextField(arr.get(i).getName(), NAME_FIELD_DIMENSION);
// column 2: Created At
JTextField t2 = createTextField(arr.get(i).getCreatedDate(), DATE_FIELD_DIMENSION);
// column 3: Status
JTextField t3 = createTextField(arr.get(i).getStatus(), STATUS_FIELD_DIMENSION);
// column 4: Image Id
JTextField t4 = createTextField(arr.get(i).getID(), IMAGE_FIELD_DIMENSION);
//column 5:Volume Id
JTextField t5 = createTextField(arr.get(i).getVolume_id(), VOLUME_FIELD_DIMENSION);
// construct the row (panel), and then add it to the list panel
JPanel rowPanel = new JPanel();
rowPanel.setLayout(new BoxLayout(rowPanel, BoxLayout.X_AXIS));
rowPanel.add(t1);
rowPanel.add(t2);
rowPanel.add(t3);
rowPanel.add(t4);
rowPanel.add(t5);
imagelist.add(rowPanel);
} catch (Exception e) {
}
}
}
private static JTextField createTextField(String text, Dimension d) {
JTextField tf = new JTextField(text);
tf.setPreferredSize(d);
tf.setBackground(Color.WHITE);
tf.setEditable(false);
return tf;
}
private static JPanel getColumnHeadings() {
GridBagConstraints regularFieldConstraints = new GridBagConstraints();
regularFieldConstraints.fill = GridBagConstraints.BOTH;
String nameColumn = "Image Name";
String secondColumn = "Created At";
String thirdColumn = "Status";
String fourthColumn = "Image Id";
String fifthColumn = "Volume Id";
JLabel name = new JLabel(nameColumn);
JLabel created_at = new JLabel(secondColumn);
JLabel status = new JLabel(thirdColumn);
JLabel id = new JLabel(fourthColumn);
JLabel volume_id = new JLabel(fifthColumn);
name.setPreferredSize(NAME_FIELD_DIMENSION);
created_at.setPreferredSize(DATE_FIELD_DIMENSION);
status.setPreferredSize(STATUS_FIELD_DIMENSION);
id.setPreferredSize(IMAGE_FIELD_DIMENSION);
volume_id.setPreferredSize(VOLUME_FIELD_DIMENSION);
JPanel headingsPanel = new JPanel(new GridBagLayout());
headingsPanel.add(name, regularFieldConstraints);
headingsPanel.add(created_at, regularFieldConstraints);
headingsPanel.add(status, regularFieldConstraints);
headingsPanel.add(id, regularFieldConstraints);
headingsPanel.add(volume_id, regularFieldConstraints);
return headingsPanel;
}
The class sun.swing.table.DefaultTableCellHeaderRenderer is not part of the published API. If you are reluctant to depend on it, consider these alternative options:
Use the existing renderer, as shown here and below.
Use Darryl Burke's Default Table Header Cell Renderer.
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
public class Demo {
/** #see https://stackoverflow.com/a/6644956/230513 */
private static class HeaderRenderer implements TableCellRenderer {
TableCellRenderer renderer;
public HeaderRenderer(JTable table) {
renderer = table.getTableHeader().getDefaultRenderer();
}
#Override
public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int col) {
// assumes JLabel
JLabel label = (JLabel) renderer.getTableCellRendererComponent(
table, value, isSelected, hasFocus, row, col);
label.setHorizontalAlignment(JLabel.LEADING);
return label;
}
}
private void initGUI() {
Object[] columnNames = new Object[]{
"Image Name", "Created At", "Status", "Image Id", "Volume Id"};
DefaultTableModel dtm = new DefaultTableModel(columnNames, 0);
dtm.addRow(new Object[]{"Some picture's name", "2013-10-05",
"Status unknown", "0123456789", "9876543210"});
JTable table = new JTable(dtm);
table.getTableHeader().setDefaultRenderer(new HeaderRenderer(table));
JScrollPane scrollPane = new JScrollPane(table);
JPanel content = new JPanel(new BorderLayout());
content.setPreferredSize(new Dimension(600, 250));
content.add(scrollPane);
JFrame frame = new JFrame("Demo");
frame.setContentPane(content);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Demo().initGUI();
}
});
}
}
I want that all the column name are indents like Image Id
If I'm understanding right, you want column header labels left-aligned just as Image ID. If so, you can use a TableCellRenderer to achive that using JTable.getHeader() method. (if not so, sorry for misunderstand your question)
For instance you can use a sun.swing.table.DefaultTableCellHeaderRenderer which extends from DefaultTableCellRenderer.
Sample Code
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import sun.swing.table.DefaultTableCellHeaderRenderer;
public class Demo{
private void initGUI(){
Object[] columnNames = new Object[]{"Image Name", "Created At", "Status", "Image Id", "Volume Id"};
DefaultTableModel dtm = new DefaultTableModel(columnNames, 0);
dtm.addRow(new Object[]{"Some picture's name", "2013-10-05", "Status unknown", "0123456789", "9876543210"});
/*
* Create your own TableCellRender
*/
TableCellRenderer headerRenderer = new DefaultTableCellHeaderRenderer(){
#Override
public Component getTableCellRendererComponent(JTable jtable, Object o, boolean bln, boolean bln1, int i, int i1) {
super.getTableCellRendererComponent(jtable, o, bln, bln1, i, i1);
setHorizontalAlignment(SwingConstants.LEADING);
return this;
}
};
JTable table = new JTable(dtm);
table.getTableHeader().setDefaultRenderer(headerRenderer);
JScrollPane scrollPane = new JScrollPane(table);
JPanel content = new JPanel(new BorderLayout());
content.setPreferredSize(new Dimension(600,250));
content.add(scrollPane);
JFrame frame = new JFrame("Demo");
frame.setContentPane(content);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
try{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
SwingUtilities.updateComponentTreeUI(frame);
}
catch(ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex){
ex.printStackTrace();
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Demo().initGUI();
}
});
}
}
Long story short, I'm making a custom Swing component that's basically a JTable with a panel on its side. The table should of course be scrollable and have a table header, but since I only want the header to be above the actual JTable and not above the side panel, I had to pull some tricks to make it work. But that part works fine.
However, in the process I've somehow managed to break the mouse-drag-column-resizing functionality of the JTableHeader. I am completely clueless as to why and what I can do about it.
Below is a minimal working sample to illustrate my problem.
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JViewport;
import javax.swing.Scrollable;
import javax.swing.table.JTableHeader;
final class FooTable extends JPanel implements Scrollable {
public FooTable() {
initComponents();
}
// Generated by NetBeans IDE
#SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
java.awt.GridBagConstraints gridBagConstraints;
sidePanel = new javax.swing.JPanel();
table = new javax.swing.JTable();
setLayout(new java.awt.GridBagLayout());
sidePanel.setMinimumSize(new java.awt.Dimension(70, 0));
sidePanel.setPreferredSize(new java.awt.Dimension(70, 0));
sidePanel.setLayout(null);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.weighty = 1.0;
add(sidePanel, gridBagConstraints);
table.setFont(table.getFont().deriveFont(table.getFont().getSize()+1f));
table.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
{"1", "A", "I", "-"},
{"2", "B", "II", "--"},
{"3", "C", "III", "---"},
{"4", "D", "IV", "----"},
{"5", "E", "V", "-----"},
{"6", "F", "VI", "------"},
{"7", "G", "VII", "-------"},
{"8", "H", "VIII", "--------"},
{"9", "I", "IX", "---------"},
{"10", "J", "X", "----------"}
},
new String [] {
"Column 1", "Column 2", "Column 3", "Column 4"
}
));
table.setRowHeight(24);
table.setSelectionMode(javax.swing.ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 0;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.weightx = 1.0;
add(table, gridBagConstraints);
}// </editor-fold>
public JScrollPane createScrollView() {
JScrollPane jsp = new JScrollPane(this);
JViewport jvp = new JViewport();
final JTableHeader th = new JTableHeader();
th.setTable(table);
th.setColumnModel(table.getColumnModel());
th.setResizingAllowed(true);
jvp.setView(new JPanel() {
{
setLayout(null);
add(th);
th.setLocation(70, 0);
FooTable.this.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
th.setSize(FooTable.this.getWidth(), th.getPreferredSize().height);
}
});
setPreferredSize(new Dimension(th.getPreferredSize().width, th.getPreferredSize().height));
}
});
jsp.setColumnHeader(jvp);
return jsp;
}
// Variables declaration - do not modify
private javax.swing.JPanel sidePanel;
private javax.swing.JTable table;
// End of variables declaration
//
// Scrollable implementation
//
public Dimension getPreferredScrollableViewportSize() {
Dimension d = new Dimension();
d.width = sidePanel.getPreferredSize().width + table.getPreferredSize().width;
d.height = sidePanel.getPreferredSize().height + table.getPreferredSize().height;
return d;
}
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
return table.getScrollableUnitIncrement(visibleRect, orientation, direction);
}
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
return table.getScrollableBlockIncrement(visibleRect, orientation, direction);
}
public boolean getScrollableTracksViewportWidth() {
return table.getScrollableTracksViewportWidth();
}
public boolean getScrollableTracksViewportHeight() {
return table.getScrollableTracksViewportHeight();
}
//
// Test program
//
public static void main(String[] args) {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
FooTable fooTable = new FooTable();
f.add(fooTable.createScrollView());
f.pack();
f.setVisible(true);
}
}
I think what you are missing is also telling the JTable about the JTableHeader. In the method createScrollView try adding the following just before returning:
table.setTableHeader(th);