1

I am messing around with some ideas for a side project and I would like to create a GUI using Java swing that doesn't look like it is from Windows95. One of the ideas I was kicking around was to use JLabels as buttons instead of the standard JButton. This would allow me to customize hover, drag, and movement effects as I like.

Research into the MouseAdapter class should allow me to do everything I intend, unfortunately I am having some trouble implementing the hover effect as I wanted as the JLabel does not appear to update. I have tried updating the Frame directly by calling frame.update(getGraphics()); but that does not appear to work as I think it does.

Can I get some advice on how to update the label properly.

Note: This is just an example with no effort put in to organize the code efficiently

public class Window extends JFrame {
    /**
     * 
     */
    private static final long serialVersionUID = 5259700796854880162L;
    private JTextField textField;
    private JLabel lblNewLabel;
    static Window frame;
    int i = 0;

    public Window() {

        JPanel panel = new JPanel();
        getContentPane().add(panel, BorderLayout.CENTER);
        panel.setLayout(null);

        lblNewLabel = new JLabel("New label");
        lblNewLabel.setBackground(Color.LIGHT_GRAY);
        lblNewLabel.setBounds(137, 38, 114, 70);
        panel.add(lblNewLabel);
        lblNewLabel.addMouseListener(new LabelAdapter());

        textField = new JTextField();
        textField.setBounds(122, 119, 86, 20);
        panel.add(textField);
        textField.setColumns(10);

    }

    private class LabelAdapter extends MouseAdapter {
        @Override
        public void mouseClicked(MouseEvent e) {
            textField.setText(String.valueOf(i));
            i++;
        }

        @Override
        public void mouseEntered(MouseEvent e) {
            lblNewLabel.setBackground(Color.CYAN);

        }

        @Override
        public void mouseExited(MouseEvent e) {
            lblNewLabel.setBackground(Color.LIGHT_GRAY);
        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        frame = new Window();

        frame.setSize(900, 700);
        frame.setVisible(true);
    }
}
mKorbel
  • 109,525
  • 20
  • 134
  • 319
JME
  • 2,293
  • 9
  • 36
  • 56
  • JLabel is transparent by default. Consider disabling a buttons content and birder instead... – MadProgrammer Dec 30 '13 at 07:28
  • Refer following Link that helps you [link] http://stackoverflow.com/questions/11678722/how-to-add-jlabel-image-hovering – Darshan Patel Dec 30 '13 at 07:32
  • 1
    Using label components instead of buttons for reasons of fanciness is a bad practice in gui developement. Just think of the folks that prefer a keyboard navigation. All your requirements can be achieved with `JButton` here. – Jens Piegsa Dec 30 '13 at 08:26

2 Answers2

6
  1. Window is reserver name for awt.Window, change this name to e.g. MyWindow

  2. JPanel has implemented FlowLayout, you can't to use NullLayout use built_in LayoutManager, then to use JFrame.pack() before JFrame.setVisible for proper sizing on the screen

  3. JLabel is transparent, change that by using JLabel.setOpaque(true);

  4. refresh of Backgroung Color from Mouse over/hover isn't possible without JLabel.repaint() as last code line in concrete mouse_event, repaint() missing in JLabel API

mKorbel
  • 109,525
  • 20
  • 134
  • 319
3

On top of mKorbel's answer...

I don't know why you're going to so much effort, when you could actually make a button look like a label.

Button or label?

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.ButtonModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class NotALabel {

    public static void main(String[] args) {
        new NotALabel();
    }

    public NotALabel() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                final JButton btn = new JButton("Am I label or a button?");
                btn.setContentAreaFilled(false);
                btn.setBorderPainted(false);
                btn.setFocusPainted(false);
                btn.setOpaque(true);
                btn.getModel().addChangeListener(new ChangeListener() {
                    @Override
                    public void stateChanged(ChangeEvent e) {
                        ButtonModel model = (ButtonModel) e.getSource();
                        if (model.isRollover()) {
                            btn.setBackground(Color.CYAN);
                        } else {
                            btn.setBackground(null);
                        }
                    }
                });

                btn.addActionListener(new ActionListener() {
                    private int count = 0;

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        count++;
                        ((JButton) e.getSource()).setText("I'm a super button!! Or label...");
                    }
                });

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new GridBagLayout());
                frame.add(btn);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

}

You should also consider trying to Setting the look and feel or even possibly Modifying the look and feel

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • This is a very interesting answer as it contains several concepts I have not encountered before. I have been teaching myself the swing package and have been using WindowBuilder to assist with creating GUI's. What is the EventQueue.invokeLater, and why are you using it? – JME Dec 30 '13 at 08:53
  • +1 , but -1k for setBackground(null) instead of woodoo with UIManager, maybe getModel.isRollover is better than (then useless and contraproductive) MouseListener – mKorbel Dec 30 '13 at 08:56
  • @mKorbel What `setBackground(null)`? I agree, the model is probably a better solution, but the best solution would be to use a custom UI delegate ;) – MadProgrammer Dec 30 '13 at 10:41
  • @JME Take a look at [Initial Threads](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html) – MadProgrammer Dec 30 '13 at 10:42
  • JButton.setBackground(null) reseting background to actual L&F arrays of Colors (for JButton) – mKorbel Dec 30 '13 at 10:44
  • @mKorbel Fair point. Think I like the absolute usage of passing it an absolute color. I would have made it transparent, but I would have lost the mouse events ;) – MadProgrammer Dec 30 '13 at 10:50
  • @mKorbel Hopefully that suits your needs better ;) – MadProgrammer Dec 30 '13 at 11:11