Disabling a Jbutton in java when another Jbutton is pressed - java

My code is:
public FactoryWindow()
{
getPreferredSize();
setTitle("Bounce");
JPanel buttonPanel = new JPanel();
add(comp, BorderLayout.CENTER);
addButton(buttonPanel, "Circle", new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
comp.addShape();
}
});
addButton(buttonPanel, "Machine", new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
comp.addMachine();
}
});
addButton(buttonPanel, "Close", new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
System.exit(0);
}
});
add(buttonPanel, BorderLayout.SOUTH);
pack();
}
This is a constructor. the class extends JFrame
public void addButton(Container c, String title, ActionListener listener)
{
JButton button = new JButton(title);
c.add(button);
button.addActionListener(listener);
}
I want to be able to disable the Shape button when I press the machine button
How would I go about doing that?
I know there is Something like buttonName.setEnabled(false); but I cannot figure out how to use it in this context.

You will need a reference to the button you are trying to disable, this will require you to change your code slightly...
First, you need your addButton method to return the button it created...
public JButton addButton(Container c, String title, ActionListener listener) {
JButton button = new JButton(title);
c.add(button);
button.addActionListener(listener);
return button;
}
Then you need to assign the result to a variable...
JButton cirlce = null;
JButton machine = null;
cirlce = addButton(buttonPanel, "Circle", new ActionListener() {
public void actionPerformed(ActionEvent event) {
comp.addShape();
}
});
Then you can access it from your ActionListener...
machine = addButton(buttonPanel, "Machine", new ActionListener() {
public void actionPerformed(ActionEvent event) {
comp.addMachine();
circle.setEnabled(false);
}
});
Now, if you're using Java 6 (and I think Java 7), it will complain that the button should be final, but this won't work based on the way you have your code set up. Instead, you will need to make circle and machine instance fields in order to be able to access them from within the ActionListener context

Related

Why is my showMessageDialog displaying twice?

I am working on a simple counter swing app. I'm trying to make it so when you click the check box, it will stay on the top and display a message dialog being "On Top" or "Not On Top".
However, when I click the checkbox after compiling and running, both of the messages display, and after clicking OK on both messages, the checkbox isn't even enabled. If I were to remove the showMessageDialog, it would still function properly, but I want to learn how to appropriately implement this.
Thank you in advance. Here is all of the code for the program:
public Class Counter {
JFrame frame;
JPanel panel;
JButton button, clear;
JTextField textC;
JLabel label;
JCheckBox cbox;
boolean topC = false;
int icount = 0;
String scount;
String topStatus = "";
public Counter() {
gui();
setActions();
}
public void gui() {
frame = new JFrame("Counter Program");
panel = new JPanel();
label = new JLabel("Counter");
textC = new JTextField();
textC.setPreferredSize(new Dimension(72,28));
textC.setEditable(false);
button = new JButton("Click");
clear = new JButton("Clear");
cbox = new JCheckBox("Top");
frame.setSize(350,80);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.add(panel);
panel.add(label);
panel.add(textC);
panel.add(button);
panel.add(clear);
panel.add(cbox);
frame.setVisible(true);
}
public void setActions() {
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
icount++;
scount = Integer.toString(icount);
textC.setText(scount);
}
});
clear.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
icount = 0;
textC.setText("");
}
});
cbox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
topC = !topC;
if (topC) {
topStatus = "Top";
}
else topStatus = "Not Top";
frame.setAlwaysOnTop(topC);
JOptionPane.showMessageDialog(frame, topStatus, "Top Setting", 1);
}
});
}
public static void main(String[]args) {
new Counter();
}
}
An ItemListener generates two events, one for the selection and one for the unselection (and vice versa). Read the section from the Swing tutorial on How to Write an ItemListener for more information and working exmaples if you really want to use an ItemListener.
Otherwise, use an ActionListener instead, it will only generate a single event.

Understanding How to Add A JButton to a JTable

I am trying to implement some buttons in my JTable. I have been looking at
this example.
What I don't understand is this constructor:
public ButtonEditor(JCheckBox checkBox) {
super(checkBox);
button = new JButton();
button.setOpaque(true);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
fireEditingStopped();
}
});
}
What does the JCheckBox have to do with anything? There is no JCheckBox displayed anywhere nor does it seem it is even relevant to the example. TIA.
The DefaultCellEditor usage here is more of a hack for using Buttons as it accepts only JCheckBox, JComboBox and JTextField.
If you really want to implement for JButton, you can also do like,
class ButtonEditor extends AbstractCellEditor
implements javax.swing.table.TableCellEditor,
javax.swing.tree.TreeCellEditor
Else you can update your implementation for using a constructor with JButton as parameter or default constructor,
Approach 1
public ButtonEditor() {
super(new JCheckBox());
button = new JButton();
button.setOpaque(true);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
fireEditingStopped();
}
});
}
and can be accessed as,
table.getColumn("Button").setCellEditor(
new ButtonEditor());
Approach 2
public ButtonEditor(JButton button) {
super(new JCheckBox());
this.button = button;
button.setOpaque(true);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
fireEditingStopped();
}
});
}
This approach provides better clarity and usage of button component outside the cell editor too,
JButton button=new JButton();
table.getColumn("Button").setCellEditor(
new ButtonEditor(button));
It is because class ButtonEditor extends DefaultCellEditor, and constructor of DefaultCellEditor in your example looks like this DefaultCellEditor​(JCheckBox checkBox)

Counting click on button

I want to ask what function or another have to write so that every time I pressed the Start button (function:addbutton), the other button to exit (function:addButton2) to change its title to how many times I press the start?
class DroppingFrame extends JFrame {
public DroppingFrame() {
int clicked=0;
String b="a";
setSize(1400, 700);
setTitle("Dropping");
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
Container contentPane = getContentPane();
canvas = new JPanel();
contentPane.add(canvas, "Center");
JPanel p = new JPanel();
addButton(p, "Drop ball", clicked, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//addButton.setText(String.valueOf(++clicked));
Ball b = new Ball(canvas);
// if(b== new Ball(canvas)){
// clicked++;
// }
b.start();
}
});
addButton2(p, b, clicked, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
canvas.setVisible(false);
System.exit(0);
}
});
contentPane.add(p, "South");
}
public void addButton(Container c, String title, int i, ActionListener a) {
//i++;
//title = Integer.toString(i);
JButton b = new JButton(title);
c.add(b);
b.addActionListener(a);
}
public void addButton2(Container c, String title, int i, ActionListener a ) {
i++;
title = Integer.toString(i);
JButton b = new JButton(title);
c.add(b);
b.addActionListener(a);
}
private JPanel canvas;
}
My preference would be:
Make clicked a class field - that way you can access it and mutate it inside the event handler
Create a class field for a button
Refactor the addButton method so there is only one of them - this makes your code tidier:
Change the method return type to return the button created, then you decide if you store it or not from the caller. This just smells nicer.
The code looks like:
class DroppingFrame extends JFrame {
final JPanel canvas = new JPanel();
JButton button2;
int clicked = 0;
public DroppingFrame() {
setSize(1400, 700);
setTitle("Dropping");
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
Container contentPane = getContentPane();
contentPane.add(canvas, "Center");
JPanel p = new JPanel();
addButton(p, "Drop ball", clicked, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
Ball b = new Ball(canvas);
b.start();
button2.setText(String.valueOf(++clicked));
}
});
button2 = addButton(p, String.valueOf(clicked), clicked, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
canvas.setVisible(false);
System.exit(0);
}
});
contentPane.add(p, "South");
}
public JButton addButton(Container c, String title, int i, ActionListener a) {
JButton b = new JButton(title);
c.add(b);
b.addActionListener(a);
return b;
}
}
It requires the reference of the second button so that start button can update its text.
Keep it simple:
Use setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); instead of adding WindowListener to close the window.
Use JFrame#dispose to close the JFrame programmatically.
Favor Composition over Inheritance It means if you are not overriding any logic/implementation of the existing class then don't extend it.
There is no meaning of creating separate method for adding each component. Either make the method generic or simply remove it.
Sample code:
public class DroppingFrame {
private int clicked = 0;
public DroppingFrame() {
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container contentPane = frame.getContentPane();
JPanel p = new JPanel();
final JButton btn2 = new JButton(String.valueOf(clicked));
btn2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
frame.dispose();
}
});
JButton btn1 = new JButton("Drop ball");
btn1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
btn2.setText(String.valueOf(++clicked));
}
});
p.add(btn1);
p.add(btn2);
contentPane.add(p, BorderLayout.SOUTH);
frame.setVisible(true);
}
}
It's not correct.. addButton always creates a new button and its reference is lost.. you should make it class-scoped.
So make a class variable:
JButton button = new JButton();
Change your function:
public void addButton(Container c, String title, int i, ActionListener a) {
button.setText(title);
c.add(button);
button.addActionListener(a);
}
And also change your actionPerformed override:
public void actionPerformed(ActionEvent evt) {
button.setText(String.valueOf(++clicked));
....
});

How to replace current JPanel with another JPanel?

I am trying to transit from a UserAdminPanel to AdminLogin within the same JPanel when I press the Admin button.
UserAdmin Panel
transit to AdminLogin Panel
The problem I have now is that I am opening up a new panel instead of changing the current panel to the new panel.
This is my code for the UserAdminPanel
public class SelectAdminUserPanel extends JPanel
{
public SelectAdminUserPanel()
{
setLayout(new GridLayout(3,1));
JButton b1 = new JButton("User Login");
JButton b2 = new JButton("Admin Login");
JButton b3 = new JButton("Exit");
b1.addActionListener(new SelectUserButtonListener() );
b2.addActionListener(new SelectAdminButtonListener());
b3.addActionListener(new SelectExitButtonListener() );
add(b1);
add(b2);
add(b3);
}
private class SelectAdminButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
AdminModule am = new AdminModule();
am.run();
}
}
private class SelectUserButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
GameModule gm = new GameModule();
gm.run();
}
}
private class SelectExitButtonListener implements ActionListener
{
public void actionPerformed (ActionEvent event)
{
}
}
}
This is the code for the AdminLogin Panel
public class AdminLoginPanel extends JPanel
{
AdminLoginPanel()
{
JLabel pwlabel = new JLabel("Password");
JPasswordField pwfield = new JPasswordField(20);
JButton loginbutton = new JButton("Login");
add(pwlabel);
add(pwfield);
add(loginbutton);
}
}
I have looked at the following example and this example but it's not very applicable because it talks about CardLayout instead of like rewriting the current JPanel.
I think that you should have a reference to your main frame and just remove the components from it based on the button pressed and add only the required components. From what you say, UserAdminPanel is your main panel. I think it's added to a frame for which you can obtain a reference. When you click a button, you want to remove all the content shown on it and display only what the button clicked should show. I think it should look something like this:
private class SelectAdminButtonListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
frame.getContentPane().removeAll();
AdminModule am = new AdminModule();
frame.add(am.getNewPanel());
frame.pack();
// am.run(); //it's not clear what does for you
}
}
Where the method getNewPanel() would return the underlying JPanel. I'm assuming that AdminModule has a reference to the AdminLoginPanel.

Default button in JFrame is not firing when the enter key is being pressed

I have a JFrame with three JButtons on it. I have set txtSearch (a JTextField component) to have the focus when JFrame loads. One of the buttons is set as the default button. This is my code:
private void formWindowOpened(java.awt.event.WindowEvent evt)
{
// btnRefresh.setMnemonic(KeyEvent.VK_R); // Even if this line
// is not commented, but
// still the event wouldn't fire.
this.getRootPane().setDefaultButton(btnRefresh);
}
When it loads, the button is just selected, but it did nothing when the Enter key was being pressed. How do I correctly implement it?
btnRefresh.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnRefreshActionPerformed(evt);
}
});
private void btnRefreshActionPerformed(java.awt.event.ActionEvent evt) {
JOptionPane.showMessageDialog(this, "Pressed!");
// Other codes here (Replace by JOptionPane)
}
What component has focus when the JFrame comes up? I ask because some components "eat" the Enter key event. For example, a JEditorPane will do that.
Also, when you assign an ActionListener to JTextField, the ActionListener will be called instead of the DefaultButton for the root pane. You must choose either to have an ActionListener or a DefaultButton, but you can't have both fire for the same JTextField. I'm sure this applies to other components as well.
I don't see what you are doing incorrectly from what is posted. Here is a short example that works. Perhaps it will reveal something useful to you.
import java.awt.BorderLayout;
public class ExampleFrame extends JFrame
{
private JPanel m_contentPane;
private JTextField m_textField;
/**
* Launch the application.
*/
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
try
{
ExampleFrame frame = new ExampleFrame();
frame.setVisible(true);
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public ExampleFrame()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
m_contentPane = new JPanel();
m_contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
m_contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(m_contentPane);
m_textField = new JTextField();
m_contentPane.add(m_textField, BorderLayout.NORTH);
m_textField.setColumns(10);
JButton btnNewButton = new JButton("Default");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(ExampleFrame.this, "Default.");
}
});
m_contentPane.add(btnNewButton, BorderLayout.CENTER);
JButton btnNewButton_1 = new JButton("Not default");
btnNewButton_1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
JOptionPane.showMessageDialog(ExampleFrame.this, "Not default.");
}
});
m_contentPane.add(btnNewButton_1, BorderLayout.WEST);
m_textField.requestFocus();
getRootPane().setDefaultButton(btnNewButton);
}
}

Categories