How to make two JButtons do separate actions - java

Everytime I press cancel or save on the UI it always executes both of the buttons. I've tried countless ways to make it listen to the if statements in the actionperformed block, but it seems to ignore it. I need it so that if I click save it only executes onSave() and cancel for onCancel(). Thanks for your time
public class EditTagPanel extends AbstractTagPanel implements ActionListener {
TagPanelEventListener tagPanelEventListener;
JButton save;
JButton cancel;
public EditTagPanel(ID3v1 id3v1Tag) {
super(id3v1Tag);
}
#Override
protected void configureActionFields() {
JPanel editOptionsPanel = new JPanel(new FlowLayout());
save = new JButton("Save");
save.addActionListener(this);
editOptionsPanel.add(save);
cancel = new JButton("Cancel");
cancel.addActionListener(this);
editOptionsPanel.add(cancel);
this.add(editOptionsPanel, BorderLayout.PAGE_END);
}
public void addTagPanelEventListener(TagPanelEventListener tagPanelEvent) {
this.tagPanelEventListener = tagPanelEvent;
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(save));
{
tagPanelEventListener.onSave(getId3v1Tag());
}
if(e.getSource().equals(cancel));
{
tagPanelEventListener.onCancel();
}
}

Just remove:
;
after each if-statment in your actionPerformed() method, like next:
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(save)) {
tagPanelEventListener.onSave(getId3v1Tag());
}
if (e.getSource().equals(cancel)) {
tagPanelEventListener.onCancel();
}
}

Related

Cant use dispose(); method, Java Gui form

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();
}
}

JButton not invoking actionPerformed on any subsequent click in same GUI instance

I have a JButton that will not allow me to perform the same action on any subsequent click on it after the first in the same Swing GUI instance.
JButton Run = new JButton("Run");
Run.setLocation(290, 70);
Run.setSize(120, 30);
buttonPanel.add(Run);
Run.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (Run.isEnabled()) {
errorLabel.setText("");
Result result = JUnitCore.runClasses(Run.class);
errorMessageDisplay(result);
}
}
});
totalGUI.setOpaque(true);
return totalGUI;
}
So far I thought about and tried removing the JPanel and painting all of the buttons back on, and disabling/renabling buttons.
The errorMessageDisplay method is as follows:
public void errorMessageDisplay(Result resultPass) {
if (resultPass.getFailureCount() > 0) {
errorLabel.setForeground(Color.red);
errorLabel.setVisible(true);
errorLabel.setText(" Failed");
}
else {
errorLabel.setForeground(Color.green);
errorLabel.setText(" Passed");
errorLabel.setVisible(true);
}
}
At first glance, the JUnitCore.runClasses(Run.class); call is suspicous. Also, it would be good to know what does the errorMessageDisplay() do. I believe, the problem is with one of these methods.
You can verify this with the following experimental code. Just be careful not to push it into production.
JButton run = new JButton("Run");
run.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (Run.isEnabled()) {
errorLabel.setText("");
System.out.println("Run action peformed.");
}
}
Update Since the errorMessageDisplay() looks okay, it's probably a Threading problem with JUniCore. Thus I'd try the following code:
final ExecutorService executor = Executors.newFixedThreadPool(5); // this runs stuff in background
JButton run = new JButton("Run");
// ..
run.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (Run.isEnabled()) {
executor.execute(new Runnable() { // This is how we run stuff in background. You can use lambdas instead of Runnables.
public void run() {
final Result result = JUnitCore.runClasses(Run.class); // Run.class is different from the current JButton run.
SwingUtilities.invokeLater(new Runnable() { // Now we go back to the GUI thread
public void run() {
errorMessageDisplay(result);
}
});
}
});
}
});

triggering an action of button from another class in the main method

Hello while I was following a tutorial I have learnt a way to trigger response in the main class from a click of a button in another class.
So what I have done is that I have a ToolBar class with some code as below
private JButton helloButton;
private JButton goodbyeButton;
private StringListener textListener;
public Toolbar() {
setBorder(BorderFactory.createEtchedBorder());
helloButton = new JButton("Hello");
goodbyeButton = new JButton("Goodbye");
helloButton.addActionListener(this);
goodbyeButton.addActionListener(this);
setLayout(new FlowLayout(FlowLayout.LEFT));
add(helloButton);
add(goodbyeButton);
}
public void setStringListener(StringListener listener) {
this.textListener = listener;
}
#Override
public void actionPerformed(ActionEvent e) {
JButton clicked = (JButton) e.getSource();
if (clicked == helloButton) {
if (textListener != null){
textListener.textEmitted("Hello\n");
}
//textPanel.appendText("Hello\n");
} else {
if (textListener != null){
textListener.textEmitted("Goodbye\n");
//textPanel.appendText("Goodbye\n");
}
}
}
Then in StrinListener Interface I have
public interface StringListener {
public void textEmitted (String text);
}
Finally in main I get the two together by
toolbar.setStringListener(new StringListener (){
#Override
public void textEmitted(String text) {
textPanel.appendText(text);
}
});
what I am curious about is that why does clicking a button trigger response in main method "every time" I click?
so the click is being passed onto textemitted method in StringListener interface and that is received by toolbar.setStringListener in main method. But what is invoking it to work over and over whenever I click the button?
shouldn't the code be read only once unless there is while loop or another loop of some sort?
Thanks
my main class
public MainFrame() {
super("Hello World");
setLayout(new BorderLayout());
textPanel = new TextPanel();
btn = new JButton("Click Me!");
toolbar = new Toolbar();
formPanel = new FormPanel();
toolbar.setStringListener(new StringListener (){
#Override
public void textEmitted(String text) {
textPanel.appendText(text);
}
});
formPanel.setFormListener(new FormListener(){
public void formEventOccurred(FormEvent e){
String name = e.getName();
String occupation = e.getOccupation();
textPanel.appendText(name + ": " + occupation + "\n");
}
});
add(toolbar, BorderLayout.NORTH);
add(textPanel, BorderLayout.CENTER);
add(formPanel, BorderLayout.WEST);
setSize(600, 500);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
It is behaving as expected.
Remember that when you set the textListener, the Toolbar class holds on to an instance variable (of the textListener), and therefore it is kept alive as long as your program is running or until the toolbar object is destroyed. Just because it is an anonymous inner class doesn't mean that the object is destroyed after the method textEmitted is ran once.

How can i wait for a frame to perform an action before the code execute the next line?

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

How to make an action command for same buttons

I have here just a snip of code for my button:
up = new JButton(new ImageIcon("more_buttons\\up3.png"));
up.setBackground(new Color(224,223,227));
up.setPreferredSize(new Dimension(5,15));
up.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
value1000++;
if(value1000>0)
{
number.setText(value1000+"");
down.setEnabled(true);
}
}
});
down = new JButton(new ImageIcon("more_buttons\\down3.png"));
down.setBackground(new Color(224,223,227));
down.setPreferredSize(new Dimension(5,15));
down.setEnabled(false);
down.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
value1000--;
if(value1000>0)
{
number.setText(value1000+"");
}
if(value1000==0)
{
number.setText(value1000+"");
down.setEnabled(false);
}
}
});
I'm wondering if I can make an action command for this button so that I won't have to repeat this code throughout my program. I only have to call the function like buttonaction(e) or something like that. I'm not used to creating action command but I have used it before but only for appending text. I'm not sure how to do that with a function like this. Is it possible? Or is there a more efficient way to do this?
You can add the same ActionListener to multiple buttons:
ActionListener al = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// You can check which button was pressed and act accordingly
// simply by checking the event source:
if (e.getSource() == button1)
System.out.println("Button1 was pressed.");
else if (e.getSource() == button2)
System.out.println("Button2 was pressed.");
}
};
button1.addActionListener(al);
button2.addActionListener(al);
To remove boiler plate code, You need to at least implement an ActionListener in your class
samaple:
public class myClass implements ActionListener
It will generate an actionPerformed method After you need to add actionCommand in your button so when you click a button it will recognize it that you pressed that button
sample:
down.setActionCommand("down");
down.addActionListener(this);
up.setActionCommand("up");
up.addActionListener(this);
in the actionPerformed method
#Override
public void actionPerformed(ActionEvent evt)
{
String actionCommand = evt.getActionCommand(); //get the actionCommand and pass it to String actionCommand
switch(actionCommand) { //switch statement for each of the action command
case "down":
//down button command here
break;
case "up":
//up button command here
}
}
Take a look at How to use Actions
public abstract class AbstractNumberValueAction extends AbstractAction {
private NumberModel model;
private JTextField numberField;
private int delta;
public ValueAction(NumberModel model, JTextField numberField, int delta) {
this.model = model;
this.numberField = numberField;
this.delta = delta;
}
public void actionPerformed(ActionEvent evt) {
int value1000 = model.updateValue(delta);
if(value1000>0)
{
numberField.setText(value1000+"");
}
if(value1000==0)
{
numberField.setText(value1000+"");
setEnabled(false);
}
}
}
public class UpAction extends AbstractNumberValueAction {
public ValueAction(NumberModel model, JTextField numberField) {
this(model, numberField, 1);
putValue(SMALL_ICON, new ImageIcon("more_buttons\\up3.png"));
}
}
public class DownAction extends AbstractNumberValueAction {
public ValueAction(NumberModel model, JTextField numberField) {
this(model, numberField, -1);
putValue(SMALL_ICON, new ImageIcon("more_buttons\\down3.png"));
}
}
Which could then simply be applied as
up = new JButton(new UpAction(model, number));
down = new JButton(new DownAction(model, number));
For example...
(ps- NumberModel would be a simple class that controlled the underlying value to make is simpler to manage ;))

Categories