Swing/LargeCellEditor のバックアップ差分(No.12)
- バックアップ一覧
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- バックアップ を表示
- Swing/LargeCellEditor へ行く。
- 1 (2006-08-28 (月) 00:57:26)
- 2 (2006-08-28 (月) 08:21:34)
- 3 (2006-08-28 (月) 16:26:07)
- 4 (2006-08-31 (木) 14:27:45)
- 5 (2006-10-29 (日) 02:01:59)
- 6 (2007-04-11 (水) 16:07:24)
- 7 (2007-07-03 (火) 19:21:07)
- 8 (2012-09-05 (水) 23:15:13)
- 9 (2013-02-24 (日) 22:28:05)
- 10 (2015-01-20 (火) 15:49:33)
- 11 (2016-05-20 (金) 19:17:07)
- 12 (2016-05-27 (金) 13:14:22)
- 13 (2017-08-31 (木) 13:54:58)
- 14 (2018-09-14 (金) 20:04:37)
- 15 (2018-10-30 (火) 16:36:36)
- 16 (2018-12-21 (金) 14:09:26)
- 17 (2020-11-22 (日) 01:13:23)
- 18 (2023-01-20 (金) 17:37:28)
- 追加された行はこの色です。
- 削除された行はこの色です。
--- title: JTableの編集にセルより大きなセルエディタを使用 tags: [JTable, JList, GlassPane] author: aterai pubdate: 2006-08-28T00:57:26+09:00 description: 通常のセルエディタではなく、セルより大きなアイコンを選択する為のセルエディタを使用してJTableを編集します。 --- * 概要 [#u7405edd] 通常のセルエディタではなく、セルより大きなアイコンを選択する為のセルエディタを使用して`JTable`を編集します。 #download(https://lh5.googleusercontent.com/_9Z4BYR88imo/TQTO6b-zTJI/AAAAAAAAAdI/UAROdzzun4k/s800/LargeCellEditor.png) * サンプルコード [#p6d316e9] #code(link){{ class IconTable extends JTable { private final MyGlassPane panel = new MyGlassPane(); private final EditorFromList editor; private final JFrame frame; private Rectangle rect; 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); } @Override protected void paintComponent(Graphics g) { g.setColor(new Color(0x64FFFFFF, 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); } }; public IconTable(JFrame _frame, TableModel model, Vector list) { protected IconTable(TableModel model, ListModel<IconItem> list) { super(model); setDefaultRenderer(Object.class, new TestRenderer()); setDefaultRenderer(Object.class, new IconTableCellRenderer()); setSelectionMode(ListSelectionModel.SINGLE_SELECTION); initCellSize(50); frame = _frame; addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent me) { @Override public void mouseClicked(MouseEvent e) { startEditing(); } }); editor = new EditorFromList(list); editor.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { cancelEditing(); } 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 me) { changeValue(me.getPoint()); @Override public void mouseClicked(MouseEvent e) { Point p = e.getPoint(); IconItem item = editor.getModel().getElementAt(editor.locationToIndex(p)); setValueAt(item, getSelectedRow(), getSelectedColumn()); cancelEditing(); } }); panel.add(editor); frame.setGlassPane(panel); panel.setVisible(false); 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); } 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(); panel.setVisible(true); getRootPane().setGlassPane(glassPane); Dimension d = editor.getPreferredSize(); editor.setSize(d); 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); glassPane.setVisible(true); editor.setSelectedValue(getValueAt(sr, sc), true); editor.requestFocusInWindow(); } private void cancelEditing() { panel.setVisible(false); glassPane.setVisible(false); } private void changeValue(Point p) { int index = editor.locationToIndex(p); Object o = editor.getModel().getElementAt(index); if (o != null) { setValueAt(o, getSelectedRow(), getSelectedColumn()); } panel.setVisible(false); } } }} * 解説 [#t6dfc826] 上記のサンプルでは、`JTable`のセルをクリックするとそのセル上にセルエディタが表示されて編集できるようになっています。 上記のサンプルでは、`JTable`のセルをクリックすると、そのセル上にセルエディタ(`JList`)が表示され、アイコンを選択、変更可能になっています。 通常のセルエディタは使用しないため、すべてのセルを編集不可にしています。かわりにセルをクリックしたときに、フレームの`GlassPane`を有効にして、そこに`JList`で作成したアイコン選択エディタや、その影などを描画しています。 - デフォルトの`TableCellEditor`は使用しないため、すべてのセルを編集不可に設定 - セルをクリックしたときに、`JRootPane`の`GlassPane`を可視化 -- この`GlassPane`にアイコン選択エディタとして`JList`を追加 -- `JList`の半透明の影なども`GlassPane`上に描画 -- `GlassPane`を使用しているため、`JFrame`の外にセルエディタを描画できない --- `JTable`の周りに余白を設定することで回避 このように`GlassPane`を使用しているため、フレームの外にセルエディタを描画することができません。このためサンプルでは`JTable`の周りに余白をかなり多めにとっています。`JTable`からはみ出す場合(端の方のセルを編集する場合)は、セルエディタの表示位置を内部にずらすように変更するようにしたほうがいいかもしれません。 * 参考リンク [#yc6dd5bb] - [http://www.icongalore.com/ XP Style Icons - Windows Application Icon, Software XP Icons] -- アイコンを利用しています。 * コメント [#n6dadda3] #comment - 表示をアニメーションさせたり、音を出したりしても面白そうです。 -- &user(aterai); &new{2006-10-29 (日) 02:03:44}; #comment