我有一行数据,可以在其中对远程服务器执行操作。
我在JTable
中显示这些数据,因为这样可以避免为每行创建一个组件的成本,而且组件数量很多。
我已经设法显示组件,并能够与细胞互动,(但我仍然是第一次点击)。
但是我所纠结的是我希望我的编辑器组件是可扩展的,当然也要更新当前的行高。当然还要在折叠时恢复到常规的行高。我想我需要向单元格编辑器注册一些侦听器,但是我目前还不能正确地做到这一点。
ComponentListner::componentResized
使整个表不断地重新绘制。editorComponent.addPropertyChangeListener("preferredSize", propertyChangeListener)
,不总是重新绘制表editorComponent.addPropertyChangeListener("preferredSize", propertyChangeListener)
,不总是重新绘制表
所以才有这个问题。
第一节第二节第一节第三节第一节
有些超出了范围,我目前正在讨论组件在转到另一个单元格时是否应该保持展开状态(但这可以是模型的一部分expanded
属性)。
下面是一个最小的示例,我没有尝试在编辑器组件(getTableCellEditorComponent
中)上注册侦听器。
提前感谢您的ay指针。
package io.github.bric3.fireplace.ui;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.border.TitledBorder;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
public class DynamicCellRow {
@NotNull
private static JTable makeTable() {
var jTable = new JTable(
new Object[][]{
{"a", "charly"},
{"b", "tango"}
},
new Object[]{"id", "control"}
);
{
var richColumn = jTable.getColumnModel().getColumn(1);
richColumn.setCellRenderer(new TableCellRenderer() {
private final ExpandablePanel expandablePanelRenderComponent = new ExpandablePanel();
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
expandablePanelRenderComponent.setValue(value);
return updatePreferredRowHeight(table, expandablePanelRenderComponent, row, column);
}
});
richColumn.setCellEditor(new DynamicCellEditor());
}
return jTable;
}
public static <T extends JComponent> T updatePreferredRowHeight(JTable table, T cellComponent, int row, int column) {
// Adjust cell height per component
int originalPreferredHeight = cellComponent.getPreferredSize().height;
cellComponent.setSize(
table.getColumnModel().getColumn(column).getWidth(),
originalPreferredHeight
);
int newPreferredHeight = cellComponent.getPreferredSize().height;
if (table.getRowHeight(row) < newPreferredHeight) {
table.setRowHeight(row, newPreferredHeight);
}
return cellComponent;
}
static class ExpandablePanel extends JPanel {
private final JLabel comp;
ExpandablePanel() {
setBorder(BorderFactory.createLineBorder(Color.black));
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
// horizontal left-to-right layout
gbc.gridx = 0;
gbc.gridy = 0;
// resizing behavior
gbc.weightx = 1;
gbc.weighty = 1;
gbc.insets = new Insets(2, 2, 2, 2);
gbc.fill = GridBagConstraints.BOTH;
JPanel advanced = new JPanel();
{
advanced.setLayout(new BoxLayout(advanced, BoxLayout.Y_AXIS));
advanced.setBorder(new TitledBorder("Advance Settings"));
advanced.add(new JCheckBox("Live"));
advanced.add(new JCheckBox("Condition"));
advanced.add(new JCheckBox("Disable"));
}
advanced.setVisible(false);
var standard = new JPanel();
{
standard.setLayout(new BoxLayout(standard, BoxLayout.X_AXIS));
comp = new JLabel("Label 1");
standard.add(comp);
standard.add(new JButton("Button 1"));
var expandButton = new JButton("+");
expandButton.addActionListener(e -> {
if (advanced.isVisible()) {
advanced.setVisible(false);
expandButton.setText("+");
} else {
advanced.setVisible(true);
expandButton.setText("-");
}
});
standard.add(expandButton);
}
add(standard, gbc);
gbc.gridy++;
gbc.weighty = 0;
add(advanced, gbc);
}
public void setValue(Object value) {
comp.setText(value.toString());
}
}
private static class DynamicCellEditor extends AbstractCellEditor implements TableCellEditor {
Object value;
@Override
public Object getCellEditorValue() {
return value; // not changing
}
private final ExpandablePanel expandablePanel = new ExpandablePanel();
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
this.value = value;
expandablePanel.setValue(value);
return updatePreferredRowHeight(table, expandablePanel, row, column);
}
}
public static void main(String[] args) {
var contentPane = new JPanel(new BorderLayout());
contentPane.add(new JScrollPane(makeTable()));
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("DynamicCellRow");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(contentPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
1条答案
按热度按时间4dc9hkyq1#
@kleopatra谢谢!你的提示让我走上了正确的轨道。我制作了下面的代码来在布局操作期间预先计算行高。
当一个单元格被编辑时,编辑器被添加到表中,然后重新验证,并相应地计算高度。
我以前遇到过一个问题,因为在渲染器中设置高度实际上阻止了单元组件的正确显示。
在下面的代码中,请注意
doLayout
是如何根据单元格组件的首选大小(无论是呈现还是编辑单元格)调整行高的。DynamicExpndablePanelCellEditor
中的侦听器也是如此。*