你能让 JToolBar 不可分离吗?
Can you make a JToolBar undetachable?
我想让我的 JToolBar 无法与其容器分离,但仍然让用户将它拖到容器的一侧。
我知道
public void setFloatable( boolean b )
但这根本不允许用户移动 JToolBar。
有没有什么方法可以在不覆盖 ToolBarUI 的情况下做到这一点?
此外,是否有一个选项可以在删除它之前突出显示它的新位置?
- 我在 WinOS 上工作得很好,来自 SunForum 的旧代码
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);
}
}
}
这不是最优雅的解决方案,但它确实有效。
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 完成创建浮动 window 的过程,然后你才能告诉它不要浮动。结果是您实际上看到 window 创建然后隐藏。
注:
我认为重写工具栏的 UI 是一个更好的解决方案,尽管使用更复杂的方法执行与我所做的类似的事情也可能会很好。
我想让我的 JToolBar 无法与其容器分离,但仍然让用户将它拖到容器的一侧。
我知道
public void setFloatable( boolean b )
但这根本不允许用户移动 JToolBar。
有没有什么方法可以在不覆盖 ToolBarUI 的情况下做到这一点?
此外,是否有一个选项可以在删除它之前突出显示它的新位置?
- 我在 WinOS 上工作得很好,来自 SunForum 的旧代码
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);
}
}
}
这不是最优雅的解决方案,但它确实有效。
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 完成创建浮动 window 的过程,然后你才能告诉它不要浮动。结果是您实际上看到 window 创建然后隐藏。
注:
我认为重写工具栏的 UI 是一个更好的解决方案,尽管使用更复杂的方法执行与我所做的类似的事情也可能会很好。