JListのセルに配置したJLabelのテキストを編集する
Total: 2526, Today: 1, Yesterday: 2
Posted by aterai at
Last-modified:
Summary
JListのセル内に配置したJLabelのテキストを編集可能にするセルエディタを作成します。
Screenshot

Advertisement
Source Code Examples
class EditableList<E extends ListItem> extends JList<E> {
private transient MouseInputAdapter handler;
protected final Container glassPane = new EditorGlassPane();
protected final JTextField editor = new JTextField();
protected final Action startEditing = new AbstractAction() {
@Override public void actionPerformed(ActionEvent e) {
getRootPane().setGlassPane(glassPane);
int idx = getSelectedIndex();
ListItem item = getSelectedValue();
Rectangle rect = getCellBounds(idx, idx);
Point p = SwingUtilities.convertPoint(
EditableList.this, rect.getLocation(), glassPane);
rect.setLocation(p);
int h = editor.getPreferredSize().height;
rect.y = rect.y + rect.height - h - 1;
rect.height = h;
rect.grow(-2, 0);
editor.setBounds(rect);
editor.setText(item.title);
editor.selectAll();
glassPane.add(editor);
glassPane.setVisible(true);
editor.requestFocusInWindow();
}
};
protected final Action cancelEditing = new AbstractAction() {
@Override public void actionPerformed(ActionEvent e) {
glassPane.setVisible(false);
}
};
protected final Action renameTitle = new AbstractAction() {
@Override public void actionPerformed(ActionEvent e) {
String title = editor.getText().trim();
int index = getSelectedIndex();
if (!title.isEmpty() && index >= 0) {
E item = getModel().getElementAt(index);
item.setTitle(title);
}
glassPane.setVisible(false);
}
};
protected EditableList(DefaultListModel<E> model) {
super(model);
editor.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
editor.setHorizontalAlignment(SwingConstants.CENTER);
// editor.setOpaque(false);
// editor.setLineWrap(true);
InputMap im = editor.getInputMap(JComponent.WHEN_FOCUSED);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "rename-title");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "cancel-editing");
ActionMap am = editor.getActionMap();
am.put("rename-title", renameTitle);
am.put("cancel-editing", cancelEditing);
addMouseListener(new MouseAdapter() {
@Override public void mouseClicked(MouseEvent e) {
int idx = getSelectedIndex();
Rectangle rect = getCellBounds(idx, idx);
if (rect == null) {
return;
}
int h = editor.getPreferredSize().height;
rect.y = rect.y + rect.height - h;
rect.height = h;
boolean isDoubleClick = e.getClickCount() >= 2;
if (isDoubleClick && rect.contains(e.getPoint())) {
startEditing.actionPerformed(new ActionEvent(
e.getComponent(), ActionEvent.ACTION_PERFORMED, ""));
}
}
});
getInputMap(JComponent.WHEN_FOCUSED).put(
KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "start-editing");
getActionMap().put("start-editing", startEditing);
}
@Override public void updateUI() {
removeMouseListener(handler);
setSelectionForeground(null);
setSelectionBackground(null);
setCellRenderer(null);
super.updateUI();
setLayoutOrientation(JList.HORIZONTAL_WRAP);
getSelectionModel().setSelectionMode(
ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
setVisibleRowCount(0);
setFixedCellWidth(56);
setFixedCellHeight(56);
setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
setCellRenderer(new ListItemListCellRenderer<>());
handler = new ClearSelectionListener();
addMouseListener(handler);
}
protected JTextComponent getEditorTextField() {
return editor;
}
private class EditorGlassPane extends JComponent {
protected EditorGlassPane() {
super();
setOpaque(false);
setFocusTraversalPolicy(new DefaultFocusTraversalPolicy() {
@Override public boolean accept(Component c) {
return Objects.equals(c, getEditorTextField());
}
});
addMouseListener(new MouseAdapter() {
@Override public void mouseClicked(MouseEvent e) {
if (!getEditorTextField().getBounds().contains(e.getPoint())) {
renameTitle.actionPerformed(new ActionEvent(
e.getComponent(), ActionEvent.ACTION_PERFORMED, ""));
}
}
});
}
@Override public void setVisible(boolean flag) {
super.setVisible(flag);
setFocusTraversalPolicyProvider(flag);
setFocusCycleRoot(flag);
}
}
}
View in GitHub: Java, KotlinDescription
- 水平ニュースペーパー・スタイルレイアウトを設定した
JListでアイテム(セル)のタイトル文字列を編集可能にするJListデフォルトのセルを垂直方向に1列に並べたレイアウトでセルを編集可能にする場合はヘッダを非表示にしたJTableとTableCellEditorで代用可能JFileChooser(FilePane)で使用されるListViewはJListで作成されているが、名前がTree.cellEditorのJTextFieldがファイル名変更用セルエディタとして利用可能
- 選択したセルのタイトル文字列領域がダブルクリックされると
GlassPaneを表示 JTextFieldに選択したセルのタイトル文字列を設定GlassPaneにJTextFieldを配置してその位置とサイズをセルのタイトル文字列領域と同じになるよう変更JList上にセルエディタとしてGlassPaneごと表示JTextFieldからフォーカスが移動したらGlassPaneを非表示に設定し、JTextFieldのテキストを選択したセルのタイトル文字列に設定
- Resizing the parent JFrame results in incorrect positioning of the list cell editor during editing · Issue #34 · aterai/java-swing-tips
- リストエディタ表示中に
JListのサイズが変更されて編集中のセル位置が変化した場合、リストエディタの位置がずれてしまうバグを修正 JFileChooserのリストエディタも同様に位置がずれるバグ?がある
- JFileChooserのリサイズでファイル名編集をキャンセルするに、
ComponentListenerを追加してリサイズで編集をキャンセルすることで位置ズレを回避するサンプルを移動
- リストエディタ表示中に
Reference
- JTabbedPaneのタブタイトルを変更
- JListのアイテムをフィルタリングして表示
- JListのモデルをソートする
- JTextAreaとJFrameで幅固定、文字列の折り返し、親枠外まで高さ拡大可能なセルエディタを作成する
- JFileChooserのセルエディタでリネームを開始したとき拡張子を除くファイル名を選択状態にする