How to center a value in JTable cell? I'm using Netbeans.
You need to customize the renderer. To center the first column you can do:
DefaultTableCellRenderer centerRenderer = new DefaultTableCellRenderer();
centerRenderer.setHorizontalAlignment( JLabel.CENTER );
table.getColumnModel().getColumn(0).setCellRenderer( centerRenderer );
To center all columns with String data you can do:
DefaultTableCellRenderer centerRenderer = new DefaultTableCellRenderer();
centerRenderer.setHorizontalAlignment( JLabel.CENTER );
table.setDefaultRenderer(String.class, centerRenderer);
Another good way to center all columns is with a loop:
for(int x=0;x<numberofcols;x++){
table1.getColumnModel().getColumn(x).setCellRenderer( centerRenderer );
}
Here you go:
import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableModel;
public class JTableUtilities
{
public static void setCellsAlignment(JTable table, int alignment)
{
DefaultTableCellRenderer rightRenderer = new DefaultTableCellRenderer();
rightRenderer.setHorizontalAlignment(alignment);
TableModel tableModel = table.getModel();
for (int columnIndex = 0; columnIndex < tableModel.getColumnCount(); columnIndex++)
{
table.getColumnModel().getColumn(columnIndex).setCellRenderer(rightRenderer);
}
}
}
Usage:
JTableUtilities.setCellsAlignment(table, SwingConstants.CENTER);
I had a similar problem. I wanted to align a single cell depending on the value of another cell. If cell X was NULL, then cell Y should be RIGHT aligned. Else, cell Y should be LEFT aligned.
I found this solution really helpful. It consists on creating a custom Render, extending DefaultTableCellRender.
Here's the code:
public class MyRender extends DefaultTableCellRenderer{
#Override
public Component getTableCellRendererComponent(JTable table,Object value,boolean isSelected,boolean hasFocus,int row,int column){
super.getTableCellRendererComponent (table, value, isSelected, hasFocus, row, column);
MyTableModel mtm = (MyTableModel)table.getModel();
switch(column){
case Y :
if(mla.getValueAt(row,X)!=null)
setHorizontalAlignment(SwingConstants.RIGHT);
else
setHorizontalAlignment(SwingConstants.LEFT);
break;
}
return this;
}
}
After that, just create a new instance of MyRender and set it to column Y, in this case. I do this when I load the information on the table.
MyRender render = new MyRender();
table.getColumnModel().getColumn(Y).setCellRender(render);
Hope it's useful!
Instead of JLabel.CENTER, you can use SwingConstants.CENTER.
((DefaultTableCellRenderer) jTable1.getTableHeader().getDefaultRenderer())
.setHorizontalAlignment(JLabel.CENTER); // header to center
This code header center jtable
DefaultTableCellRenderer rendar = new DefaultTableCellRenderer();
rendar.setHorizontalAlignment(jLabel1.CENTER);
jTable1.getColumnModel().getColumn(0).setCellRenderer(rendar);
this code to column center
Related
I already add a picture with JLabel in my JTable with TableCellRenderer. But how to add a border to the JLabel when mouse moves over the cell, on specific column and row?
This is the 1st renderer class:
public class RenderTabel implements TableCellRenderer{
#Override
public Component getTableCellRendererComponent(JTable table, Object
value,boolean isSelected, boolean hasFocus,int row, int column){
JLabel gambar=new JLabel();
String url="D:\\Kuliah Semester 4\\Pemrograman Berorientasi Objek\\DINUS BOOKSTORE\\image";
ImageIcon img=scalegmbr(url+"\\"+table.getModel().getValueAt(row, 0)+".png");
gambar.setIcon(img);
gambar.setText("");
gambar.setHorizontalAlignment(SwingConstants.CENTER);
table.setRowHeight(row, 50);
table.getColumnModel().getColumn(column).setPreferredWidth(80);
return gambar;
}
public ImageIcon scalegmbr(String file){
Image image=new ImageIcon(file).getImage();
return new ImageIcon(image.getScaledInstance(80,50,SCALE_SMOOTH));
}
}
This is 2nd renderer class:
public class RenderTabel1 implements TableCellRenderer{
#Override
public Component getTableCellRendererComponent(JTable table, Object
value,boolean isSelected, boolean hasFocus,int row, int column){
JLabel gambar=new JLabel();
String url="D:\\Kuliah Semester 4\\Pemrograman Berorientasi Objek\\DINUS BOOKSTORE\\image";
ImageIcon img=scalegmbr(url+"\\"+table.getModel().getValueAt(row, 0)+".png");
gambar.setIcon(img);
gambar.setText("");
gambar.setHorizontalAlignment(SwingConstants.CENTER);
gambar.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(200, 100, 52), 2));
table.setRowHeight(row, 50);
table.getColumnModel().getColumn(column).setPreferredWidth(80);
return gambar;
}
public ImageIcon scalegmbr(String file){
Image image=new ImageIcon(file).getImage();
return new ImageIcon(image.getScaledInstance(80,50,SCALE_SMOOTH));
}
}
and this is how I set the mouse enter and mouse clicked in my JTable:
private void tblbukuMouseEntered(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:
tblbuku.getColumnModel().getColumn(6).setCellRenderer( new RenderTabel1());
}
private void tblbukuMouseExited(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:
tblbuku.getColumnModel().getColumn(6).setCellRenderer( new RenderTabel());
}
But this adds a border to all cells in column 6 when mouse moves ofer a cell of that column. How to change it only into specific row and column when mouse entered that row and column?
So, for a particular column of your table, you want to paint a border on the cell that is hovered by the mouse (only the hovered cell, only in this column).
(edit: after clarification it appears that this question has been asked before -- I'm leaving my answer below as it might still help)
don't change the cell renderer dynamically, have only 1 renderer for that column, and handle that situation within the single renderer.
don't add listeners on the Component that is returned by the renderer: such listeners won't be triggered, as the component is only used for its paint()-ing logic.
instead, add a mouse motion listener on the table itself, and compute the coordinates of hovered cells with JTable's methods rowAtPoint and columnAtPoint, when mouse moves over table, or exits the area.
(irrelevant to problem at hand, but deserves a mention) Avoid creating a new JLabel for each call of your renderer, this is wasteful. Swing is single-thread, it's safe to reuse the same object (provided you don't forget to reset all its properties that might have changed between 2 calls)
Small demo that shows the effect:
import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class SimpleTableDemo extends JPanel {
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(SimpleTableDemo::createAndShowGUI);
}
private int
hoveredRow = -1,
hoveredColumn = -1;
SimpleTableDemo() {
super(new GridLayout(1,0));
String[] columnNames = {"First Name", "Last Name", "Sport", "# of Years", "Vegetarian"};
Object[][] data = {
{"Kathy", "Smith", "Snowboarding", 5, Boolean.FALSE},
{"John", "Doe", "Rowing", 3, Boolean.TRUE},
{"Sue", "Black", "Knitting", 2, Boolean.FALSE},
{"Jane", "White", "Speed reading", 20, Boolean.TRUE},
{"Joe", "Brown", "Pool", 10, Boolean.FALSE}
};
final JTable table = new JTable(data, columnNames);
table.setPreferredScrollableViewportSize(new Dimension(500, 70));
table.setFillsViewportHeight(true);
table.getColumn("Sport").setCellRenderer(new MyCellRenderer());
table.addMouseMotionListener(new MouseAdapter() {
public void mouseMoved(MouseEvent e) {
Point p = e.getPoint();
hoveredRow = table.rowAtPoint(p);
hoveredColumn = table.columnAtPoint(p);
table.repaint();
}
public void mouseExited(MouseEvent e) {
hoveredRow = hoveredColumn = -1;
table.repaint();
}
});
JScrollPane scrollPane = new JScrollPane(table);
add(scrollPane);
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("SimpleTableDemo");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
SimpleTableDemo newContentPane = new SimpleTableDemo();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
}
private class MyCellRenderer extends DefaultTableCellRenderer {
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (hoveredColumn == column && hoveredRow == row) {
label.setBorder(BorderFactory.createLineBorder(Color.GREEN, 2));
}
else {
label.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
}
return label;
}
}
}
Note 1: I'm using the default cell renderer, unlike you, but the same idea applies. The demo above is a generic example, that will be more useful as example to keep here than a specific solution for your case (for example, in my interpretation of the problem, I understand the details about icon are irrelevant).
Note 2: In the demo I repaint the whole visible area each time, but if you want to optimize it should be possible to repaint only 2 cells, that's an entire new question, see here for help about that.
I read a lot of articles and finally got my JTable rendering as per my requirements but the problem is when the table is scrolled by user, some of the other hidden parts of jtable are also colored as shown in image below
And when the user scrolls the table, other parts are also got colored like this
Why this happens? I read many articles and and all of them show exactly the same thing but this...
Here is my code
JTable table = new JTable()
{
public boolean isCellEditable(int rowIndex, int colIndex)
{
return false;
}
};
(DefaultTableCellRenderer)table.getTableHeader().getDefaultRenderer())
.setHorizontalAlignment(JLabel.CENTER);
table.setModel(new DefaultTableModel(new Object [][] {}, Columns));
table.setRowHeight(25);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.getColumnModel().removeColumn(table.getColumnModel().getColumn(0));
table.setDefaultRenderer(Object.class, new DefaultTableCellRenderer()
{
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if(!table.getModel().getValueAt(row, 10).toString().equals("true"))
{
setBackground(new Color(246,137,137));
}
return this;
}
});
JScrollPane areaScrollPane = new JScrollPane(table);
areaScrollPane.setPreferredSize(new Dimension(width, height));
MyPanel.add(areaScrollPane);
All the articles show this way to render custom row on condition base. What's wrong in my code? Thanks for any support.
if(!table.getModel().getValueAt(row, 10).toString().equals("true"))
{
setBackground(new Color(246,137,137));
}
The same renderer is used for all cells so once you set the background it will apply for all cells. So, I think you need something like:
if(!table.getModel().getValueAt(row, 10).toString().equals("true"))
{
setBackground(new Color(246,137,137));
}
else
setBackground( table.getBackground() );
You should also add code to make sure the cell is not selected so that the default selection color can be painted.
Instead of using a custom renderer you can also override the prepareRenderer(...) method of JTable. Table Row Rendering show how you can render a row based on a value in that row.
Is there a way to align all the column in jtable at the same time?
using this:
DefaultTableCellRenderer rightRenderer = new DefaultTableCellRenderer();
rightRenderer.setHorizontalAlignment( JLabel.RIGHT );
JTAB_TABLE.getColumnModel().getColumn(0).setCellRenderer( rightRenderer );
will let me align only one column but i need to align all.
Normally, a table contains different kinds of data, (Date, Number, Boolean, String) and it doesn't make sense to force all types of data to be right aligned.
If however you have a table with all the same type of data and you want to force the renderering of all columns to be the same, then you should probably use the same renderer. Assuming you are using the default renderer you can use:
DefaultTableCellRenderer renderer = (DefaultTableCellRenderer)table.getDefaultRenderer(Object.class);
renderer.setHorizontalAlignment( JLabel.RIGHT );
You can do so by overriding prepareRenderer(...) in JTable. This assumes that any custom renderers are JLabels (they're JLabels by default). You'd have to guard against it otherwise.
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
public class TableDemo implements Runnable
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new TableDemo());
}
public void run()
{
JTable table = new JTable(5, 5)
{
#Override
public Component prepareRenderer(TableCellRenderer renderer,
int row, int col)
{
Component comp = super.prepareRenderer(renderer, row, col);
((JLabel) comp).setHorizontalAlignment(JLabel.RIGHT);
return comp;
}
};
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane(table);
JFrame frame = new JFrame();
frame.getContentPane().add(scrollPane);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
I'm making a table where I want to make the first column with a higher Font Size.
For example in column 0 I want Font size of 30 and on columns 1-3 y want Font size of 13.
Here's my code
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.*;
public class kanji_list extends JFrame {
kanji_list(){
JTable table = new JTable();
JScrollPane scroll = new JScrollPane();
Image icon = Toolkit.getDefaultToolkit().getImage("JLPT.jpg");
ImageIcon ima = new ImageIcon("JLPT.jpg");
DefaultTableModel model = new DefaultTableModel(get_data(), get_header());
table = new JTable(model){
public boolean isCellEditable(int rowIndex, int vColIndex){
return false;
}
};
JTableHeader th = table.getTableHeader();
TableColumnModel tcm = th.getColumnModel();
TableColumn column = null;
table.setFont(new Font("Microsoft JhengHei", Font.BOLD, 13));
for (int i = 0; i < 4; i++) {
column = table.getColumnModel().getColumn(i);
DefaultTableCellRenderer tcr = new DefaultTableCellRenderer();
tcr.setHorizontalAlignment(SwingConstants.CENTER);
column.setCellRenderer(tcr);
if (i==0) {
column.setPreferredWidth(50);
}
else{
if(i==1){
column.setPreferredWidth(175);
}
else{
if(i==2){
column.setPreferredWidth(200);
}
else{
column.setPreferredWidth(875);
}
}
}
}
table.setRowHeight(table.getRowHeight()+30);
table.setModel(model);
scroll.add(table);
this.add(scroll);
this.setTitle("Katakana");
this.setSize(1350, 700);
this.setIconImage(icon);
this.setVisible(true);
this.setLocationRelativeTo(null);
scroll.setViewportView(table);
}
Object [][]get_data(){
Object data[][] = new Object[][]{
{"\u4e00", "Uno, 1", "ICHI, ITSU", "hito-, hitotsu"},
{"\u4e8c", "Dos, 2", "NI, JI", "futa, futatsu, futatabi"},
{"\u4e09", "Tres, 3", "SAN, JOU", "mi, mitsu, mittsu"},
{"\u99c5", "EstaciĆ³n", "EKI", ""}
};
return data;
}
String []get_header(){
String header [] = new String[]{"KANJI", "SIGNIFICADO", "LECTURA ON", "LECTURA KUN"};
return header;
}
}
This is a Japanese learning system, and Kanjis on unicode on 1st column aren't visible at all with my 13 size font, but if I make all the table on a higher size, all the other columns get bigger and it doesn't looks fine.
In core JTable you basically need a custom renderer which sets the Font to something different from the table's font, f.i. in a subclass of DefaultTableCellRenderer. Note that setting the font on DefaultTableCellRenderer once after instantiation won't work because it's reset on each call to getTableCellRendererComponent.
JTable table = new JTable(new AncientSwingTeam());
// the default renderer uses the table's font,
// so set it as appropriate
table.setFont(fontToUseForAllColumnsExceptFirst);
// a custom renderer which uses a special font
DefaultTableCellRenderer r = new DefaultTableCellRenderer() {
Font font = fontToUseForFirstColumn;
#Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
row, column);
setFont(font);
return this;
}
};
// doesn't work because the default renderer's font is reset
// to the table's font always
// r.setFont(font);
// set the custom renderer for first column
table.getColumnModel().getColumn(0).setCellRenderer(r);
An alternative is the renderer decoration approach, supported in the SwingX project (biased me can't resist :-) Then the above would be a two-liner (assuming table is of type JXTable):
Highlighter hl = new FontHighlighter(font);
table.getColumnExt(0).setHighlighter(hl);
I'm trying to render an specific row of my jtable (it should have a different background color and it should have bold characters).
I found several questions regarding how to implement a custom TableCellRenderer (here and here) and the tutorial How to Use Tables and this one (Table Row Rendering).
I'm using a JInternalFrame to display the JTable. I tried to implement both solutions but neither getCellRenderer nor prepareRenderer are being called. When debugging, I can see my new jtable being created, but, my breakpoint inside the methods aren't called.
My code looks like:
this.add(createData(model));
private JComponent createData(ProfitLossTableModel model) {
JTable table = new JTable(model) {
public TableCellRenderer getCellRenderer(int row, int column) {
if ((row == 0) && (column == 0)) {
DefaultTableCellRenderer renderer = new DefaultTableCellRenderer();
renderer.setHorizontalAlignment(JLabel.RIGHT);
renderer.setBackground(Color.red);
return renderer;
} else {
return super.getCellRenderer(row, column);
}
}
};
table.setPreferredScrollableViewportSize(table.getPreferredSize());
table.changeSelection(0, 0, false, false);
table.setAutoCreateRowSorter(true);
return new JScrollPane(table);
}
As you can see, model is my implementation of a AbstractTableModel.
Of course that I'm missing something. I tried to call repaint() to see if something happened, but nothing occurred.
I also tried to put a JPane inside my JInternalFrame and them add the JScrollPane into it, but nothing occurred also.
Any help?
TIA,
Bob
As discussed in Concepts: Editors and Renderers, "the table invokes the table model's getColumnClass method, which gets the data type of the column's cells." You should verify that your implementation of AbstractTableModel returns a suitable value, as suggested in this example.
Addendum:
I'm trying to render a row, not a column.
Rob Camick's Table Row Rendering approach that overrides prepareRenderer() seems apropos.
tabbedPane.addTab("FirstRow", createFirstRow(model));
...
private JComponent createFirstRow(DefaultTableModel model) {
final Font font = new Font("Serif", Font.BOLD, 14);
JTable table = new JTable(model) {
public Component prepareRenderer(
TableCellRenderer renderer, int row, int column) {
Component c = super.prepareRenderer(renderer, row, column);
if (!isRowSelected(row)) {
c.setBackground(row == 0 ? Color.yellow: getBackground());
c.setFont(row == 0 ? font : getFont());
}
return c;
}
};
table.setPreferredScrollableViewportSize(table.getPreferredSize());
table.changeSelection(1, 1, false, false);
return new JScrollPane(table);
}