Recently I found out that I can use my images as buttons with mouse listener.
What is the main difference between using buttons and images as buttons. What is the main drawback of this option?
Button:
JButton btnNewButton_1 = new JButton("Button");
btnNewButton_1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
//Do something
}
});
Image:
getJlabel().addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
//Do something
}
});
Although both of them provide similar functionalities, I think that most users are not accustomed to such a thing.
To the average user (in my opinion at least), buttons should be clicked and images should be looked at. It is like the image provides a means to the user to understand and the button provides a means for the user to act.
You could throw in Images in JButtons (as explained here), but that being said, I think that from a User Experience point of view you should not use images as buttons unless you really have to, and when you do, I think that you should include specific instructions.
The JButton provides animation (during clicking and releasing), different looks for different states (like when it's not enabled) and other things one expects from an actual "push button".
You can add the these (or some of these) functionalities to an image according to your requirements using a mouse listener.
It all depends on what you want and how much code are you willing to write by hand.
FYI, the images can be added to JButtons (mainly for the purpose of icons).
Related
Currently the code only hides the JLabel. I'm not sure why it's not making it visible when I click the button again. Hopefully this is an easy fix
contentPane.add(btnSwap);
btnHide.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
lblHello.setVisible(false);
}
});
contentPane.add(btnHide);
btnHide.setBounds(185, 199, 89, 23);
lblHello.setVisible(true);
}
I'm not sure why it's not making it visible when I click the button again.
Why should it, since all the ActionListener does (the code that's called on button press) is to continually set the label invisible?
A solution is to simply toggle its visibility:
lblHello.setVisible(!lblHello.isVisible());
Note that to be safe, it's best to revalidate and repaint the container after making such changes, so:
btnHide.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
lblHello.setVisible(!lblHello.isVisible());
revalidate();
repaint();
}
});
as this will rid the GUI of "dirty" pixels that can occur from adding and especially from removing visible components.
A word on this:
btnHide.setBounds(185, 199, 89, 23);
This suggests that you're using null layouts with setBounds(...). While this often seems to newbie Swing coders the best way to create complex GUI's, it will come back to haunt them later, since this will mean that the GUI will look OK on one platform and one platform only, and that if later you want to enhance or improve the GUI, it can only be done with much difficulty and risk of bugs. Much better is to learn and use the layout managers.
Another recommendation:
If your desire is to change the appearance of the GUI on button press, then also have a look at the CardLayout (please check the CardLayout Tutorial) as this can be a way to cleanly and easily swap views
And a better recommendation:
Since a JLabel only shows its text or its icon or both, the best way to make it "invisible" is to remove its text and its icon, as noted by Andrew Thompson below:
// get rid of its text
lblHello.setText("");
// and if needed
lblHello.setIcon(null);
This won't work for text components such as JTextFields and JTextAreas or other components that have more "heft" than a JLabel including pretty much all other user-interaction components.
Try :
btnChangeLabelVisibilityButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
lblHello.setVisible(!lblHello.isVisible());
}
});
So I was wondering what is the better looking solution/what are the differences and what are things to think about when making the decision about making either several listeners (1 listener for 1 button) or just 1 ActionListener for all buttons in my GUI (about 10 Buttons) and getting the information about which button was pressed through actionevent.getSource() == buttonname.
What is the better style in your opinion? Is there a disadvantage on creating so many classes for several ActionListeners? Or will it not matter at all?
By the way, in my code im trying to stick to the model-view-controller organization.
I prefer to have different ActionListener classes but grouping them by functional responsibility is a good practice in my experience.
I also suggest you relying on ActionEvent#getActionCommand() over ActionEvent#getSource() because you could handle an equivalent action from different UI components.
JButton button = new JButton("Button");
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
//do your work here.
}
});
This is the way to go for each button.
A long ActionListener interface object with multiple if else or switch statements is both clumsy and hard to maintain.
Additionally, on each button press, the program has to go through a number of matchings to get to know what button was pressed. That is very expensive.
So, one Button ---> one ActionListener is the better way.
I prefer to use lambdas, one per each button, e.g.:
JButton button = new JButton("Button");
button.addActionListener(e -> //do your work here);
I have built a program using Window Builder. I have used various Jbuttons, and would like to display a message such as "click here to add product" when the button is hovered over. I have added an event handler
addButton.addFocusListener(new FocusAdapter() {
#Override
public void focusGained(FocusEvent arg0) {
}
However i am unsure on the code needed within the FocusEvent to allow for this message to be displayed. I have looked at various methods such as MessageBox, but i don't think this is what i have been looking for.
No, don't use FocusListeners for this. Java Swing already has a built in tool for this, tool-tip. You will want to call setToolTipText(...) on your JButtons.
I have written a calculator in NetBeans and it functions perfectly. However, I have to actually click the buttons to insert numbers and am trying to remedy that with a KeyListener. I have all my numbers and function buttons set inside a JPanel named buttons. I have my display label in a JPanel named display.
I set my class to implement KeyListener and it inserted the KeyPressed, -Typed, and -Released methods; however I stuck from there. I'm not sure how to make my buttons actually listen for the KeyPressed event, and when it hears the event - activate the button. Also, my buttons are named by their number (e.g. the Zero Button is named zero, One button is one, etc.).
I've read that you actually have to implement a KeyListener somewhere by using: something.addKeyListener(something);
but I cannot seem to figure this out.
Can I get some help here? I'm new to Java and this is my first solo project. And let me know if I didn't provide enough information.
EDIT: Most of my code is NetBeans Generated and I cannot edit the initialization of the components which seems to be my problem I think?
My class declaration:
public class Calculator extends javax.swing.JFrame implements KeyListener {
//Creates new form Calculator
public Calculator() {
initComponents();
}
One of my buttonPressed actions (all identical with changes for actual number):
private void zeroActionPerformed(java.awt.event.ActionEvent evt) {
if (display.getText().length() >= 16)
{
JOptionPane.showMessageDialog(null, "Cannot Handle > 16 digits");
return;
}
else if (display.getText().equals("0"))
{
return;
}
display.setText(display.getText().concat("0"));
Main method supplied by NetBeans:
public static void main(String args[]) {
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Calculator().setVisible(true);
}
});
}
The initComponents() netbeans generated is absolutely massive (about 500 lines of code) and I cannot edit any of it. Let me know if I can supply any more helpful information.
Could there be an issue of Focus, and if so how can I resolve the issue?
Yes there is probably an issue with focus. That is why you should NOT be using a KeyListener.
Swing was designed to be used with Key Bindings. That is you create an Action that does what you want. Then this Action can be added to your JButton. It can also be bound to a KeyStroke. So you have nice reusable code.
Read the Swing tutorial on How to Use Key Bindings for more information. Key Bindings don't have the focus issue that you currently have.
I'm not sure I completely understand your question, and some code would help, but I'll take a crack, since it sounds like a problem I used to have a lot.
It sounds like the reason that your key presses aren't being recognized is that the focus is on one of the buttons. If you add keylisteners to the buttons, then you shouldn't have any problem.
In netbeans you can add keylisteners through the design screen really easily.
Here's a picture showing you how to add a keyPressed listener to a button in a jPanel.
private void jButton1KeyPressed(java.awt.event.KeyEvent evt) {
//Check which key is pressed
//do whatever you need to do with the keypressed information
}
It is nice to be able to write out the listeners yourself, but if you are just learning, then it is also nice to get as much help as possible.
This might not be the best solution, since you would have to add the listener for each of your buttons.
This may be a stupid question, but I have to ask!
I have the following code snippets that are supposed to run their corresponding methods when the user interacts with objects.
For some reason, "foo" is never printed, but "bar" is.
myJSpinner1.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseEntered(java.awt.event.MouseEvent evt) {
System.out.println("foo"); //"foo" is not printed
}
});
myJSpinner2.addChangeListener(new java.awt.event.ChangeListener() {
public void stateChanged(java.awt.event.ChangeEvent evt) {
System.out.println("bar"); //"bar" is printed
}
});
I get no exceptions or stack trace. What am I missing in the MouseListener one?
Thanks in advance.
EDIT: MouseEntered works perfectly on a JCheckBox implemented in exactly the same way!
JSpinner is a composite component consisting of a text field and 2 buttons. It's possible to add mouse listeners to all of those by iterating over the results of getComponents() and adding a listener to each.
However, in my experience, when something takes that much work, you're probably going about it the wrong way.
Why do you need the mouse-entered information for a JSpinner?
What do you want to do with this event?
Update:
If you're looking to supply information about all of the controls in your panel, you may want to look at using a glasspane to detect the component under the mouse.
A Well-behaved Glasspane by Alexander Potochkin is a good place to start.
This is a guess but I suspect you need to add a MouseListener to the JSpinner's editor (via a call to getEditor()). I imagine that the editor Component occupies all available space within the JSpinner and is therefore intercepting all MouseEvents.
This worked for me.
JSpinner spinner = new JSpinner();
((JSpinner.DefaultEditor)spinner.getEditor()).getTextField().addMouseListener(
new java.awt.event.MouseAdapter() {
public void mouseClicked(final MouseEvent e) {
// add code here
}
});
I needed this in order to evoke a popup key dialog for added usability due to our software requirements.
Aditional to #Rapier answer...
If you change the Spinner using something like
yourOldSpinner = new JSpinner(new SpinnerModel(...))
you will lost your previosly MouseListener...
If you need to change something of SpinnerModel, Don't create a new, change its parameters instead! (if you do it, you will need to reassign the MouseListener again, because it will be lost when you assign a new SpinnerModel).
an example (I'm talking...):
((SpinnerNumberModel)yourOldSpinner.getModel()).setValue(size/3);
((SpinnerNumberModel)yourOldSpinner.getModel()).setMinimum(0);
((SpinnerNumberModel)yourOldSpinner.getModel()).setMaximum(isize/2);
((SpinnerNumberModel)yourOldSpinner.getModel()).setStepSize(1);