Swing/LargeCellEditor のバックアップの現在との差分(No.5)
TITLE:JTableの編集にセルより大きなセルエディタを使用
JTableの編集にセルより大きなセルエディタを使用
編集者:Terai Atsuhiro~
作成日:2006-08-28
更新日:2023-01-20 (金) 17:37:29
概要
通常のセルエディタではなく、セルより大きなアイコンを選択する為のセルエディタを使用してJTable
を編集します。
Screenshot
Advertisement
概要
通常のセルエディタではなく、セルより大きなアイコンを選択する為のセルエディタを使用してJTableを編集します。サンプルコード
#spanend
#spanadd
class IconTable extends JTable {
#spanend
private static final int XOFF = 4;
private final JList<IconItem> editor;
private final JComponent glassPane = new JComponent() {
@Override public void setVisible(boolean flag) {
super.setVisible(flag);
setFocusTraversalPolicyProvider(flag);
setFocusCycleRoot(flag);
}
#spandel
#screenshot
#spanend
@Override protected void paintComponent(Graphics g) {
g.setColor(new Color(0x64_FF_FF_FF, true));
g.fillRect(0, 0, getWidth(), getHeight());
BufferedImage bufimg = new BufferedImage(
getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = bufimg.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .15f));
g2.setPaint(Color.BLACK);
Rectangle r = editor.getBounds();
for (int i = 0; i < XOFF; i++) {
g2.fillRoundRect(
r.x - i, r.y + XOFF, r.width + i + i, r.height - XOFF + i, 5, 5);
}
g2.dispose();
g.drawImage(bufimg, 0, 0, null);
}
};
#spandel
**サンプルコード [#p6d316e9]
#spanend
class IconTable extends JTable {
private final MyGlassPane panel = new MyGlassPane();
private FocusTraversalPolicy policy = new MyFocusTraversalPolicy();
private FocusTraversalPolicy ftp;
private final EditorFromList editor;
private final JFrame frame;
private Rectangle rect;
public IconTable(JFrame _frame, TableModel model, Vector list) {
super(model);
setDefaultRenderer(Object.class, new TestRenderer());
setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
initCellSize(50);
frame = _frame;
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent me) {
startEditing();
}
});
editor = new EditorFromList(list);
editor.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_ESCAPE) {
cancelEditing();
}
}
});
editor.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent me) {
changeValue(me.getPoint());
}
});
panel.add(editor);
frame.setGlassPane(panel);
panel.setVisible(false);
}
private void initCellSize(int size) {
setRowHeight(size);
JTableHeader tableHeader = getTableHeader();
tableHeader.setResizingAllowed(false);
tableHeader.setReorderingAllowed(false);
TableColumnModel m = getColumnModel();
for(int i=0;i<m.getColumnCount();i++) {
TableColumn col = m.getColumn(i);
col.setMinWidth(size);
col.setMaxWidth(size);
}
setBorder(BorderFactory.createLineBorder(Color.black));
}
private void initEditor() {
Dimension dim = editor.getPreferredSize();
rect = getCellRect(getSelectedRow(), getSelectedColumn(), true);
int iv = (dim.width-rect.width)/2;
Point p = SwingUtilities.convertPoint(this,
rect.getLocation(), panel);
rect.setRect(p.x-iv, p.y-iv, dim.width, dim.height);
editor.setBounds(rect);
Object o = getValueAt(getSelectedRow(), getSelectedColumn());
editor.setSelectedValue(o, true);
}
public void startEditing() {
initEditor();
ftp = frame.getFocusTraversalPolicy();
panel.setVisible(true);
editor.requestFocusInWindow();
frame.setFocusTraversalPolicy(policy);
}
private void cancelEditing() {
frame.setFocusTraversalPolicy(ftp);
panel.setVisible(false);
}
private void changeValue(Point p) {
frame.setFocusTraversalPolicy(ftp);
int index = editor.locationToIndex(p);
Object o = editor.getModel().getElementAt(index);
if(o != null) {
setValueAt(o, getSelectedRow(), getSelectedColumn());
}
panel.setVisible(false);
}
}
protected IconTable(TableModel model, ListModel<IconItem> list) {
super(model);
setDefaultRenderer(Object.class, new IconTableCellRenderer());
setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
initCellSize(50);
addMouseListener(new MouseAdapter() {
@Override public void mouseClicked(MouseEvent e) {
startEditing();
}
});
-&jnlp;
-&jar;
-&zip;
editor = new EditorFromList<>(list);
editor.getInputMap(JComponent.WHEN_FOCUSED).put(
KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "cancel-editing");
editor.getActionMap().put("cancel-editing", new AbstractAction() {
@Override public void actionPerformed(ActionEvent e) {
cancelEditing();
}
});
editor.addMouseListener(new MouseAdapter() {
@Override public void mouseClicked(MouseEvent e) {
Point p = e.getPoint();
IconItem item = editor.getModel().getElementAt(editor.locationToIndex(p));
setValueAt(item, getSelectedRow(), getSelectedColumn());
cancelEditing();
}
});
#spandel
**解説 [#t6dfc826]
#spanend
#spandel
上記のサンプルでは、JTableのセルをクリックするとそのセル上にセルエディタが表示されて編集できるようになっています。
#spanend
glassPane.addMouseListener(new MouseAdapter() {
@Override public void mouseClicked(MouseEvent e) {
cancelEditing();
}
});
glassPane.setFocusTraversalPolicy(new DefaultFocusTraversalPolicy() {
@Override public boolean accept(Component c) {
return Objects.equals(c, editor);
}
});
glassPane.add(editor);
glassPane.setVisible(false);
}
#spandel
通常のセルエディタは使用しないため、すべてのセルを編集不可にしています。かわりにセルをクリックしたときに、フレームのGlassPaneを有効にして、そこにJListで作成したアイコン選択エディタや、その影などを描画しています。
#spanend
private void initCellSize(int size) {
setRowHeight(size);
JTableHeader tableHeader = getTableHeader();
tableHeader.setResizingAllowed(false);
tableHeader.setReorderingAllowed(false);
TableColumnModel m = getColumnModel();
for (int i = 0; i < m.getColumnCount(); i++) {
TableColumn col = m.getColumn(i);
col.setMinWidth(size);
col.setMaxWidth(size);
}
setBorder(BorderFactory.createLineBorder(Color.BLACK));
}
#spandel
フレームの外にセルエディタを描画することができないため、JTableの周りに余白をかなり多めにとっています。JTableからはみ出す場合は、セルエディタの表示位置を変更するようにしたほうがいいかもしれません。
#spanend
public void startEditing() {
getRootPane().setGlassPane(glassPane);
#spandel
**参考リンク [#yc6dd5bb]
#spanend
-[[XP Style Icons - Windows Application Icon, Software XP Icons>http://www.icongalore.com/]]
--アイコンを利用しています。
Dimension d = editor.getPreferredSize();
editor.setSize(d);
#spandel
**コメント [#n6dadda3]
#spanend
int sr = getSelectedRow();
int sc = getSelectedColumn();
Rectangle r = getCellRect(sr, sc, true);
Point p = SwingUtilities.convertPoint(this, r.getLocation(), glassPane);
p.translate((r.width - d.width) / 2, (r.height - d.height) / 2);
editor.setLocation(p);
#spanadd
#spanend
glassPane.setVisible(true);
editor.setSelectedValue(getValueAt(sr, sc), true);
editor.requestFocusInWindow();
}
#spanadd
#spanend
private void cancelEditing() {
glassPane.setVisible(false);
}
#spanadd
}
#spanend
#spanadd
View in GitHub: Java, Kotlin解説
上記のサンプルでは、JTable
のセルをクリックするとそのセル上にセルエディタ(JList
)を表示してアイコンの選択、変更が可能になります。
- デフォルトの
TableCellEditor
は使用しないためすべてのセルを編集不可に設定 - セルをクリックしたときに
JRootPane
のGlassPane
を可視化- この
GlassPane
にアイコンを選択するためのセルエディタとしてJList
を追加 -
JList
の半透明の影などもGlassPane
上に描画 -
GlassPane
を使用しているためJFrame
の外にセルエディタを描画できない-
JTable
の周りに余白を設定することで回避
-
- この