Swing/DnDLayerTabbedPane のバックアップの現在との差分(No.3)
TITLE:JLayerを使ってJTabbedPaneのタブの挿入位置を描画する
Posted by aterai at 2012-01-23
JLayerを使ってJTabbedPaneのタブの挿入位置を描画する
JLayerを使って、タブのドラッグ&ドロップでの移動先をJTabbedPane上に描画します。-
category: swing
folder: DnDLayerTabbedPane
title: JLayerを使ってJTabbedPaneのタブの挿入位置を描画する
tags: [JLayer, JTabbedPane, DragAndDrop, TransferHandler, JWindow, JLabel]
author: aterai
pubdate: 2012-01-23T18:01:31+09:00
description: JLayerを使って、タブのドラッグ&ドロップでの移動先をJTabbedPane上に描画します。
image:
hreflang:
href: https://java-swing-tips.blogspot.com/2012/01/sharing-tabs-between-2-jframes.html lang: en
概要
JLayer
を使って、タブのドラッグ&ドロップでの移動先をJTabbedPane
上に描画します。
- &jnlp;
- &jar;
- &zip;
Screenshot
Advertisement
サンプルコード
#spanend
#spanadd
* サンプルコード [#sourcecode]
#spanend
#spanadd
#code(link){{
#spanend
class DropLocationLayerUI extends LayerUI<DnDTabbedPane> {
private static final int LINEWIDTH = 3;
private final Rectangle lineRect = new Rectangle();
@Override public void paint(Graphics g, JComponent c) {
super.paint (g, c);
JLayer layer = (JLayer)c;
DnDTabbedPane tabbedPane = (DnDTabbedPane)layer.getView();
DnDTabbedPane.DropLocation loc = tabbedPane.getDropLocation();
if(loc != null && loc.isDropable() && loc.getIndex()>=0) {
int index = loc.getIndex();
boolean isZero = index==0;
Rectangle r = tabbedPane.getBoundsAt(isZero?0:index-1);
if(tabbedPane.getTabPlacement()==JTabbedPane.TOP ||
tabbedPane.getTabPlacement()==JTabbedPane.BOTTOM) {
lineRect.setRect(
r.x-LINEWIDTH/2+r.width*(isZero?0:1), r.y,LINEWIDTH,r.height);
}else{
lineRect.setRect(
r.x,r.y-LINEWIDTH/2+r.height*(isZero?0:1), r.width,LINEWIDTH);
super.paint(g, c);
if (c instanceof JLayer) {
JLayer layer = (JLayer) c;
DnDTabbedPane tabbedPane = (DnDTabbedPane) layer.getView();
DnDTabbedPane.DropLocation loc = tabbedPane.getDropLocation();
if (loc != null && loc.isDroppable() && loc.getIndex() >= 0) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setComposite(
AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .5f));
g2.setColor(Color.RED);
initLineRect(tabbedPane, loc);
g2.fill(lineRect);
g2.dispose();
}
Graphics2D g2 = (Graphics2D)g.create();
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
g2.setColor(Color.RED);
g2.fill(lineRect);
g2.dispose();
}
}
#spanadd
#spanend
private void initLineRect(JTabbedPane tabbedPane, DnDTabbedPane.DropLocation loc) {
int index = loc.getIndex();
int a = index == 0 ? 0 : 1;
Rectangle r = tabbedPane.getBoundsAt(a * (index - 1));
if (tabbedPane.getTabPlacement() == JTabbedPane.TOP
|| tabbedPane.getTabPlacement() == JTabbedPane.BOTTOM) {
lineRect.setBounds(
r.x - LINE_WIDTH / 2 + r.width * a, r.y, LINE_WIDTH, r.height);
} else {
lineRect.setBounds(
r.x, r.y - LINE_WIDTH / 2 + r.height * a, r.width, LINE_WIDTH);
}
}
}
解説
上記のサンプルでは、JTabbedPaneのタブをドラッグ&ドロップや、JTabbedPane間でタブのドラッグ&ドロップ移動のようにGlassPaneを使用する代わりに、JDK 1.7.0 で導入されたJLayerを使用して、タブの挿入先を描画しています。JLayerを使用することで、別ウィンドウにあるJTabbedPaneへのタブ移動などの描画が簡単にできるようになっています。解説
上記のサンプルでは、JTabbedPaneのタブをドラッグ&ドロップや、JTabbedPane間でタブのドラッグ&ドロップ移動のようにGlassPane
を使用する代わりに、JDK 1.7.0
で導入されたJLayer
を使用してタブの挿入先を描画しています。JLayer
を使用することで別ウィンドウにあるJTabbedPane
へのタブ移動などの描画が簡単になります。
メニューバーから、ドラッグ中の半透明タブイメージの描画方法を切り替えてテストすることができます。
- Lightweight
- JDK1.7.0で導入された、TransferHandler#setDragImage(...)メソッドを使用して描画
- ウインドウの外では非表示 メニューバーからドラッグ中の半透明タブイメージの描画方法を切り替えてテストできます。
- Heavyweight
- 半透明のJWindowにJLabelを追加して表示
- ウインドウの外でも表示可能
- 表示位置のオフセットが(0, 0)の場合、DragOverイベントが元のJFrameに伝わらない?
- オフセットが(0, 0)でも、JLabel#contains(...)が常にfalseなら問題なし
-
Lightweight
-
JDK1.7.0
で導入された、TransferHandler#setDragImage(...)
メソッドを使用して描画 - ウィンドウの外部では非表示
-
-
Heavyweight
- 半透明の
JWindow
にJLabel
を追加して表示 - ウィンドウの外部でも表示可能
- 表示位置のオフセットが
(0, 0)
の場合、DragOver
イベントが元のJFrame
に伝わらない?- オフセットが
(0, 0)
でも、JLabel#contains(...)
が常にfalse
なら問題なし
- オフセットが
- 半透明の
private final JLabel label = new JLabel() {
@Override public boolean contains(int x, int y) {
return false;
}
};
private final JWindow dialog = new JWindow();
public TabTransferHandler() {
dialog.add(label);
//dialog.setAlwaysOnTop(true); // Web Start
dialog.setOpacity(0.5f);
//com.sun.awt.AWTUtilities.setWindowOpacity(dialog, 0.5f); // JDK 1.6.0
// dialog.setAlwaysOnTop(true); // Web Start
dialog.setOpacity(.5f);
// com.sun.awt.AWTUtilities.setWindowOpacity(dialog, .5f); // JDK 1.6.0
DragSource.getDefaultDragSource().addDragSourceMotionListener(
new DragSourceMotionListener() {
@Override public void dragMouseMoved(DragSourceDragEvent dsde) {
Point pt = dsde.getLocation();
pt.translate(5, 5); // offset
dialog.setLocation(pt);
}
});
#spandel
//...
#spanend
#spanadd
// ...
#spanend
参考リンク
参考リンク
- JTabbedPaneのタブをドラッグ&ドロップ
- JTabbedPane間でタブのドラッグ&ドロップ移動
- Free the pixel: GHOST drag and drop, over multiple windows