JTable 单元格中的 JButtons 在行选择时改变形状
JButtons in JTable cell change shape on row selection
我每行有一个单元格(列)table,单元格是一个面板,上面有 2 个按钮。 TableCellRenderer 和 TableCellEditor 已正确实现以允许呈现和编辑单元格。但是当我点击行甚至按钮时,按钮的形状会改变。看起来按钮的大小缩小以适合按钮文本。请参阅所附图片。
如果我设置了按钮的首选大小,那么大小似乎没有改变,但按钮文本向右移动。下面是 table 单元面板的代码。 运行从如下所示的相同 class 中的主面板打开此面板不会显示此行为。此行为仅在将此面板用作单列 table 行中的单元格时可见。不知道哪个 属性 哪个 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
}
下面是我的主要 JFrame 的样子:
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
}
添加示例代码以帮助重现问题。 运行 主要在NewJFrame1 class 看问题。取消注释并 运行 TableRowPanel1 private class 中的 main 以查看默认的正确工作。如果我直接在 JFrame 中使用 table 单元格面板组件,它工作正常。但是通过编辑器用作 table 单元格的相同组件显示了问题。请真的需要帮助。:
/*
* 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);
// });
//
// }
}
}
根据源代码,根据FlatBorder
规范,table单元格编辑器的边框插入为0。
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?
将单元格编辑器面板层次结构设为三级或更多级。
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);
}
}
或覆盖 FlatBorder#isCellEditor(Component c)
方法以始终 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);
// }
// }
我每行有一个单元格(列)table,单元格是一个面板,上面有 2 个按钮。 TableCellRenderer 和 TableCellEditor 已正确实现以允许呈现和编辑单元格。但是当我点击行甚至按钮时,按钮的形状会改变。看起来按钮的大小缩小以适合按钮文本。请参阅所附图片。
如果我设置了按钮的首选大小,那么大小似乎没有改变,但按钮文本向右移动。下面是 table 单元面板的代码。 运行从如下所示的相同 class 中的主面板打开此面板不会显示此行为。此行为仅在将此面板用作单列 table 行中的单元格时可见。不知道哪个 属性 哪个 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
}
下面是我的主要 JFrame 的样子:
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
}
添加示例代码以帮助重现问题。 运行 主要在NewJFrame1 class 看问题。取消注释并 运行 TableRowPanel1 private class 中的 main 以查看默认的正确工作。如果我直接在 JFrame 中使用 table 单元格面板组件,它工作正常。但是通过编辑器用作 table 单元格的相同组件显示了问题。请真的需要帮助。:
/*
* 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);
// });
//
// }
}
}
根据源代码,根据FlatBorder
规范,table单元格编辑器的边框插入为0。
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?
将单元格编辑器面板层次结构设为三级或更多级。
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);
}
}
或覆盖 FlatBorder#isCellEditor(Component c)
方法以始终 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);
// }
// }