JOptionPane always returning -1 - java

I want to double check the delete operation to prevent accidental deletion.
(Here the Yes button would only be enabled if the checkbox is checked.)
But both Yes and No Buttons are returning -1.
This is a snippet of my program.
public class class1 extends javax.swing.JInternalFrame {
JCheckBox cbConfirmDelete;
JPanel outer = new JPanel(new BorderLayout());
final JButton btnYes = new JButton("Yes");
final JButton btnNo = new JButton("No");
public class1() {
......
//Button btnYes ActionListener for JOptionPane
btnYes.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane pane = getOptionPane((JComponent) e.getSource());
pane.setValue(btnYes);
}
});
//Button btnNo ActionListener for JOptionPane
btnNo.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane pane = getOptionPane((JComponent) e.getSource());
pane.setValue(btnNo);
}
});
//layout for JOptionPane
JPanel nested1 = new JPanel();
nested1.add(cbConfirmDelete);
JPanel nested2 = new JPanel();
nested2.add(btnYes);
nested2.add(btnNo);
outer.add(nested1, BorderLayout.NORTH);
outer.add(nested2, BorderLayout.CENTER);
}
protected JOptionPane getOptionPane(JComponent parent) {
JOptionPane pane = null;
if (!(parent instanceof JOptionPane)) {
pane = getOptionPane((JComponent) parent.getParent());
} else {
pane = (JOptionPane) parent;
}
return pane;
}
private void btnDeleteActionPerformed(java.awt.event.ActionEvent evt) {
int dialogResult = JOptionPane.showOptionDialog(null, "Are you sure you want to Delete the Reference ?", "Delete Reference", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, new Object[]{outer}, btnYes);
System.out.println("DialogResult: " + dialogResult);
}
}
The Output DialogResult is always -1. Why is that happening ?
If I pass the following object in JOptionPane it works fine..
new Object[]{cbConfirmDelete, btnYes, btnNo}
But this is not working
new Object[]{outer}

I see a couple of problems here. Since you're creating a Yes/No option dialog, your Object[] array should contain two, and only two, components that correspond to yes or no.
For your example that works, your Object[] array contains the checkbox, the yes button, and the no button. That's one too many components. When you set the pane value in the yes or no action listener, you're setting it to 1 or 2 instead of 0 or 1, since positionally, those components are the second and third. This isn't necessarily a big problem, but usually when you return from a yes/no dialog box, you check for JOptionPane.YES_OPTION (0) or JOptionPane.NO_OPTION (1) to see if the user chose yes or no. In your scenario, you're going to have to check for 1 or 2 since the checkbox is component 0.
For your non-working scenario, the problem is that your object array only contains one object, the outer panel containing the checkbox and the yes/no buttons. Technically what's happening is that you're telling the option pane that there's only one selectable component, a JPanel. Calling pane.setValue() with any component other than the outer panel will have no effect, since the pane's selection value is -1 (uninitialized value) to begin with, and it will only change if you call setValue(outer).

Related

Java dynamically create buttons and pass a parameter to action performed

I am new to java and i am trying a small project on my own, i want to list the first and lastname of users from a sql database (this all works fine, but i don't just want to list them
I want to list all users in a GUI with a delete button, naturally this delete button will be generated dynamically and i want to pass the userID of the button to the action performed.
like this:
John Doe 'Delete button'
Jane Doe 'Delete button'
In my code below i just generate 16 buttons dynamically (without a users table) instead of passing the userID i am trying to pass the 'i' value of the for loop, but my code does not seem to work
CODE
public class UsersView implements ActionListener {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
public UsersView() {
//Create the 16 buttons.
for (int i=0; i<16; i++) {
Button button = new Button("Click "+i);
button.setId(i); //this gives me and error 'Symbol not find' on the 'setId'
panel.add(button);
button.addActionListener(this);
}
panel.setBorder(BorderFactory.createBevelBorder(0, Color.lightGray, Color.yellow));
//panel.setBorder(BorderFactory.createEmptyBorder(300, 300, 100, 300));
panel.setLayout(new GridLayout(4,4)); //Rows Cols
frame.add(panel, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("App GUI");
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
// TODO code application logic here
new UsersView();
}
//On button click.
#Override
public void actionPerformed(ActionEvent e) {
//I know i have nothing here (yet) that is because the 'setId' gives me an error.
}
}
One of the issues you're having is creating a monolithic action listener, and then expecting to delegate actions from that. One nice feature of java are anonymous classes, or since java 7 lambdas.
JButton button = new JButton("Click " + i);
panel.add(button);
int id = i;
button.addActionListener( evt->{
performActionOnId( id );
});
Now instead of having the main class be an action listener, the main class has methods that are descriptive.
public void addUser( User a ){
//just showing delete button.
JButton delete = new JButton("X");
delete.addActionListener( evt ->{
removeUser( a );
//clean up gui.
});
}
This puts some of the steps of delegation at the creation of the user. Otherwise you'll have to delegate in your action performed.
public void actionPerformed( ActionEvent evt ){
//has to be a new class to have id attribute.
CustomButton b = (CustomButton)evt.getSource();
int id = b.getId();
User u = getUserById(id);
removeUser(u);
}
Use a JButton instead of Button. Mixing AWT and Swing components rarely works well, if at all. If you want to set a custom field for a component, just subclass it (use direct subclassing or a decorator pattern with composition). E.g.:
public class IdButton extends JButton {
private int id;
public IdButton(String label, int id) {
super(label);
this id = id;
}
public int getId() {
return id;
}
}
The J/Button classes do not have set/getId methods on it's own.

JOptionPane.showConfirmDialog with a JScrollPane and a maximum size

I was trying to make a JFrame with a JScrollPane containing hundreds of JRadioButtons and two JButtons below (OK and Cancel). Finally I discovered the JOptionPane.showConfirmDialog(...) method.
It seems to be perfect for what I want : From a first JFrame, open a "window" with a Scroll containing my radio buttons and get the selected one in my first JFrame when I click on "OK".
However, when the showConfirmDialog appears, there is no JScrollPane, and we cannot see the bottom of the window (there are hundreds of radio buttons). So :
I tried to call JOptionPane.showConfirmDialog(myScrollPane) instead of adding the JScrollPane to a JPanel and call the method with a JPanel... it didn't work
I tried to initialize a JOptionPane object, then set its maximum size, then call the method showConfirmDialog with the initialized object but it doesn't work because "the method must be called in a static way".
So I need your help, here is my code, and I don't understand what is wrong and why I don't have a scroll with my radio buttons in the confirm dialog.
public void buildMambaJobPathWindow(ArrayList<String> list) {
ButtonGroup buttonGroup = new ButtonGroup();
JPanel radioPanel = new JPanel(new GridLayout(0,1));
for(int i=0; i<list.size(); i++) {
JRadioButton radioButton = new JRadioButton(list.get(i));
buttonGroup.add(radioButton);
radioButton.addActionListener(this);
radioButton.setActionCommand(list.get(i));
radioPanel.add(radioButton);
}
JScrollPane myScrollPane = new JScrollPane(radioPanel);
myScrollPane.setMaximumSize(new Dimension(600,600));
JOptionPane.showConfirmDialog(null, myScrollPane);
}
// Listens to the radio buttons
public void actionPerformed(ActionEvent e) {
String result = e.getActionCommand();
}
Thank you for your time.
As shown here, you can override the scroll pane's getPreferredSize() method to establish the desired size. If the content is larger in either dimension, the corresponding scroll bar will appear as needed.
JScrollPane myScrollPane = new JScrollPane(radioPanel){
#Override
public Dimension getPreferredSize() {
return new Dimension(600, 600);
}
};
JOptionPane.showConfirmDialog(null, myScrollPane);

JComboBox and ItemListener / ActionListener

I am creating a program for class where you have a JComboBox and when one option is selected it pops up a window with different options. I have one option that pops up a new window with two buttons on it.
First I'm not sure if I should be using ItemListener or ActionListener for the JComboBox options. Right now I have an ItemListener which I thought would work for just "The Matrix" option but it works for both options and I can't figure out why. I'll post all my code just in case but I'll add stars above and below the specified issue.
Thanks for any help or pointing me in the right direction!
public class MultiForm extends JFrame{
private JComboBox menu;
private JButton bluePill;
private JButton redPill;
private JLabel matrix;
private int matrixSelection;
private static String[] fileName = {"", "The Matrix", "Another Option"};
public MultiForm() {
super("Multi Form Program");
setLayout(new FlowLayout());
menu = new JComboBox(fileName);
add(menu);
*************************************************************************
TheHandler handler = new TheHandler();
menu.addItemListener(handler);
}
private class TheHandler implements ItemListener{
public void itemStateChanged(ItemEvent event) {
if(event.getStateChange() == ItemEvent.SELECTED) {
menu.setSelectedItem("The Matrix");
menu.getSelectedIndex();
*************************************************************************
//Create a new window when "The Matrix" is clicked in the JCB
JFrame newFrame = new JFrame();
JPanel panel = new JPanel();
newFrame.setLayout(new FlowLayout());
newFrame.setSize(500, 300);
newFrame.setDefaultCloseOperation(newFrame.EXIT_ON_CLOSE);
add(panel, BorderLayout.CENTER);
matrix = new JLabel("<html>After this, there is no turning back. "
+ "<br>You take the blue pill—the story ends, you wake up "
+ "<br>in your bed and believe whatever you want to believe."
+ "<br>You take the red pill—you stay in Wonderland, and I show"
+ "<br>you how deep the rabbit hole goes. Remember: all I'm "
+ "<br>offering is the truth. Nothing more.</html>");
newFrame.add(matrix, BorderLayout.NORTH);
Icon bp = new ImageIcon(getClass().getResource("Blue Pill.png"));
bluePill = new JButton("Blue Pill", bp);
newFrame.add(panel.add(bluePill));
Icon rp = new ImageIcon(getClass().getResource("Red Pill.png"));
redPill = new JButton("Red Pill", rp);
newFrame.add(panel.add(redPill));
newFrame.setVisible(true);
}
}
}
public static void main(String[] args) {
MultiForm go = new MultiForm();
go.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
go.setSize(400, 200);
go.setVisible(true);
}
}
ItemListener and ActionListener will tell when something about the combo box has changed. You then need to ascertain WHAT has changed and take appropriate action
For example...
private class TheHandler implements ItemListener{
public void itemStateChanged(ItemEvent event) {
if(event.getStateChange() == ItemEvent.SELECTED) {
Object source = event.getSource();
if (source instanceof JComboBox) {
JComboBox cb = (JComboBox)source;
Object selectedItem = cb.getSelectedItem();
if ("The Matrix".equals(selectedItem)) {
// Do the matrix
} else if ("Another Option".equals(selectedItem)) {
// Do another option
}
}
}
}
}
This simply checks what the selectedItem is and takes appropriate action according to what is selected. You could also use selectedIndex instead, which will return a int representing the selected item, but which ever is easier for you.
Have a look at How to Use Combo Boxes for more details
If all you want to know is when a item is selected, you might find a ActionListener simpler, as you don't need to check the state (SELECTED/UNSELECTED), as it only triggers on the selected state change

How to get to JDialog methods?

I just get stuck with app. The thing is in second actionListener, I want to get object or more specifically access to methods in my JDialog class.
I got few dialogs created, but not visible. In first actionListener I get to them by getDialog function which is returning JDialog. So I can each one of them visible.
2nd actionListener which I need help with, is showing JOptionPane and if user pick the YES_OPTION I want to run my method from specific dialog.
I it's not clear I'd try to fix my explanations so you can understand it.
modifyButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JButton thisButton = (JButton) e.getSource();
JPanel parentPanel = (JPanel) thisButton.getParent();
Container topLevel = parentPanel.getTopLevelAncestor();
MainFrame mainFrame = (MainFrame) topLevel;
mainFrame.getDialog(TABLECOUNTER).setVisible(true);
}
});
abortButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Object[] options = {"Tak", "Nie"};
int userReply = JOptionPane.showOptionDialog(null, "Czy na pewno chcesz anulować rachunek?", "Probujesz anulować rachunek!", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, options, options[0]);
if (userReply == JOptionPane.YES_OPTION) {
JButton thisButton = (JButton) e.getSource();
JPanel parentPanel = (JPanel) thisButton.getParent();
Container topLevel = parentPanel.getTopLevelAncestor();
MainFrame mainFrame = (MainFrame) topLevel;
mainFrame.getDialog(TABLECOUNTER).myMethod(); //here
}
}
});
"I want to get object or more specifically access to methods in my JDialog class"
If the method getDialog returns a standard JDialog,
public JDialog getDialog(...) {}
Then you're stuck with the methods of JDialog, without proper casting, or changing the return type. That would explain why you are able to setVisible in the first method, because JDialog does have a method setVisible. So to access the method myMethod you'll want to do some casting.
((MyDialog)mainFrame.getDialog(TABLECOUNTER)).myMethod();

adding components in applet

I am making an applet and as part of my applet, I want this to happen: When the user presses "OK", the old components (some radio buttons) are removed, and a new JPanel is added, with a bunch of textfields.
However, I cannot figure out how to add a new component to the applet after it has started. I made the problem simpler by ignoring the removal part (Which I know how to do) and just adding a simple JLabel instead, but even that won't add!
Here is my code so far:
// imports omitted
public class Class extends Applet implements ActionListener
{
Button okButton;
CheckboxGroup radioGroup;
Checkbox radio1;
Checkbox radio2;
Checkbox radio3;
JLabel j;
public void init()
{
setLayout(new FlowLayout());
okButton = new Button("OK");
j = new JLabel("hello");
radioGroup = new CheckboxGroup();
radio1 = new Checkbox("Red", radioGroup,false);
radio2 = new Checkbox("Blue", radioGroup,true);
radio3 = new Checkbox("Green", radioGroup,false);
add(okButton);
add(radio1);
add(radio2);
add(radio3);
okButton.addActionListener(this);
}
public void repaint(Graphics g)
{
if (radio1.getState()) add(j);
}
public void actionPerformed(ActionEvent evt)
{
if (evt.getSource() == okButton) repaint();
}
}
What am I doing wrong?
You shouldn't override the repaint method, and certainly not add a component in this method. Just remove the radio buttons from the applet (using its remove method) and add the label in the applet in your actionPerformed method, the same way you add them in the init method.
You might have to call validate after.
Add components and then call validate() of your container. In this case yourApplet.validate(). This will trigger repainting and rearranging of all elements.
you could do something like
JFrame fr= new JFrame(); // global variables
JPanel panelToBeAdded = new JPanel();
JPanel initialPanel = new JPanel();
JTextField fieldToBeAdded = new JTextField();
panelToBeAdded.setPreferredSize( new Dimension(400,400));
initialPanel.setPreferredSize( new Dimension(400,400));
initialPanel.setVisible(true);
fr.add(initialPanel);
fr.setVisible(true);
fr.pack();
public void actionPerformed(ActionEvent ae) {
initialPanel.setVisible(false);
//radiobuttons.setVisible(false);---> hide the radio buttons
panelToBeAddedd.add(fieldToBeAddedd);
panelToBeAddedd.setVisible(true);
fr.add(panelToBeAddedd);
}
public void repaint( Graphics g ) {
// do something
}
What am I doing wrong?
Your repaint(Graphics) method is not the same method you are calling in your actionPerformed method.
Also, repaint is a pretty bad name for a method which is adding a new component.
public void swapComponents()
{
if (radio1.getState()) {
remove(radio1);
remove(radio2);
remove(radio3);
add(j);
validate();
}
}
public void actionPerformed(ActionEvent evt)
{
if (evt.getSource() == okButton) {
swapComponents();
}
}
When the user presses "OK", the old components (some radio buttons) are removed, and a new JPanel is added, with a bunch of textfields.
Use a CardLayout, as shown here. It is perfect for situations like this.

Categories