I wonder how one should implement an event which will do some Action when a button is pressed, and stop do that action when button is released
I tried to add MouseListerner for this approach. The problem is it will recognize that I have pressed the button. But not which button it is. So wonder how should it be written so it will know which button I have pressed down.
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.*;
public class Main extends JFrame implements MouseListener, ActionListener{
private JPanel panel1 = new JPanel();
private JPanel panel2 = new JPanel(new GridLayout(4,4));
public Main() {
setSize(300,400);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new BorderLayout());
add(panel1, BorderLayout.NORTH);
add(panel2, BorderLayout.CENTER);
String[] buttonNamn = {"1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};
for(int i=0;i<buttonNamn.length;i++) {
JButton button = new JButton(buttonNamn[i]);
panel2.add(button);
button.addMouseListener(this);
button.addActionListener(this);
}
}
public static void createGUI() {
new Main();
}
public static void main(String[] args) {
createGUI();
}
#Override
public void mouseClicked(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent arg0) {
System.out.println("Pressed");
}
#Override
public void mouseReleased(MouseEvent arg0) {
System.out.println("Relased");
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().equals("1")) {
System.out.println("Foo 1");
}
else if(e.getActionCommand().equals("2")){
System.out.println("Foo 2");
}
}
}
You will need invokeLater as described here: Java: mytextarea.setText("hello") + Thread.sleep(1000) = strange result
otherwise your action will block the UI-thread
For the start look at SwingUtilities.invokeLater.
For the cancel, I generally use an interface with a cancel operation on it which the Runnable provided to the invokeLater implements, the cancel button then kicks off the cancel simply by calling the cancel operation. How this cancels teh operation depends on what it does, maybe it could set a cancelled flag which the running operation can periodically check to see if it should continue.
Note that you can extend listener implementation classes like MouseAdapter to save yourself some typing (only override the methods you want to use).
Rather than use a single listener and have a bunch of case statements to try and figure out the relationship between the button and the data, add a new listener to each button and hold the data in the listener. This code does this with an anonymous class.
public static void main(String[] args) {
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(4, 4));
String[] buttonName = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "A",
"B", "C", "D", "E", "F" };
for (final String name : buttonName) {
JButton button = new JButton(name);
panel.add(button);
button.addMouseListener(new MouseAdapter() {
#Override public void mousePressed(MouseEvent e) {
System.out.println("pressed:" + name);
}
#Override public void mouseReleased(MouseEvent e) {
System.out.println("released:" + name);
}
});
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(panel);
frame.pack();
frame.setVisible(true);
}
Note the use of the final keyword.
There are other ways to express this, if you prefer. This method adds a static inner class:
private static class MyListener extends MouseAdapter {
private final String name;
public MyListener(String name) {
this.name = name;
}
#Override public void mousePressed(MouseEvent e) {
System.out.println("pressed:" + name);
}
#Override public void mouseReleased(MouseEvent e) {
System.out.println("released:" + name);
}
}
public void addStaticInnerClassListener(JButton button, String name) {
button.addMouseListener(new MyListener(name));
}
This one uses a class scoped to the method:
public void addNameListener(JButton button, final String name) {
class MyListener extends MouseAdapter {
#Override public void mousePressed(MouseEvent e) {
System.out.println("pressed:" + name);
}
#Override public void mouseReleased(MouseEvent e) {
System.out.println("released:" + name);
}
}
button.addMouseListener(new MyListener());
}
The code/action you want performed will have to be performed in another thread. Swing provides some utility classes for this, such as SwingWorker.
The getSource method of MouseEvent inherited from EventObject should give you a reference to the clicked button
java api link
Use MouseEvent.getButton() to get the button that triggered the event.
Related
I have some problems with using dispose() method in my GUI project.
I' am making a GUI swing application for some kind of Elections in IntelliJ.
My problem is, by clicking a button(Confirm1, or 2 or 3) I want to open new JFrame which is checking the age of voter and closes the current JFrame where this button is located by calling dispose().
But frame.dispose(); doesn't work.
I have my JFrame declared in public static main().
Should I make reference for it in my ActionListener? I have been looking for solution, but I couldn't find any.
Here is a code:
import javax.swing.*; //another libraries
public class ElectionGUI {
private JPanel labelElection; // another texfields or etc.
private JButton Confirm1;
private JButton Confirm3;
private JButton Confirm2;
private JPanel Elections;
public VotesGUI(){
Votes votes = new Votes("...","...",0);
listX.addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
if(!e.getValueIsAdjusting()){
NrX.setText(listX.getSelectedValue().toString());
}
}
});
listY.addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
if(!e.getValueIsAdjusting()){
NrY.setText(listY.getSelectedValue().toString());
}
}
});
listZ.addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
if(!e.getValueIsAdjusting()){
NrZ.setText(listZ.getSelectedValue().toString());
}
}
});
Confirm1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
votes.VotesX();
votes.countVotes();
CheckAge age = new CheckAge();
age.Check(); /// referention, to my next //Jframe called psvm Check();
}
});
Confirm2.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
votes.VotesY();
votes.countVotes();
CheckAge age = new CheckAge();
age.Check();
}
});
Confirm3.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
votes.VotesZ();
votes.countVotes();
CheckAge age = new CheckAge();
age.Check();
}
});
}
public static void main(String[] args) {
JFrame frame = new JFrame("Elentions");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setContentPane(new ElectionGUI().labelElection);
frame.pack();
}
}
I want to initialize a Graphical User Interface (GUI) for the user to input a form. After this is accomplished i want to open a new GUI, but as soon as the first GUI pops-up the next one is initialized to.
Is there any way to solve this without using waits and notifies?
here is an example of my code:
public static void main(String[] args) {
new GUIForm();
// wait until the user inputs the complete form
new GUIWelcome();
}
It is really simple I woild like to keep it that way.
Create an Interface OnActionListener
public interface OnActionListener {
public void onAction();
}
Add these code in GUIForm class
private OnActionListener listener;
private JButton action;
public GUIForm(OnActionListener listener) {
this.listener = listener;
action = new JButton("Action");
action.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
GUIForm.this.listener.onAction();
}
});
}
Now you can achieve that
new GUIForm(new OnActionListener() {
#Override
public void onAction() {
new GUIWelcome();
}
});
You need to use some sort pub/sub mechanism. This in a nutshell is what you need:
public class PubSub {
public static void main(String[] args) {
JFrame frame1 = new JFrame("GUIForm");
frame1.setSize(640, 480);
JButton button = new JButton("User Input");
JFrame frame2 = new JFrame("Welcome");
frame2.setSize(320, 240);
button.addMouseListener(new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent e) {
button.setCursor(new Cursor(Cursor.HAND_CURSOR));
}
#Override
public void mouseExited(MouseEvent e) {
button.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
#Override
public void mouseClicked(MouseEvent e) {
frame2.setVisible(true);
}
});
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame1.add(button);
frame1.setVisible(true);
}
}
This version uses JFrame's listeners, but you could implement your on callback mechanism to accomplish the same
I would like to listen to events when clicked on Ok and Cancel buttons in CheckBoxListComboBox Does any one know how to register for events on Ok and Cancel buttons? If the events registration is not possible, can we override the Ok and cancel buttons of our own?
It seems there is no option to register a listener. However, you can override getDialogOKAction() and getDialogCancelAction(). You can also override createListChooserPanel() and provide you own actions there.
For example:
import java.awt.event.ActionEvent;
import javax.swing.*;
import com.jidesoft.combobox.CheckBoxListComboBox;
public class TestCheckboxList extends JPanel{
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
String[] items = {"Item1", "Item2", "Item3"};
frame.add(new CheckBoxListComboBox(items){
#Override
protected Action getDialogOKAction() {
return new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("OK");
}
};
}
#Override
protected Action getDialogCancelAction() {
return new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Cancel");
}
};
}
});
frame.pack();
frame.setVisible(true);
}
});
}
}
I'm trying to build a simple Java Swing application using the MVC architecture pattern. What I've done is create the user interface components (as private) in my views, and have public methods that return the components. These methods are then called by the controllers, through which I can write methods for event/action listeners. Below is a sample example:
View:
private JButton btnAdd;
public JButton getBtnAdd(){
return btnAdd;
}
Control:
myGuiFrame gui = new myGuiFrame();
//on add button clicked
gui.getBtnAdd().addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
//calls to model
}
});
Is this implementation correct?
If so, then I'm having a problem with FocusListeners. When I create a FocusListener in my view, the focusLost and focusGained methods are created within the view.
private FocusListener l;
someComponent.addFocusListener(l);
l = new FocusListener() {
#Override
public void focusLost(FocusEvent e) {
// TODO Auto-generated method stub
}
#Override
public void focusGained(FocusEvent e) {
// TODO Auto-generated method stub
}
};
I want all the event handlers to be in my controllers. My question is ... is there a way I can call/declare the focusLost and focusGained methods from my controller? I tried to define the FocusListener as public so that I can define it in my controller:
view:
public FocusListener l;
public someComponentType someComponent;
controller:
gui.l = new FocusListener() {
#Override
public void focusLost(FocusEvent e) {
// TODO Auto-generated method stub
}
#Override
public void focusGained(FocusEvent e) {
// TODO Auto-generated method stub
gui.someComponent.addFocusListener(gui.l);
}
};
This however does not work.
Is it possible to handle FocusEvents from the controller?
EDIT:
Gosh, my bad. Didn't quite understand what Robin was all about. I was too fixated on having the FocusListener explicitly defined somewhere. A simple:
gui.getTextFieldEmployeeCode().addFocusListener(new FocusListener() {
#Override
public void focusLost(FocusEvent e) {
// TODO Auto-generated method stub
}
#Override
public void focusGained(FocusEvent e) {
// TODO Auto-generated method stub
System.out.println("YES!!!");
}
});
in the controller would work just fine in the manner I planned to do it, though I quite like how nIcE cOw's gone about it. Just out of curiosity, is there a standard or widely accepted manner of implementing MVC on Swing Apps?
As far as I understood, the way you doing is this. Better still, I prefer the Anonymous Classes, they respect the concept of Encapsulation. Here try your hands on this code, see what you can grasp with this :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class View
{
private JButton focusButton;
private JButton spareButton;
private void createAndDisplayGUI()
{
JFrame frame = new JFrame("VIEW");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel contentPane = new JPanel();
contentPane.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 5));
focusButton = new JButton("GAINED/LOST");
focusButton.addFocusListener(new ButtonController(this));
spareButton = new JButton("SPARE");
spareButton.setOpaque(true);
spareButton.addActionListener(new ButtonController(this));
spareButton.addFocusListener(new ButtonController(this));
contentPane.add(focusButton);
contentPane.add(spareButton);
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public JButton getFocusButton()
{
return focusButton;
}
public JButton getSpareButton()
{
return spareButton;
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new View().createAndDisplayGUI();
}
});
}
}
class ButtonController implements FocusListener, ActionListener
{
private View view;
private JButton focusButton;
private JButton spareButton;
public ButtonController(View v)
{
view = v;
focusButton = view.getFocusButton();
spareButton = view.getSpareButton();
}
public void actionPerformed(ActionEvent ae)
{
JButton button = (JButton) ae.getSource();
if (button == spareButton)
{
spareButton.setBackground(Color.BLUE);
focusButton.setEnabled(true);
}
}
public void focusGained(FocusEvent fe)
{
JButton button = (JButton) fe.getSource();
if (button == focusButton)
{
focusButton.setEnabled(true);
}
else if (button == spareButton)
{
spareButton.setBackground(Color.WHITE);
}
}
public void focusLost(FocusEvent fe)
{
JButton button = (JButton) fe.getSource();
if (button == focusButton)
{
focusButton.setEnabled(false);
}
else if (button == spareButton)
{
spareButton.setBackground(Color.DARK_GRAY.darker());
}
}
}
Another approach, if you feel irritated by getters/setters and sending references around, is to define one inner class as follows (A Simple workaround for the previous example) :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class View
{
private JButton focusButton;
private JButton spareButton;
private void createAndDisplayGUI()
{
JFrame frame = new JFrame("VIEW");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel contentPane = new JPanel();
contentPane.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 5));
focusButton = new JButton("GAINED/LOST");
focusButton.addFocusListener(new ButtonController());
spareButton = new JButton("SPARE");
spareButton.setOpaque(true);
spareButton.addActionListener(new ButtonController());
spareButton.addFocusListener(new ButtonController());
contentPane.add(focusButton);
contentPane.add(spareButton);
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private class ButtonController implements FocusListener, ActionListener
{
public void actionPerformed(ActionEvent ae)
{
JButton button = (JButton) ae.getSource();
if (button == spareButton)
{
spareButton.setBackground(Color.BLUE);
focusButton.setEnabled(true);
}
}
public void focusGained(FocusEvent fe)
{
JButton button = (JButton) fe.getSource();
if (button == focusButton)
focusButton.setEnabled(true);
else if (button == spareButton)
spareButton.setBackground(Color.WHITE);
}
public void focusLost(FocusEvent fe)
{
JButton button = (JButton) fe.getSource();
if (button == focusButton)
focusButton.setEnabled(false);
else if (button == spareButton)
spareButton.setBackground(Color.DARK_GRAY.darker());
}
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new View().createAndDisplayGUI();
}
});
}
}
I want to be notified when my JPopupMenu is hidden — whether because an item was selected, the menu was dismissed, or setVisible(false) was called on it. Here is my test code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class A extends ComponentAdapter implements Runnable, ActionListener {
private JButton b;
public static void main(String[] args) {
EventQueue.invokeLater(new A());
}
public void run() {
JFrame f = new JFrame("Test");
b = new JButton("Click me");
b.addActionListener(this);
f.add(b);
f.pack();
f.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
JPopupMenu pm = new JPopupMenu();
pm.addComponentListener(this);
pm.add("Popup...");
pm.add("...menu!");
pm.show(b, 10, 10);
}
public void componentShown(ComponentEvent e) { System.out.println("componentShown"); }
public void componentHidden(ComponentEvent e) { System.out.println("componentHidden"); }
}
Regardless of how I interact with the menu, neither of the two ComponentListener methods are being called. Why is that? Is there different/better/correct way of finding out when my JPopupMenu is hidden?
Thanks,
Cameron
JPopupMenu has a special listener for visibility change events:
pm.addPopupMenuListener(new PopupMenuListener() {
#Override
public void popupMenuCanceled(PopupMenuEvent e) {
System.out.println("cancelled");
}
#Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
System.out.println("vanishing");
}
#Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
System.out.println("appearing");
}
});
Note, however, as method names hint, they are called before visibility changes, so if you're calling isVisible() somewhere in the event handlers, you should be aware of that, for example:
#Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
updateMenu();
}
private void updateMenu() {
if (!menu.isVisible()) { // this won't work!
// perform some updates
}
}
With regards to why ComponentListener isn't sending you events on the menu disappearing, this might explain:
The component-hidden and component-shown events occur only as the result of calls to a Component 's setVisible method. For example, a window might be miniaturized into an icon (iconified) without a component-hidden event being fired.
Source: ComponentListener tutorial (non-canonical perhaps, but from the horse's mouth.)
Consider that in conjunction with JPopupMenu's implementation of setVisible:
public void setVisible(boolean b) {
// Not supported for MenuComponents
}
And you might know how it so happens, but not why it happens (what is the justification and where is that properly documented?)