用 JLayer 装饰滚动工具栏按钮绘制其边框
Decorating a rollover toolbar button with JLayer paints its border
我正在尝试用 JLayer
包裹 JButton
以向其中添加一些 effects/functionality。当我用工具栏中的包装器替换按钮时,它会出于某种原因绘制按钮边框。工具栏的翻转设置为 true
。
为什么会发生这种情况,我该如何预防?
import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLayer;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.plaf.LayerUI;
public class JLayerButton extends JFrame {
private JToolBar toolbar;
private JButton button1;
private JButton button2;
private JButton button3;
public JLayerButton() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle("JLayer Button");
setLayout(new BorderLayout());
toolbar = new JToolBar();
toolbar.setFloatable(false);
toolbar.setRollover(true);
getContentPane().add(toolbar, BorderLayout.NORTH);
button1 = new JButton("One");
button1.setFocusable(false);
toolbar.add(button1);
button2 = new JButton("Two");
button2.setFocusable(false);
toolbar.add(button2);
button3 = new JButton("Three");
button3.setFocusable(false);
toolbar.add(button3);
// wrap button2 in JLayer
int componentIndex = toolbar.getComponentIndex(button2);
JButtonLayerUI layerUI = new JButtonLayerUI();
JLayer<JButton> layer = new JLayer<JButton>(button2, layerUI);
layer.setLayerEventMask(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
layer.setFocusable(false);
toolbar.add(layer, componentIndex);
setSize(300, 200);
setLocationRelativeTo(null);
}
public static void main(String[] args)
throws ClassNotFoundException, InstantiationException,
IllegalAccessException, UnsupportedLookAndFeelException {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new JLayerButton().setVisible(true);
}
});
}
private static class JButtonLayerUI extends LayerUI<JButton> {
public JButtonLayerUI() {
}
@Override
public void paint(Graphics g, JComponent c) {
super.paint(g, c);
}
@Override
protected void processMouseEvent(MouseEvent e, JLayer<? extends JButton> l) {
onMouseEvent(l, e);
}
@Override
protected void processMouseMotionEvent(MouseEvent e, JLayer<? extends JButton> l) {
onMouseEvent(l, e);
}
private void onMouseEvent(JLayer<? extends JButton> l, MouseEvent e) {
System.out.println(e);
}
}
}
使用 JLayer
似乎无法实现您想实现的目标,因为 :
从BasicToolBarUI
的代码中,我们可以看到那些调用
调用 installRolloverBorders
以在 JToolBar
上安装边框:
public void setRolloverBorders( boolean rollover ) {
rolloverBorders = rollover;
if ( rolloverBorders ) {
installRolloverBorders( toolBar );
} else {
installNonRolloverBorders( toolBar );
}
}
installRolloverBorders
在工具栏的每个 direct JComponent
childs(非递归)上调用 setBorderToRollover
protected void installRolloverBorders ( JComponent c ) {
// Put rollover borders on buttons
Component[] components = c.getComponents();
for (Component component : components) {
if (component instanceof JComponent) {
((JComponent) component).updateUI();
setBorderToRollover(component);
}
}
}
最后,setBorderToRollover
仅适用于 AbstractButton
的实例,而您的 JLayer
则无效。所以你的 JLayer 按钮的原始边框根本不受影响。
protected void setBorderToRollover(Component c) {
if (c instanceof AbstractButton) {
AbstractButton b = (AbstractButton)c;
Border border = borderTable.get(b);
if (border == null || border instanceof UIResource) {
borderTable.put(b, b.getBorder());
}
// Only set the border if its the default border
if (b.getBorder() instanceof UIResource) {
b.setBorder(getRolloverBorder(b));
}
rolloverTable.put(b, b.isRolloverEnabled()?
Boolean.TRUE: Boolean.FALSE);
b.setRolloverEnabled(true);
}
}
总而言之,rollover 效果仅适用于满足这两个条件的组件:
- 成为 直接 child 的
JToolBar
- 成为
AbstractButton
的实例
您可能可以推出自己的 BasicToolBarUI
版本并覆盖一些方法以添加递归性,例如,看看是否值得花时间。
我正在尝试用 JLayer
包裹 JButton
以向其中添加一些 effects/functionality。当我用工具栏中的包装器替换按钮时,它会出于某种原因绘制按钮边框。工具栏的翻转设置为 true
。
为什么会发生这种情况,我该如何预防?
import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLayer;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.plaf.LayerUI;
public class JLayerButton extends JFrame {
private JToolBar toolbar;
private JButton button1;
private JButton button2;
private JButton button3;
public JLayerButton() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle("JLayer Button");
setLayout(new BorderLayout());
toolbar = new JToolBar();
toolbar.setFloatable(false);
toolbar.setRollover(true);
getContentPane().add(toolbar, BorderLayout.NORTH);
button1 = new JButton("One");
button1.setFocusable(false);
toolbar.add(button1);
button2 = new JButton("Two");
button2.setFocusable(false);
toolbar.add(button2);
button3 = new JButton("Three");
button3.setFocusable(false);
toolbar.add(button3);
// wrap button2 in JLayer
int componentIndex = toolbar.getComponentIndex(button2);
JButtonLayerUI layerUI = new JButtonLayerUI();
JLayer<JButton> layer = new JLayer<JButton>(button2, layerUI);
layer.setLayerEventMask(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
layer.setFocusable(false);
toolbar.add(layer, componentIndex);
setSize(300, 200);
setLocationRelativeTo(null);
}
public static void main(String[] args)
throws ClassNotFoundException, InstantiationException,
IllegalAccessException, UnsupportedLookAndFeelException {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new JLayerButton().setVisible(true);
}
});
}
private static class JButtonLayerUI extends LayerUI<JButton> {
public JButtonLayerUI() {
}
@Override
public void paint(Graphics g, JComponent c) {
super.paint(g, c);
}
@Override
protected void processMouseEvent(MouseEvent e, JLayer<? extends JButton> l) {
onMouseEvent(l, e);
}
@Override
protected void processMouseMotionEvent(MouseEvent e, JLayer<? extends JButton> l) {
onMouseEvent(l, e);
}
private void onMouseEvent(JLayer<? extends JButton> l, MouseEvent e) {
System.out.println(e);
}
}
}
使用 JLayer
似乎无法实现您想实现的目标,因为 :
从BasicToolBarUI
的代码中,我们可以看到那些调用
installRolloverBorders
以在 JToolBar
上安装边框:
public void setRolloverBorders( boolean rollover ) {
rolloverBorders = rollover;
if ( rolloverBorders ) {
installRolloverBorders( toolBar );
} else {
installNonRolloverBorders( toolBar );
}
}
installRolloverBorders
在工具栏的每个 direct JComponent
childs(非递归)上调用 setBorderToRollover
protected void installRolloverBorders ( JComponent c ) {
// Put rollover borders on buttons
Component[] components = c.getComponents();
for (Component component : components) {
if (component instanceof JComponent) {
((JComponent) component).updateUI();
setBorderToRollover(component);
}
}
}
最后,setBorderToRollover
仅适用于 AbstractButton
的实例,而您的 JLayer
则无效。所以你的 JLayer 按钮的原始边框根本不受影响。
protected void setBorderToRollover(Component c) {
if (c instanceof AbstractButton) {
AbstractButton b = (AbstractButton)c;
Border border = borderTable.get(b);
if (border == null || border instanceof UIResource) {
borderTable.put(b, b.getBorder());
}
// Only set the border if its the default border
if (b.getBorder() instanceof UIResource) {
b.setBorder(getRolloverBorder(b));
}
rolloverTable.put(b, b.isRolloverEnabled()?
Boolean.TRUE: Boolean.FALSE);
b.setRolloverEnabled(true);
}
}
总而言之,rollover 效果仅适用于满足这两个条件的组件:
- 成为 直接 child 的
JToolBar
- 成为
AbstractButton
的实例
您可能可以推出自己的 BasicToolBarUI
版本并覆盖一些方法以添加递归性,例如,看看是否值得花时间。