Swing/RubberBanding のバックアップの現在との差分(No.4)
TITLE:JListのアイテムを範囲指定で選択
JListのアイテムを範囲指定で選択
編集者:Terai Atsuhiro~
作成日:2006-08-14
更新日:2022-08-17 (水) 14:32:17
- category: swing folder: RubberBanding title: JListのアイテムを範囲指定で選択 tags: [JList, MouseListener, MouseMotionListener] author: aterai pubdate: 2006-08-14T01:35:31+09:00 description: JListのアイテムをラバーバンドで範囲指定して選択します。 image: hreflang:
href: https://java-swing-tips.blogspot.com/2008/10/using-rubber-band-selection-in-jlist.html lang: en
概要
JList
のアイテムをラバーバンドで範囲指定して選択します。
Screenshot
Advertisement
概要
JListのアイテムをラバーバンドで範囲指定して選択します。サンプルコード
#spanend
#spanadd
class RubberBandSelectionList<E extends ListItem> extends JList<E> {
#spanend
private static final AlphaComposite ALPHA =
AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .1f);
private RubberBandListCellRenderer<E> renderer;
private Color polygonColor;
public RubberBandSelectionList(ListModel<E> model) {
super(model);
}
#spandel
#screenshot
#spanend
@Override public void updateUI() {
setSelectionForeground(null);
setSelectionBackground(null);
setCellRenderer(null);
if (renderer == null) {
renderer = new RubberBandListCellRenderer<E>();
} else {
removeMouseMotionListener(renderer);
removeMouseListener(renderer);
}
super.updateUI();
EventQueue.invokeLater(() -> {
setCellRenderer(renderer);
addMouseMotionListener(renderer);
addMouseListener(renderer);
setLayoutOrientation(JList.HORIZONTAL_WRAP);
setVisibleRowCount(0);
setFixedCellWidth(62);
setFixedCellHeight(62);
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
});
Color c = getSelectionBackground();
int r = c.getRed();
int g = c.getGreen();
int b = c.getBlue();
polygonColor = r > g ? r > b ? new Color(r, 0, 0) : new Color(0, 0, b)
: g > b ? new Color(0, g, 0) : new Color(0, 0, b);
}
#spandel
**サンプルコード [#t7aa984b]
#spanend
class MyList extends JList {
private final Color pcolor;
private final AlphaComposite alcomp =
AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.1f);
private final Polygon polygon = new Polygon();
private final Line2D line = new Line2D.Double();
private Point srcPoint = null;
public MyList(ListModel model) {
super(model);
pcolor = makeColor();
setLayoutOrientation(JList.HORIZONTAL_WRAP);
setVisibleRowCount(0);
setFixedCellWidth(62);
setFixedCellHeight(62);
setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
setCellRenderer(new ListCellRenderer() {
public Component getListCellRendererComponent(JList list,
Object value, int index,
boolean isSelected, boolean cellHasFocus) {
MyIcon icon = (MyIcon)getModel().getElementAt(index);
icon.setSelected(isSelected);
icon.setFocused(cellHasFocus);
return icon;
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e){
if(srcPoint==null) srcPoint = e.getPoint();
Point destPoint = e.getPoint();
polygon.reset();
polygon.addPoint(srcPoint.x, srcPoint.y);
polygon.addPoint(destPoint.x, srcPoint.y);
polygon.addPoint(destPoint.x, destPoint.y);
polygon.addPoint(srcPoint.x, destPoint.y);
if(srcPoint.getX()==destPoint.getX() ||
srcPoint.getY()==destPoint.getY()) {
line.setLine(srcPoint.getX(),srcPoint.getY(),
destPoint.getX(),destPoint.getY());
setSelectedIndices(getIntersectsIcons(line));
}else{
setSelectedIndices(getIntersectsIcons(polygon));
}
repaint();
}
});
addMouseListener(new MouseAdapter() {
public void mouseReleased(MouseEvent e) {
srcPoint = null;
repaint();
}
public void mousePressed(MouseEvent e) {
if(locationToIndex(e.getPoint())<0) {
clearSelection();
repaint();
}else{
int index = locationToIndex(e.getPoint());
MyIcon icon = (MyIcon)getModel().getElementAt(index);
Rectangle rect = getCellBounds(index,index);
if(!rect.contains(e.getPoint())) {
clearSelection();
repaint();
}
}
}
});
}
public void paint(Graphics g) {
super.paint(g);
if(srcPoint==null) return;
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(SystemColor.activeCaption);
g2d.drawPolygon(polygon);
g2d.setComposite(alcomp);
g2d.setColor(pcolor);
g2d.fillPolygon(polygon);
}
private int[] getIntersectsIcons(Shape p) {
ListModel model = getModel();
Vector list = new Vector(model.getSize());
for(int i=0;i<model.getSize();i++) {
Rectangle r = MyList.this.getCellBounds(i,i);
if(p.intersects(r)) {
list.add(new Integer(i));
}
}
int[] il = new int[list.size()];
for(int i=0;i<list.size();i++) {
il[i] = ((Integer)list.get(i)).intValue();
}
return il;
}
private Color makeColor() {
int r = SystemColor.activeCaption.getRed();
int g = SystemColor.activeCaption.getGreen();
int b = SystemColor.activeCaption.getBlue();
if(r>g) {
if(r>b) {
return new Color(r,0,0);
}else{
return new Color(0,0,b);
}
}else{
if(g>b) {
return new Color(0,g,0);
}else{
return new Color(0,0,b);
}
}
}
}
@Override protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (renderer != null && renderer.polygon != null) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setPaint(getSelectionBackground());
g2.draw(renderer.polygon);
g2.setComposite(ALPHA);
g2.setPaint(polygonColor);
g2.fill(renderer.polygon);
g2.dispose();
}
}
#spanadd
}
#spanend
#spanadd
View in GitHub: Java, Kotlin- &jnlp;
- &jar;
- &zip;
解説
上記のサンプルでは、JList
にマウスリスナーを設定してドラッグに応じた矩形を描画しています。
解説
JListにマウスリスナを設定して、ドラッグに応じて矩形を描画しています。このとき、その矩形の内部にアイテムアイコンが重なる場合は、それを選択状態に変更しています。選択範囲が矩形にならずに直線になっている場合は、別途その直線と交差するアイテムを選択するようにしています。-
JList
内のアイテムの配置はJList#setLayoutOrientation(JList.HORIZONTAL_WRAP)
メソッドを使っているため水平方向で整列される - ラバーバンド矩形内部に重なるアイテムアイコンを検索しそれを
JList#setSelectedIndices(int[])
で選択状態に変更-
選択範囲が矩形にならずに直線になっている場合は別途その直線と交差するアイテムを選択Polygon
ではなくPath2D
を使用することでこれを回避 -
JDK 1.8.0
以降なら以下をl.setSelectedIndices(IntStream.range(0, l.getModel().getSize()).filter(i -> p.intersects(l.getCellBounds(i, i))).toArray());
で置き換え可能
-
#spanend
#spanadd
private int[] getIntersectsIcons(JList l, Shape p) {
#spanend
ListModel model = l.getModel();
List<Integer> list = new ArrayList<>(model.getSize());
for (int i = 0; i < model.getSize(); i++) {
Rectangle r = l.getCellBounds(i, i);
if (p.intersects(r)) {
list.add(i);
}
}
// JDK 1.8.0以降のstreamでList<Integer>をプリミティブなint配列に変換:
// return list.stream().mapToInt(i -> i).toArray();
int[] il = new int[list.size()];
for (int i = 0; i < list.size(); i++) {
il[i] = list.get(i);
}
return il;
#spanadd
}
#spanend
#spanadd
参考リンク
- Java Technology Forums - Can someone optimise the following code ?
- XP Style Icons - Windows Application Icon, Software XP Icons
参考リンク
- Swing - Can someone optimise the following code ?
- XP Style Icons - Download
- JListのアイテムをラバーバンドで複数選択、ドラッグ&ドロップで並べ替え
- このラバーバンドで選択したアイテムを実際にドラッグして並べ替えるサンプル