I have a single cell (column) per row based table and the cell is a panel with 2 buttons on it. TableCellRenderer and TableCellEditor are implemented correctly to allow render and edit the cell. But when i click the row or even the button, the shape of the buttons change. It looks like the size of the button shrinks to fit the button text. Please see the attached images.
If I set a preferred size of the buttons then the size doesn't seem to change but the button text shift towards right. Below is the code of the table cell panel. Running this panel from a main in the same class like shown below dosn't show this behavior. This behavior is only visible when using this panel as a cell in the single column table row. Don't know which property of what to set/change.
public class PartitionsTableRowPanel extends javax.swing.JPanel {
/**
* Creates new form PartitionsTableRowPanel
*/
public PartitionsTableRowPanel() {
initComponents();
postInitAdjustments();
}
private void postInitAdjustments() {
// infoButton.putClientProperty("JButton.buttonType", "roundRect");
// scanButton.putClientProperty("JButton.buttonType", "roundRect");
//
// infoButton.addActionListener((e) -> {
// log.info("info clicked");
// });
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jButton1 = new javax.swing.JButton();
jButton2 = new javax.swing.JButton();
setPreferredSize(new java.awt.Dimension(1000, 59));
setLayout(new org.netbeans.lib.awtextra.AbsoluteLayout());
jButton1.setText("Info");
add(jButton1, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 20, -1, -1));
jButton2.setText("jButton2");
add(jButton2, new org.netbeans.lib.awtextra.AbsoluteConstraints(90, 20, -1, -1));
}// </editor-fold>
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
FlatDarkLaf.install();
JFrame f = new JFrame("TestProgressBar");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setContentPane(new PartitionsTableRowPanel());
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
// Variables declaration - do not modify
private javax.swing.JButton jButton1;
private javax.swing.JButton jButton2;
// End of variables declaration
}
Below is what my main JFrame looks like:
public class MainAppWindow extends javax.swing.JFrame {
/**
* Creates new form MainWindow1
*/
public MainAppWindow() {
initComponents();
postInitAdjustments();
}
private void postInitAdjustments() {
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
northPanel = new javax.swing.JPanel();
jScrollPane1 = new javax.swing.JScrollPane();
partitionDetailsTable = new javax.swing.JTable();
centerPanel = new javax.swing.JPanel();
messageDetailsTextPaneScrollPane = new javax.swing.JScrollPane();
messageDetailsTextPane = new javax.swing.JTextPane();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setTitle("Sentry Disk Helper");
setName("mainFrame"); // NOI18N
setPreferredSize(new java.awt.Dimension(984, 606));
northPanel.setName("northPanel"); // NOI18N
partitionDetailsTable.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
{null, null, null, null},
{null, null, null, null},
{null, null, null, null},
{null, null, null, null}
},
new String [] {
"Title 1", "Title 2", "Title 3", "Title 4"
}
));
partitionDetailsTable.setFocusable(false);
partitionDetailsTable.setName("partitionsTable"); // NOI18N
jScrollPane1.setViewportView(partitionDetailsTable);
javax.swing.GroupLayout northPanelLayout = new javax.swing.GroupLayout(northPanel);
northPanel.setLayout(northPanelLayout);
northPanelLayout.setHorizontalGroup(
northPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(northPanelLayout.createSequentialGroup()
.addContainerGap()
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 1048, Short.MAX_VALUE)
.addContainerGap())
);
northPanelLayout.setVerticalGroup(
northPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(northPanelLayout.createSequentialGroup()
.addContainerGap()
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 238, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
getContentPane().add(northPanel, java.awt.BorderLayout.NORTH);
centerPanel.setBounds(new java.awt.Rectangle(2, 4, 0, 0));
centerPanel.setName("centerPanel"); // NOI18N
messageDetailsTextPane.setFocusable(false);
messageDetailsTextPaneScrollPane.setViewportView(messageDetailsTextPane);
javax.swing.GroupLayout centerPanelLayout = new javax.swing.GroupLayout(centerPanel);
centerPanel.setLayout(centerPanelLayout);
centerPanelLayout.setHorizontalGroup(
centerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(centerPanelLayout.createSequentialGroup()
.addContainerGap()
.addComponent(messageDetailsTextPaneScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 1048, Short.MAX_VALUE)
.addContainerGap())
);
centerPanelLayout.setVerticalGroup(
centerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, centerPanelLayout.createSequentialGroup()
.addComponent(messageDetailsTextPaneScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 350, Short.MAX_VALUE)
.addContainerGap())
);
getContentPane().add(centerPanel, java.awt.BorderLayout.CENTER);
getAccessibleContext().setAccessibleName("Sentery Disk Helper");
setSize(new java.awt.Dimension(984, 628));
setLocationRelativeTo(null);
}// </editor-fold>
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(MainAppWindow.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(MainAppWindow.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(MainAppWindow.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(MainAppWindow.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
//FlatIntelliJLaf.install();
new MainAppWindow().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JPanel centerPanel;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JTextPane messageDetailsTextPane;
private javax.swing.JScrollPane messageDetailsTextPaneScrollPane;
private javax.swing.JPanel northPanel;
private javax.swing.JTable partitionDetailsTable;
// End of variables declaration
}
Adding a sample code to help reproduce the problem. Run the main in the NewJFrame1 class to see the issue. Uncomment and Run the main in the TableRowPanel1 private class to see the default correct working. If i use the table cell panel component directly in a JFrame it works fine. But same component used as table cell via an editor shows the problem. Really need help with this please.:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.swing.test.demo.ui;
import com.formdev.flatlaf.FlatDarkLaf;
import com.swing.test.demo.ui.components.TableRowPanel;
import java.awt.Component;
import java.awt.EventQueue;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractCellEditor;
import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
public class NewJFrame1 extends javax.swing.JFrame {
/**
* Creates new form NewJFrame1
*/
public NewJFrame1() {
initComponents();
postInit();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jPanel1 = new javax.swing.JPanel();
jScrollPane1 = new javax.swing.JScrollPane();
jTable1 = new javax.swing.JTable();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jTable1.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
{null, null, null, null},
{null, null, null, null},
{null, null, null, null},
{null, null, null, null}
},
new String [] {
"Title 1", "Title 2", "Title 3", "Title 4"
}
));
jScrollPane1.setViewportView(jTable1);
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 481, Short.MAX_VALUE)
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 337, Short.MAX_VALUE)
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap())
);
pack();
}// </editor-fold>
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
// try {
// for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
// if ("Nimbus".equals(info.getName())) {
// javax.swing.UIManager.setLookAndFeel(info.getClassName());
// break;
// }
// }
// } catch (ClassNotFoundException ex) {
// java.util.logging.Logger.getLogger(NewJFrame1.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
// } catch (InstantiationException ex) {
// java.util.logging.Logger.getLogger(NewJFrame1.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
// } catch (IllegalAccessException ex) {
// java.util.logging.Logger.getLogger(NewJFrame1.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
// } catch (javax.swing.UnsupportedLookAndFeelException ex) {
// java.util.logging.Logger.getLogger(NewJFrame1.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
// }
//</editor-fold>
FlatDarkLaf.setup();
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
NewJFrame1 newJFrame1 = new NewJFrame1();
newJFrame1.setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JPanel jPanel1;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JTable jTable1;
// End of variables declaration
private void postInit() {
List<Data> modelData = new ArrayList<>();
for (int i = 0; i < 4; i++) {
Data data = new Data();
data.value = "Data_" + i;
modelData.add(data);
}
jTable1.setDefaultRenderer(Data.class, new MyCellRenderer());
jTable1.setDefaultEditor(Data.class, new MyCellEditor());
jTable1.setModel(new MyTableModel(modelData));
jTable1.setRowHeight(52);
jTable1.revalidate();
//
}
private class Data {
String value;
}
private class MyTableModel extends AbstractTableModel {
private List<Data> data;
public MyTableModel(List<Data> data) {
this.data = data;
}
@Override
public int getRowCount() {
return data.size();
}
@Override
public int getColumnCount() {
return 1;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
return data.get(rowIndex);
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return true;
}
@Override
public Class<?> getColumnClass(int columnIndex) {
return Data.class;
}
}
private class MyCellRenderer implements TableCellRenderer {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
System.out.println("fff");
return new TableRowPanel1();
}
}
private class MyCellEditor extends AbstractCellEditor implements TableCellEditor {
@Override
public Object getCellEditorValue() {
return null;
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
System.out.println("ddd");
return new TableRowPanel1();
}
}
private class TableRowPanel1 extends javax.swing.JPanel {
/**
* Creates new form TableRowPanel
*/
public TableRowPanel1() {
initComponents();
}
/**
* This method is called from within the constructor to initialize the
* form. WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jButton1 = new javax.swing.JButton();
jButton2 = new javax.swing.JButton();
jButton1.setText("jButton1");
jButton2.setText("jButton2");
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jButton1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jButton2)
.addContainerGap(250, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(14, 14, 14)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jButton1)
.addComponent(jButton2))
.addContainerGap(14, Short.MAX_VALUE))
);
}// </editor-fold>
// Variables declaration - do not modify
private javax.swing.JButton jButton1;
private javax.swing.JButton jButton2;
// End of variables declaration
// public static void main(String[] args) {
// EventQueue.invokeLater(() -> {
// FlatDarkLaf.setup();
// JFrame f = new JFrame("TestProgressBar");
// f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// f.setContentPane(new TableRowPanel());
// f.pack();
// f.setLocationRelativeTo(null);
// f.setVisible(true);
// });
//
// }
}
}
According to the source code, the border inset of the table cell editor is 0 according to the FlatBorder
specification.
com/formdev/flatlaf/ui/FlatBorder.java
protected boolean isCellEditor( Component c ) {
return FlatUIUtils.isCellEditor( c );
}
@Override
public Insets getBorderInsets( Component c, Insets insets ) {
// ...
if( isCellEditor( c ) ) {
// remove top and bottom insets if used as cell editor
insets.top = insets.bottom = 0;
// ...
com/formdev/flatlaf/ui/FlatUIUtils.java
public static boolean isCellEditor( Component c ) {
// check whether used in cell editor (check 3 levels up)
Any ideas about how to rectify this?
Make the cell editor panel hierarchy three or more levels.
class TableRowPanel1 extends JPanel {
protected final JButton jButton1 = new JButton("jButton1");
protected final JButton jButton2 = new JButton("jButton2");
public TableRowPanel1() {
super(new BorderLayout());
JPanel p2 = new JPanel(new FlowLayout(FlowLayout.LEADING));
p2.add(jButton1);
p2.add(jButton2);
JPanel p1 = new JPanel(new BorderLayout());
p1.add(p2);
add(p1);
}
}
or override FlatBorder#isCellEditor(Component c)
method to always return false
.
class TableRowPanel1 extends JPanel {
protected final JButton jButton1 = new JButton("jButton1");
protected final JButton jButton2 = new JButton("jButton2");
public TableRowPanel1() {
super(new FlowLayout(FlowLayout.LEADING));
FlatBorder border = new FlatButtonBorder() {
@Override protected boolean isCellEditor(Component c) {
return false;
}
};
jButton1.setBorder(border);
jButton2.setBorder(border);
add(jButton1);
add(jButton2);
}
}
NewJFrame2.java
import com.formdev.flatlaf.*;
import com.formdev.flatlaf.ui.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import javax.swing.table.*;
public class NewJFrame2 {
public Component makeUI() {
List<Data> modelData = new ArrayList<>();
for (int i = 0; i < 4; i++) {
Data data = new Data();
data.value = "Data_" + i;
modelData.add(data);
}
JTable table = new JTable(new MyTableModel(modelData));
table.setDefaultRenderer(Data.class, new MyCellRenderer());
table.setDefaultEditor(Data.class, new MyCellEditor());
table.setRowHeight(52);
JPanel p = new JPanel(new BorderLayout());
p.add(new JScrollPane(table));
p.add(new TableRowPanel1(), BorderLayout.SOUTH);
return p;
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
FlatDarkLaf.setup();
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new NewJFrame2().makeUI());
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
class Data {
String value;
}
class MyTableModel extends AbstractTableModel {
private List<Data> data;
public MyTableModel(List<Data> data) {
this.data = data;
}
@Override
public int getRowCount() {
return data.size();
}
@Override
public int getColumnCount() {
return 1;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
return data.get(rowIndex);
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return true;
}
@Override
public Class<?> getColumnClass(int columnIndex) {
return Data.class;
}
}
class MyCellRenderer implements TableCellRenderer {
protected final TableRowPanel1 renderer = new TableRowPanel1();
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
return renderer;
}
}
class MyCellEditor extends AbstractCellEditor implements TableCellEditor {
protected final TableRowPanel1 editor = new TableRowPanel1();
@Override
public Object getCellEditorValue() {
return null;
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
return editor;
}
}
class TableRowPanel1 extends JPanel {
protected final JButton jButton1 = new JButton("jButton1");
protected final JButton jButton2 = new JButton("jButton2");
public TableRowPanel1() {
super(new BorderLayout());
JPanel p2 = new JPanel(new FlowLayout(FlowLayout.LEADING));
p2.add(jButton1);
p2.add(jButton2);
JPanel p1 = new JPanel(new BorderLayout());
p1.add(p2);
add(p1);
}
}
// class TableRowPanel1 extends JPanel {
// protected final JButton jButton1 = new JButton("jButton1");
// protected final JButton jButton2 = new JButton("jButton2");
//
// public TableRowPanel1() {
// super(new FlowLayout(FlowLayout.LEADING));
// FlatBorder border = new FlatButtonBorder() {
// @Override protected boolean isCellEditor(Component c) {
// return false;
// }
// };
// jButton1.setBorder(border);
// jButton2.setBorder(border);
// add(jButton1);
// add(jButton2);
// }
// }