Swing/MoveRow のバックアップの現在との差分(No.6)
TITLE:JTableの行を移動
JTableの行を移動
編集者:Terai Atsuhiro~
作成日:2004-02-23
更新日:2021-08-12 (木) 14:12:29
概要
ツールバーや、ポップアップメニューを使って、JTable
の行を上下に移動します。
Screenshot
Advertisement
概要
ツールバーや、ポップアップメニューを使って、JTableの行を上下に移動します。サンプルコード
#spanend
#spanadd
class DownAction extends AbstractAction {
#spanend
public DownAction(String str) {
super(str);
}
#spandel
#screenshot
#spanend
@Override public void actionPerformed(ActionEvent e) {
downActionPerformed(e);
}
#spanadd
}
#spanend
#spandel
**サンプルコード [#yc463e85]
#spanend
#spanadd
private void downActionPerformed(ActionEvent e) {
#spanend
System.out.println("-------- 下へ --------");
if (table.isEditing()) {
table.getCellEditor().stopCellEditing();
}
int[] pos = table.getSelectedRows();
if (pos.length == 0) {
return;
}
RowDataModel model = (RowDataModel) table.getModel();
boolean isShiftDown = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0;
if (isShiftDown) { // Jump to the end
model.moveRow(pos[0], pos[pos.length - 1], model.getRowCount() - pos.length);
table.setRowSelectionInterval(model.getRowCount() - pos.length, model.getRowCount() - 1);
} else {
if (pos[pos.length - 1] == model.getRowCount() - 1) {
return;
}
model.moveRow(pos[0], pos[pos.length - 1], pos[0] + 1);
table.setRowSelectionInterval(pos[0] + 1, pos[pos.length - 1] + 1);
}
Rectangle r = table.getCellRect(model.getRowCount() - 1, 0, true);
table.scrollRectToVisible(r);
#spanadd
}
#spanend
#spanadd
#spanend
#spanadd
public void showRowPop(MouseEvent e) {
#spanend
int row = table.rowAtPoint(e.getPoint());
int count = table.getSelectedRowCount();
int[] ilist = table.getSelectedRows();
boolean flg = true;
for (int i = 0; i < ilist.length; i++) {
if (ilist[i] == row) {
flg = false;
break;
}
}
if (row > 0 && flg) table.setRowSelectionInterval(row, row);
JPopupMenu pop = new JPopupMenu();
Action act = new TestCreateAction("追加", null);
act.setEnabled(count == 1);
pop.add(act);
pop.addSeparator();
act = new DeleteAction("削除", null);
act.setEnabled(row >= 0);
pop.add(act);
pop.addSeparator();
act = new UpAction("上へ");
act.setEnabled(count > 0);
pop.add(act);
act = new DownAction("下へ");
act.setEnabled(count > 0);
pop.add(act);
pop.show(e.getComponent(), e.getX(), e.getY());
#spanadd
}
#spanend
#spanadd
View in GitHub: Java, Kotlin解説
上記のサンプルでは、DefaultTableModel#moveRow(...)
メソッドを使用して選択した行を上下に動かしています。Shiftキーを押しながらツールバーの移動ボタンを押すとそれぞれ、先頭、末尾に移動します。
参考リンク
コメント
- いつもお世話になっております。違うカテゴリに投稿して、すみません。
JTable
のカラムの幅をマウスで広げたり、縮んだりする際、イベントで検出し、その幅を変数に取っておく方法はご存知でしょうか?当方はJDK 1.5
を使っています。よろしくお願いいたします。 -- Panda - こんばんは。
TableColumnModelListener
を使うのはどうでしょうか。 -- aterai
class DownAction extends AbstractAction{
public DownAction(String str) {
super(str);
}
public void actionPerformed(ActionEvent evt) {
downActionPerformed(evt);
}
}
private void downActionPerformed(ActionEvent e) {
System.out.println("-------- 下へ --------");
int[] pos = table.getSelectedRows();
if(pos==null || pos.length<=0) return;
DefaultTableModel mdl = (DefaultTableModel) table.getModel();
if((e.getModifiers() & ActionEvent.SHIFT_MASK)!=0) {
mdl.moveRow(pos[0], pos[pos.length-1], mdl.getRowCount()-pos.length);
table.setRowSelectionInterval(mdl.getRowCount()-pos.length,
mdl.getRowCount()-1);
}else{
if(pos[pos.length-1]==mdl.getRowCount()-1) return;
mdl.moveRow(pos[0], pos[pos.length-1], pos[0]+1);
table.setRowSelectionInterval(pos[0]+1, pos[pos.length-1]+1);
}
scrollSelectedRow();
}
public void showRowPop(MouseEvent e) {
int row = table.rowAtPoint(e.getPoint());
int count = table.getSelectedRowCount();
int[] ilist = table.getSelectedRows();
boolean flg = true;
for(int i=0;i<ilist.length;i++) {
if(ilist[i]==row) {
flg = false;
break;
}
}
if(row>0 && flg) table.setRowSelectionInterval(row, row);
JPopupMenu pop = new JPopupMenu();
Action act = new TestCreateAction("追加", null);
act.setEnabled(count>1?false:true);
pop.add(act);
pop.addSeparator();
act = new DeleteAction("削除", null);
act.setEnabled(row<0?false:true);
pop.add(act);
pop.addSeparator();
act = new UpAction("上へ");
act.setEnabled(count>0?true:false);
pop.add(act);
act = new DownAction("下へ");
act.setEnabled(count>0?true:false);
pop.add(act);
pop.show((JComponent)e.getSource(), e.getX(), e.getY());
}
#spanadd
final TableColumnModel cm = table.getColumnModel();
#spanend
#spanadd
cm.addColumnModelListener(new TableColumnModelListener() {
#spanend
@Override public void columnAdded(TableColumnModelEvent e) {}
@Override public void columnMarginChanged(ChangeEvent e) {
for (int i = 0; i < cm.getColumnCount(); i++) {
TableColumn c = cm.getColumn(i);
System.out.println(c.getHeaderValue() + ": " + c.getWidth());
}
}
@Override public void columnMoved(TableColumnModelEvent e) {}
@Override public void columnRemoved(TableColumnModelEvent e) {}
@Override public void columnSelectionChanged(ListSelectionEvent e) {}
#spanadd
});
#spanend
- &jnlp;
- &jar;
- &zip;
解説
上記のサンプルでは、DefaultTableModel#moveRowメソッドを使用して、選択した行を上下に動かしています。シフトキーを押しながら、ツールバーの移動ボタンを押すとそれぞれ、先頭、末尾に移動します。- ご回答、ありがとうございました。列の幅を変更するため、
TableColumn c = cm.getColumn(i);・・・c.setPreferredWidth(int preferredWidth);
で行いましたが、例えばc.setPreferredWidth(100)
にすると、System.out.println(c.getHeaderValue()+": "+c.getWidth());
の結果は75
が表示されます。見た目上も100
ピクセルになっていません。確実に幅100
ピクセルにするにはどうすれば良いでしょうか? -- Panda- 列幅が自動調整される場合は、サイズ変更(デルタ)が有効な列に分散されます。このデルタの分散の詳細については、JTable#doLayout() (Java Platform SE 8)を参考にしてください。自動調整が
OFF
(table.getAutoResizeMode()==AUTO_RESIZE_OFF
)の場合はデルタの分散を考慮する必要がないので、ある列の幅をぴったり100px
にするのは簡単です(TableColumn#setPreferredWidth(100)
とするだけで良い)。デフォルトのAUTO_RESIZE_SUBSEQUENT_COLUMNS
の場合は、例えば以下のようにデルタの分散が0
になるように?後の列も含めてサイズ調整しておく必要があります。 -- aterai
- 列幅が自動調整される場合は、サイズ変更(デルタ)が有効な列に分散されます。このデルタの分散の詳細については、JTable#doLayout() (Java Platform SE 8)を参考にしてください。自動調整が
コメント
#spanend
#spanadd
import java.awt.*;
#spanend
#spanadd
import java.awt.event.*;
#spanend
#spanadd
import javax.swing.*;
#spanend
#spanadd
import javax.swing.event.*;
#spanend
#spanadd
import javax.swing.table.*;
#spanend
#spanadd
public class ColumnPreferredWidthTest {
#spanend
String[] columnNames = {"String", "Integer", "Boolean"};
Object[][] data = {
{"aaa", 12, true}, {"bbb", 5, false},
{"CCC", 92, true}, {"DDD", 0, false}
};
DefaultTableModel model = new DefaultTableModel(data, columnNames) {
@Override public Class<?> getColumnClass(int column) {
return getValueAt(0, column).getClass();
}
};
JTable table = new JTable(model);
TableColumnModel cm = table.getColumnModel();
public JComponent makeUI() {
EventQueue.invokeLater(new Runnable() {
@Override public void run() {
int total = cm.getTotalColumnWidth();
int count = cm.getColumnCount();
cm.getColumn(0).setPreferredWidth(100); //0列目の幅を100pxにする
total -= 100;
int colwidth = total / (count - 1); //残りの列幅は均等になるように計算
for (int i = 1; i < count - 1; i++) {
TableColumn col = cm.getColumn(i);
col.setPreferredWidth(colwidth);
total -= colwidth;
}
cm.getColumn(count - 1).setPreferredWidth(total); //最後の列幅で余りを吸収
}
});
#spanadd
#spanend
JPanel p = new JPanel(new BorderLayout());
p.add(new JScrollPane(table));
p.add(new JButton(new AbstractAction("print width") {
@Override public void actionPerformed(ActionEvent e) {
for (int i = 0; i < cm.getColumnCount(); i++) {
TableColumn c = cm.getColumn(i);
System.out.println(c.getHeaderValue() + ": " + c.getWidth());
}
}
}), BorderLayout.SOUTH);
return p;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new ColumnPreferredWidthTest().makeUI());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
#spanadd
}
#spanend
#spanadd
- TableColumnの幅を比率で設定の解説を追加変更したので、そのうちこれらのコードはそちらに移動するかもしれません。 -- aterai