简体   繁体   English

JOptionPane按钮和自定义面板之间的通信

[英]Communication between JOptionPane buttons and a custom panel

I have made a multiple input dialog by building a JPanel with the fields I want and adding it to a JOption pane 我通过构建一个包含我想要的字段的JPanel并将其添加到JOption窗格来创建一个多输入对话框

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'm having trouble with the buttons, because some of the fields are required. 但是我的按钮有问题,因为有些字段是必需的。 How can I make the "Ok" button to be enabled once every required field is up, or making the click on the button to make the validations and do not close the pane until every required field is filled? 如何在每个必填字段启动后启用“确定”按钮,或者单击按钮进行验证,并且在填写每个必填字段之前不要关闭窗格?

From the Java API, I found this: 从Java API,我发现了这个:

options - an array of objects indicating the possible choices the user can make; options - 一个对象数组,指示用户可以做出的选择; if the objects are components, they are rendered properly; 如果对象是组件,则它们被正确呈现; non-String objects are rendered using their toString methods; 非String对象使用其toString方法呈现; if this parameter is null, the options are determined by the Look and Feel 如果此参数为null,则选项由外观确定

So, can't I pass custom buttons as parameter? 那么,我不能将自定义按钮作为参数传递吗?

Looks like I will have to make my own JDialog? 看起来我将不得不制作自己的JDialog? for which case, I don't know how to make it return an int just like JOptionPane does, any recommended tutorial? 对于这种情况,我不知道如何让它像JOptionPane那样返回一个int ,任何推荐的教程?

In the example options is {"Aceptar", "Cancelar"} which are the displayed buttons, 在示例中, options{"Aceptar", "Cancelar"} ,它们是显示的按钮,

PS. PS。 I have full controll over the fields I added to the JPanel. 我完全控制了我添加到JPanel的字段。

This is a screenshot of the JOptionPane: 这是JOptionPane的截图:

在此输入图像描述

I suggest you to define some properties into your JPanel extended class, and use PropertyChangeListener to listen the occured changes and enable/disable relative buttons. 我建议你在JPanel扩展类中定义一些属性,并使用PropertyChangeListener来监听发生的更改并启用/禁用相对按钮。

Here's an article . 这是一篇文章

Another issue maybe finding the ok/cancel buttons in the hierarchy of components, since the JDialog is created through JOptionPane and you haven't a reference to the buttons. 另一个问题可能是在组件层次结构中找到ok / cancel按钮,因为JDialog是通过JOptionPane创建的,并且您没有对按钮的引用。 Here's a useful thread . 这是一个有用的主题

You can add a property to a JComponent using putClientProperty method. 您可以使用putClientProperty方法向JComponent添加属性。 When changes occurs to a given property a PropertyChanged event is raised. 当给定属性发生更改时,将引发PropertyChanged事件。

So in your example you can define a boolean property indicating that required that are inserted into the JDialog. 因此,在您的示例中,您可以定义一个布尔属性,指示插入到JDialog中的必需项。 Then add a PropertyChangeListener that when is notified enable/disable the ok button. 然后添加一个PropertyChangeListener,通知何时启用/禁用ok按钮。

I don't think that you can de-activate a JOptionPane's selections buttons, but one way to still use the JOptionPane is to simply re-display it if the required fields have not been set. 我不认为您可以取消激活JOptionPane的选择按钮,但仍然使用JOptionPane的一种方法是在未设置所需字段的情况下重新显示它。 You could display an error message JOptionPane first describing the error, and then display a new JOptionPane that holds the same JPanel as its second parameter -- so that the data already entered has not been lost. 您可以显示错误消息JOptionPane首先描述错误,然后显示一个新的JOptionPane ,它保存与第二个参数相同的JPanel - 这样就已经输入的数据没有丢失。 Otherwise, you may want to create your own JDialog which by the way isn't that hard to do. 否则,您可能想要创建自己的JDialog,顺便说一下,这并不难。

Edit 编辑
I'm wrong. 我错了。 You can enable and disable the dialog buttons if you use a little recursion. 如果使用一点递归,则可以启用和禁用对话框按钮。

For example: 例如:

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 state of a JCheckBox, but you can have listeners (DocumentListeners) listening to text field documents if you desire to know if they have data or not. 此代码使用侦听器来检查JCheckBox的状态,但如果您想知道它们是否有数据,您可以让侦听器(DocumentListeners)侦听文本字段文档。 The code then gets the JRootPane that holds the JCheckBox, then the root pane's contentPane, and all components of the dialog are held by this. 然后代码获取包含JCheckBox的JRootPane,然后是根窗格的contentPane,对话框的所有组件都由此保存。 It then recurses through all the components held by the dialog. 然后它会通过对话框保存的所有组件进行递归。 If a component is a Container, it recurses through that container. 如果组件是Container,则它会通过该容器进行递归。 If the component is an AbstractButton (such any JButton or checkbox), it enables or disables -- except for buttons held in the exempt buttons set. 如果组件是AbstractButton(例如任何JButton或复选框),则启用或禁用 - 除了在免除按钮集中保存的按钮。

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

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM