Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

JToolbar style for icon JButton

143 views
Skip to first unread message

Albert

unread,
Oct 21, 2009, 9:40:29 AM10/21/09
to
When putting a JButton with an icon (and no text) on a JToolbar, the
button has no (big, winXP) border, has a rollover, a pretty focus. Is it
possible to get these features for a JButton in a JPanel ?

Steve W. Jackson

unread,
Oct 21, 2009, 9:47:45 AM10/21/09
to
In article <4adf0f46$0$975$ba4a...@news.orange.fr>,
Albert <alb...@voila.fr> wrote:

Look at the JToolBar for isRollover and setRollover, which I'm pretty
sure handle that part for you. The rest should be available in JButton
and its super classes.
--
Steve W. Jackson
Montgomery, Alabama

Albert

unread,
Oct 22, 2009, 5:03:05 AM10/22/09
to
Le 21/10/2009 15:47, Steve W. Jackson a �crit :

JToolBar.setRollover just change a client property of itself:
"JToolBar.isRollover".

WindowsToolBarUI in XP style, seems to set empty borders for rollover.

Java coder

unread,
Nov 26, 2009, 4:08:33 PM11/26/09
to
Albert a �crit :

Here is a try at it. I don't there's a ultimate solution, but this a
good base:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;

import javax.swing.AbstractButton;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import javax.swing.LookAndFeel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.border.AbstractBorder;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.ButtonUI;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicButtonUI;

public class RolloverButtonDemo implements Runnable {

public static void main(String[] args) {
EventQueue.invokeLater(new RolloverButtonDemo());
}

private static class SimpleBorder extends AbstractBorder {
private boolean raised;
public SimpleBorder(boolean raised) {
this.raised = raised;
}

public Insets getBorderInsets(Component c) {
Insets insets = new Insets(1, 1, 1, 1);
return insets;
}

public boolean isBorderOpaque() {
return true;
}

public void paintBorder(Component c, Graphics g, int x, int y,
int width, int height) {
super.paintBorder(c, g, x, y, width, height);
Color b = new Color(220, 220, 220);
Color d = c.getBackground().darker();
if (!raised) {
Color tmp = b;
b = d;
d = tmp;
}

g.setColor(b);
int right = x+width-1;
int bottom = y+height-1;
g.drawLine(x, y, right, y); // up
g.drawLine(x, y, x, bottom); // left
g.setColor(d);
g.drawLine(x, bottom, right, bottom); // bottom
g.drawLine(right, y, right, bottom); // right
}
}

private static class RolloverButton extends JButton implements
MouseListener, ChangeListener {
private Border defaultBorder;
private Border rolloverBorder;
private Border pressedBorder;

public RolloverButton(Icon icon) {
super(icon);

init();
}

public RolloverButton(String s, ImageIcon icon) {
super(s, icon);

init();
}

private void init() {
// the UI should not set its border or paint, we handle it
setRolloverEnabled(false);
setFocusPainted(false);
setContentAreaFilled(false);

defaultBorder = new EmptyBorder(4, 4, 4, 4);

Border lowBorder = new SimpleBorder(false);
Border raisedBorder = new SimpleBorder(true);

rolloverBorder = BorderFactory.createCompoundBorder(raisedBorder,
new EmptyBorder(3, 3, 3, 3));
pressedBorder = BorderFactory.createCompoundBorder(lowBorder, new
EmptyBorder(3, 3, 3, 3));
setBorder(defaultBorder);

addMouseListener(this);
addChangeListener(this);
}


public void mouseClicked(MouseEvent arg0) {

}

public void mouseEntered(MouseEvent evt) {
setBorder(rolloverBorder);
}

public void mouseExited(MouseEvent arg0) {
setBorder(defaultBorder);
}

public void mousePressed(MouseEvent arg0) {
if (isEnabled())
setBorder(pressedBorder);
}

public void mouseReleased(MouseEvent evt) {
boolean interact = isDisplayable() && isVisible();
if (interact && contains(evt.getPoint()))
setBorder(rolloverBorder);
else
setBorder(defaultBorder);
}

public void stateChanged(ChangeEvent evt) {
Point pt = MouseInfo.getPointerInfo().getLocation();
SwingUtilities.convertPointFromScreen(pt, this);

boolean interact = isDisplayable() && isVisible();
if (interact && (getModel().isArmed() || getModel().isPressed()))
setBorder(pressedBorder);
else if (interact && (hasFocus() || contains(pt)))
setBorder(rolloverBorder);
else
setBorder(defaultBorder);
}
}

private static class RolloverButtonUI extends BasicButtonUI
implements MouseListener, KeyListener {

private final static RolloverButtonUI m_buttonUI = new
RolloverButtonUI();
private EmptyBorder defaultBorder;
private CompoundBorder rolloverBorder;
private CompoundBorder pressedBorder;

private RolloverButtonUI() {
defaultBorder = new EmptyBorder(4, 4, 4, 4);

Border lowBorder = new SimpleBorder(false);
Border raisedBorder = new SimpleBorder(true);

rolloverBorder = BorderFactory.createCompoundBorder(raisedBorder,
new EmptyBorder(3, 3, 3, 3));
pressedBorder = BorderFactory.createCompoundBorder(lowBorder, new
EmptyBorder(3, 3, 3, 3));
}

public static ComponentUI createUI(JComponent c) {
return m_buttonUI;
}

public void installUI(JComponent c) {
super.installUI(c);

c.addMouseListener(this);
c.addKeyListener(this);
}

// some parts are copied from super
protected void installDefaults(AbstractButton b) {
// load shared instance defaults
String pp = getPropertyPrefix();

defaultTextShiftOffset = UIManager.getInt(pp + "textShiftOffset");

LookAndFeel.installProperty(b,
JButton.CONTENT_AREA_FILLED_CHANGED_PROPERTY, Boolean.FALSE);
LookAndFeel.installProperty(b, "opaque", Boolean.FALSE);
LookAndFeel.installProperty(b,
JButton.ROLLOVER_ENABLED_CHANGED_PROPERTY, Boolean.TRUE);

b.setFocusPainted(false);
b.setBorder(defaultBorder);
}

public void uninstallUI(JComponent c) {
super.uninstallUI(c);

c.setBorder(defaultBorder);
c.removeMouseListener(this);
c.removeKeyListener(this);
}

public void mouseClicked(MouseEvent e) {
}

public void mousePressed(MouseEvent e) {
JComponent c = (JComponent) e.getComponent();
if (c.isEnabled())
c.setBorder(pressedBorder);
}

public void mouseReleased(MouseEvent evt) {
JComponent c = (JComponent) evt.getComponent();
boolean interact = c.isDisplayable() && c.isVisible();
if (interact && c.contains(evt.getPoint()))
c.setBorder(rolloverBorder);
else
c.setBorder(defaultBorder);
}

public void mouseEntered(MouseEvent e) {
JComponent c = (JComponent) e.getComponent();
c.setBorder(rolloverBorder);
c.repaint();
}

public void mouseExited(MouseEvent e) {
JComponent c = (JComponent) e.getComponent();
c.setBorder(defaultBorder);
c.repaint();
}

public void keyTyped(KeyEvent e) {
}

public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if (code == KeyEvent.VK_ENTER || code == KeyEvent.VK_SPACE) {
JComponent c = (JComponent) e.getComponent();
c.setBorder(pressedBorder);
}
}

public void keyReleased(KeyEvent e) {
int code = e.getKeyCode();
if (code == KeyEvent.VK_ENTER || code == KeyEvent.VK_SPACE) {
JComponent c = (JComponent) e.getComponent();
c.setBorder(rolloverBorder);
}
}

}

/** A normal JButton except it forces its UI */
private static class RolloverButtonWithUI extends JButton {
private static RolloverButtonUI myUI = new RolloverButtonUI();

public RolloverButtonWithUI(Icon icon) {
super(icon);
init();
}

public RolloverButtonWithUI(String s, ImageIcon icon) {
super(s, icon);
init();
}

private void init() {
setOpaque(false);
super.setUI(myUI);
}

@Override
public void setUI(ButtonUI ui) {
myUI.uninstallUI(this);
// font, etc.
super.setUI(ui);
myUI.installUI(this);
}

@Override
public ButtonUI getUI() {
return myUI;
}
}

public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setJMenuBar(createMenuBar(frame));

JPanel flowPanel = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.gridy = 0;
flowPanel.add(new JLabel("JButton"), c);
JButton bt = new JButton(genIcon(16, 16, Color.red));
flowPanel.add(bt, c);
JButton bt2 = new JButton("click", genIcon(16, 16, Color.red));
flowPanel.add(bt2, c);
JButton bt3 = new JButton("click", genIcon(16, 16, Color.red));
bt3.setEnabled(false);
flowPanel.add(bt3, c);

c.gridy = 1;
flowPanel.add(new JLabel("RolloverButton"), c);
RolloverButton mybt = new RolloverButton(genIcon(16, 16, Color.blue));
flowPanel.add(mybt, c);
RolloverButton mybt2 = new RolloverButton("click", genIcon(16, 16,
Color.blue));
flowPanel.add(mybt2, c);
RolloverButton mybt3 = new RolloverButton("click", genIcon(16, 16,
Color.blue));
mybt3.setEnabled(false);
flowPanel.add(mybt3, c);

c.gridy = 2;
flowPanel.add(new JLabel("RolloverButtonWithUI"), c);
RolloverButtonWithUI btui = new RolloverButtonWithUI(genIcon(16,
16, Color.green));
flowPanel.add(btui, c);
RolloverButtonWithUI btui2 = new RolloverButtonWithUI("click",
genIcon(16, 16, Color.green));
flowPanel.add(btui2, c);
RolloverButtonWithUI btui3 = new RolloverButtonWithUI("click",
genIcon(16, 16, Color.green));
btui3.setEnabled(false);
flowPanel.add(btui3, c);

frame.getContentPane().add(flowPanel, BorderLayout.CENTER);
frame.getContentPane().add(createToolbar(), BorderLayout.NORTH);

frame.setSize(600, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}

private JToolBar createToolbar() {
JToolBar tb = new JToolBar();
JButton bt = new JButton(genIcon(16, 16, Color.red));
tb.add(bt);
JButton bt2 = new JButton("click", genIcon(16, 16, Color.red));
tb.add(bt2);
JButton bt3 = new JButton("click", genIcon(16, 16, Color.red));
bt3.setEnabled(false);
tb.add(bt3);

RolloverButton mybt = new RolloverButton(genIcon(16, 16, Color.blue));
tb.add(mybt);
RolloverButton mybt2 = new RolloverButton("click", genIcon(16, 16,
Color.blue));
tb.add(mybt2);
RolloverButton mybt3 = new RolloverButton("click", genIcon(16, 16,
Color.blue));
mybt3.setEnabled(false);
tb.add(mybt3);

RolloverButtonWithUI btui = new RolloverButtonWithUI(genIcon(16,
16, Color.green));
tb.add(btui);
RolloverButtonWithUI btui2 = new RolloverButtonWithUI("click",
genIcon(16, 16, Color.green));
tb.add(btui2);
RolloverButtonWithUI btui3 = new RolloverButtonWithUI("click",
genIcon(16, 16, Color.green));
btui3.setEnabled(false);
tb.add(btui3);

return tb;
}

private ImageIcon genIcon(int w, int h, Color c) {
BufferedImage bi = new BufferedImage(w, h,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = bi.createGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(new Color(0, 0, 0, 0));
g.fillRect(0, 0, w, h);
g.setColor(c);
g.fillOval(0, 0, w, h);
g.dispose();
return new ImageIcon(bi);
}

private JMenuBar createMenuBar(final JFrame frame) {
JMenuBar mb = new JMenuBar();
JMenu menu = new JMenu("Lafs");
LookAndFeelInfo[] infos = UIManager.getInstalledLookAndFeels();
for (final LookAndFeelInfo info : infos) {
JMenuItem item = new JMenuItem(info.getName());
item.setToolTipText(info.getClassName());
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
try {
UIManager.setLookAndFeel(info.getClassName());
SwingUtilities.updateComponentTreeUI(frame);
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
menu.add(item);
}
mb.add(menu);
return mb;
}

}

Christian Kaufhold

unread,
Nov 30, 2009, 7:02:05 AM11/30/09
to
Java coder <cod...@servyahoo.fr> wrote:

> private static class SimpleBorder extends AbstractBorder {
> private boolean raised;
> public SimpleBorder(boolean raised) {
> this.raised = raised;
> }
>
> public Insets getBorderInsets(Component c) {
> Insets insets = new Insets(1, 1, 1, 1);
> return insets;
> }

If you subclass AbstractBorder, you must also override
getBorderInsets(Component,Insets)


> // the UI should not set its border or paint, we handle it
> setRolloverEnabled(false);

Why do not use the default rollover mechanism instead of a half-baked
own attempt?

> rolloverBorder = BorderFactory.createCompoundBorder(raisedBorder,
> new EmptyBorder(3, 3, 3, 3));
> pressedBorder = BorderFactory.createCompoundBorder(lowBorder, new
> EmptyBorder(3, 3, 3, 3));
> setBorder(defaultBorder);

There is no need to exchange Borders, you can set one Border that paints
itself differently depending on the button state. There is also no need to
subclass JButton.

Albert

unread,
Nov 30, 2009, 9:38:21 AM11/30/09
to
Le 30/11/2009 13:02, Christian Kaufhold a �crit :

> Java coder<cod...@servyahoo.fr> wrote:
>
>> private static class SimpleBorder extends AbstractBorder {
>> private boolean raised;
>> public SimpleBorder(boolean raised) {
>> this.raised = raised;
>> }
>>
>> public Insets getBorderInsets(Component c) {
>> Insets insets = new Insets(1, 1, 1, 1);
>> return insets;
>> }
>
> If you subclass AbstractBorder, you must also override
> getBorderInsets(Component,Insets)

Yes. It was working but it's better to add it anyway.

>
>
>> // the UI should not set its border or paint, we handle it
>> setRolloverEnabled(false);
>
> Why do not use the default rollover mechanism instead of a half-baked
> own attempt?

Half-baked your-self ! It is working for icon only JButton, and that's
what i need, since under Win 2003, or under XP with classic Styles (!=
XPStyle), there is no rollover at all, and i want some.

>> rolloverBorder = BorderFactory.createCompoundBorder(raisedBorder,
>> new EmptyBorder(3, 3, 3, 3));
>> pressedBorder = BorderFactory.createCompoundBorder(lowBorder, new
>> EmptyBorder(3, 3, 3, 3));
>> setBorder(defaultBorder);
>
> There is no need to exchange Borders, you can set one Border that paints
> itself differently depending on the button state. There is also no need to
> subclass JButton.

Well too late for my program. But thanks for the tip.

Christian Kaufhold

unread,
Nov 30, 2009, 6:02:35 PM11/30/09
to
Albert <alb...@voila.fr> wrote:

>>> // the UI should not set its border or paint, we handle it
>>> setRolloverEnabled(false);
>>
>> Why do not use the default rollover mechanism instead of a half-baked
>> own attempt?
>
> Half-baked your-self ! It is working for icon only JButton, and that's
> what i need, since under Win 2003, or under XP with classic Styles (!=
> XPStyle), there is no rollover at all, and i want some.

You mean to say that even if you do setRolloverEnabled(true), the rollover property
of the button model is not updated? I don't believe that.

Your combined MouseListener/ChangeListener has *numerous* problems, here are three:
* Multiple mouse buttons can be pressed, and you cancel the the pressedBorder on
the first release, even though another button may still be pressed.
* Your check contains() will give wrong positives if the button is covered by
another component or window.
* In stateChanged(), you set the rolloverBorder also if the component has focus.
/Of course/ this means that you need a FocusListener to update if the component
loses focus or gets focus without stateChanged() being called. (Similar for the
checks isDisplayable() and isVisible()).

Albert

unread,
Dec 1, 2009, 4:53:10 AM12/1/09
to
Le 01/12/2009 00:02, Christian Kaufhold a �crit :

> Your combined MouseListener/ChangeListener has *numerous* problems, here are three:
> * Multiple mouse buttons can be pressed, and you cancel the the pressedBorder on
> the first release, even though another button may still be pressed.

Yes, now i check for button1 only in pressed, and isArmed/isPressed in
released.

> * Your check contains() will give wrong positives if the button is covered by
> another component or window.

I tried with a JDialog and a JFrame and it work as expected. I won't use
my button to be covered by another component.

> * In stateChanged(), you set the rolloverBorder also if the component has focus.
> /Of course/ this means that you need a FocusListener to update if the component
> loses focus or gets focus without stateChanged() being called. (Similar for the
> checks isDisplayable() and isVisible()).

Thanks, i added that.

0 new messages