我想让我的JToolBar无法从其容器中分离,但仍然允许用户将其拖到容器的一侧。
我知道
public void setFloatable( boolean b )
但这根本不允许用户移动JToolBar。
有没有办法在不覆盖ToolBarUI的情况下这样做?
此外,是否可以选择在放弃之前突出显示新位置?
答案 0 :(得分:2)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class CaptiveToolBar {
private Robot robot;
private JDialog dialog;
private JFrame frame;
public static void main(String[] args) {
//JFrame.setDefaultLookAndFeelDecorated(true);
//JDialog.setDefaultLookAndFeelDecorated(true);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new CaptiveToolBar().makeUI();
}
});
}
public void makeUI() {
try {
robot = new Robot();
} catch (AWTException ex) {
ex.printStackTrace();
}
final JToolBar toolBar = new JToolBar();
for (int i = 0; i < 3; i++) {
toolBar.add(new JButton("" + i));
}
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setLocationRelativeTo(null);
frame.add(toolBar, BorderLayout.NORTH);
final ComponentListener dialogListener = new ComponentAdapter() {
@Override
public void componentMoved(ComponentEvent e) {
dialog = (JDialog) e.getSource();
setLocations(false);
}
};
toolBar.addHierarchyListener(new HierarchyListener() {
@Override
public void hierarchyChanged(HierarchyEvent e) {
Window window = SwingUtilities.getWindowAncestor(toolBar);
if (window instanceof JDialog) {
boolean listenerAdded = false;
for (ComponentListener listener : window.getComponentListeners()) {
if (listener == dialogListener) {
listenerAdded = true;
break;
}
}
if (!listenerAdded) {
window.addComponentListener(dialogListener);
}
}
}
});
frame.addComponentListener(new ComponentAdapter() {
@Override
public void componentMoved(ComponentEvent e) {
if (dialog != null && dialog.isShowing()) {
setLocations(true);
}
}
});
frame.setVisible(true);
}
private void setLocations(boolean moveDialog) {
int dialogX = dialog.getX();
int dialogY = dialog.getY();
int dialogW = dialog.getWidth();
int dialogH = dialog.getHeight();
int frameX = frame.getX();
int frameY = frame.getY();
int frameW = frame.getWidth();
int frameH = frame.getHeight();
boolean needToMove = false;
if (dialogX < frameX) {
dialogX = frameX;
needToMove = true;
}
if (dialogY < frameY) {
dialogY = frameY;
needToMove = true;
}
if (dialogX + dialogW > frameX + frameW) {
dialogX = frameX + frameW - dialogW;
needToMove = true;
}
if (dialogY + dialogH > frameY + frameH) {
dialogY = frameY + frameH - dialogH;
needToMove = true;
}
if (needToMove) {
if (!moveDialog && robot != null) {
robot.mouseRelease(InputEvent.BUTTON1_MASK);
}
dialog.setLocation(dialogX, dialogY);
}
}
}
答案 1 :(得分:2)
这不是最优雅的解决方案,但它确实有效。
public class Example extends JFrame {
BasicToolBarUI ui;
Example() {
JToolBar tb = new JToolBar();
tb.add(new JButton("AAAAA"));
tb.setBackground(Color.GREEN);
ui = (BasicToolBarUI) tb.getUI();
getContentPane().addContainerListener(new Listener());
getContentPane().add(tb, BorderLayout.PAGE_START);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(300, 300);
setLocationRelativeTo(null);
setVisible(true);
}
class Listener implements ContainerListener {
@Override
public void componentAdded(ContainerEvent e) {}
@Override
public void componentRemoved(ContainerEvent e) {
if (ui.isFloating()) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
ui.setFloating(false, null);
}
});
}
}
}
public static void main(String[] args) {
new Example();
}
}
每当工具栏移动到浮动状态时,都会指示不这样做。唯一的问题是你必须等待EDT完成创建浮动窗口的过程,然后才能告诉它不要浮动。结果是您实际看到窗口已创建然后隐藏。
我认为覆盖工具栏的UI是一个更好的解决方案,尽管使用更复杂的方法做一些类似于我所做的事情也可能效果很好。