The relationship between the JOptionPane buttons and the user panel

I made a multi-input dialog by building a JPanel with the fields I want and adding it to the JOption panel

JMainPanel mainPanel = new JMainPanel(mensaje, parametros, mgr); int i = JOptionPane.showOptionDialog(null, mainPanel, "Sirena", JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, null, new String[] {"Aceptar", "Cancelar"}, "Aceptar"); 

However, I am having problems with buttons because some of the fields are required. How can I activate the "Ok" button after all the necessary fields are raised or click on the button to perform checks and not close the panel until each required field is filled?

From the Java API, I found this:

options - an array of objects indicating the possible choices the user can make; if objects are components, they are displayed correctly; objects other than String are rendered using toString methods; if this parameter is null, the parameters are determined using the Look and Feel function

So, I can not pass custom buttons as a parameter?

Sounds like I have to make my own JDialog? why don't I know how to make it return an int just like JOptionPane, any recommended tutorial?

In the example options there are {"Aceptar", "Cancelar"} , which are display buttons,

PS. I have full control over the fields that I added to JPanel.

This is a screenshot of JOptionPane:

enter image description here

+4
source share
2 answers

I don't think you can deactivate the JOptionPane selection buttons, but one way to use JOptionPane is to simply re-display it if the required fields have not been set. You can display a JOptionPane error message that first describes the error, and then display a new JOptionPane that contains the same JPanel as the second parameter, so that the data you have already entered has not been lost. Otherwise, you can create your own JDialog, which, incidentally, is not so difficult to do.

Edit
I'm wrong. You can enable and disable the dialog buttons if you use a small recursion.

For instance:

 import java.awt.Component; import java.awt.Container; import java.awt.event.*; import java.util.HashSet; import java.util.Set; import javax.swing.*; public class Foo extends JPanel { private static final String[] DIALOG_BUTTON_TITLES = new String[] { "Aceptar", "Cancelar" }; private JCheckBox checkBox = new JCheckBox("Buttons Enabled", true); private Set<AbstractButton> exemptButtons = new HashSet<AbstractButton>(); public Foo() { JButton exemptBtn = new JButton("Exempt Button"); JButton nonExemptBtn = new JButton("Non-Exempt Button"); add(checkBox); add(exemptBtn); add(nonExemptBtn); exemptButtons.add(checkBox); exemptButtons.add(exemptBtn); checkBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent evt) { allBtnsSetEnabled(checkBox.isSelected()); } }); } private void allBtnsSetEnabled(boolean enabled) { JRootPane rootPane = SwingUtilities.getRootPane(checkBox); if (rootPane != null) { Container container = rootPane.getContentPane(); recursiveBtnEnable(enabled, container); } } private void recursiveBtnEnable(boolean enabled, Container container) { Component[] components = container.getComponents(); for (Component component : components) { if (component instanceof AbstractButton && !exemptButtons.contains(component)) { ((AbstractButton) component).setEnabled(enabled); } else if (component instanceof Container) { recursiveBtnEnable(enabled, (Container) component); } } } public int showDialog() { return JOptionPane.showOptionDialog(null, this, "Sirena", JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, null, DIALOG_BUTTON_TITLES, "Aceptar"); } private static void createAndShowGui() { Foo foo = new Foo(); int result = foo.showDialog(); System.out.println(DIALOG_BUTTON_TITLES[result]); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGui(); } }); } } 

This code uses listeners to check the status of the JCheckBox, but you can listen to (DocumentListeners) text field listeners if you want to know if they have data or not. Then the code gets a JRootPane that contains the JCheckBox, and then the contents area of โ€‹โ€‹the root panel and all the dialogue components are held by that. Then it repeats through all the components held by the dialog. If the component is a container, it passes through that container. If the component is an AbstractButton (for example, any JButton or flag), it enables or disables - with the exception of buttons held in sets of released buttons.

Best example with document listeners

 import java.awt.*; import java.awt.event.*; import java.util.HashSet; import java.util.Set; import javax.swing.*; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; public class Foo2 extends JPanel { private static final String[] DIALOG_BUTTON_TITLES = new String[] { "Aceptar", "Cancelar" }; private static final int FIELD_COUNT = 10; private Set<AbstractButton> exemptButtons = new HashSet<AbstractButton>(); private JTextField[] fields = new JTextField[FIELD_COUNT]; public Foo2() { setLayout(new GridLayout(0, 5, 5, 5)); DocumentListener myDocListener = new MyDocumentListener(); for (int i = 0; i < fields.length; i++) { fields[i] = new JTextField(10); add(fields[i]); fields[i].getDocument().addDocumentListener(myDocListener); } // cheating here int timerDelay = 200; Timer timer = new Timer(timerDelay , new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { checkDocsForText(); } }); timer.setRepeats(false); timer.setInitialDelay(timerDelay); timer.start(); } private void checkDocsForText() { for (JTextField field : fields) { if (field.getText().trim().isEmpty()) { allBtnsSetEnabled(false); return; } } allBtnsSetEnabled(true); } private void allBtnsSetEnabled(boolean enabled) { JRootPane rootPane = SwingUtilities.getRootPane(this); if (rootPane != null) { Container container = rootPane.getContentPane(); recursiveBtnEnable(enabled, container); } } private void recursiveBtnEnable(boolean enabled, Container container) { Component[] components = container.getComponents(); for (Component component : components) { if (component instanceof AbstractButton && !exemptButtons.contains(component)) { ((AbstractButton) component).setEnabled(enabled); } else if (component instanceof Container) { recursiveBtnEnable(enabled, (Container) component); } } } public int showDialog() { return JOptionPane.showOptionDialog(null, this, "Sirena", JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, null, DIALOG_BUTTON_TITLES, "Aceptar"); } private class MyDocumentListener implements DocumentListener { public void removeUpdate(DocumentEvent arg0) { checkDocsForText(); } public void insertUpdate(DocumentEvent arg0) { checkDocsForText(); } public void changedUpdate(DocumentEvent arg0) { checkDocsForText(); } } private static void createAndShowGui() { Foo2 foo = new Foo2(); int result = foo.showDialog(); if (result >= 0) { System.out.println(DIALOG_BUTTON_TITLES[result]); } } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGui(); } }); } } 
+2
source

I suggest that you define some properties in the extended JPanel class and use the PropertyChangeListener to listen to the changes and enable / disable relative buttons.

Here is the article .

Another problem is probably finding ok / cancel buttons in the component hierarchy, because the JDialog is created through JOptionPane and you are not referring to the buttons. Here's a useful thread .

You can add a property to JComponent using the putClientProperty method. When changes occur with the specified property, the PropertyChanged event is raised.

So, in your example, you can define a boolean property that indicates what is required, which are inserted into JDialog. Then add the PropertyChangeListener property to enable / disable the ok button when notified.

+2
source

Source: https://habr.com/ru/post/1389693/


All Articles