2012-01-06 55 views
4

我已经通过构建一个JPanel,与我的栏目并将它添加到但是我有与按钮麻烦JOption窗格JOptionPane的按钮和一个自定义面板之间的通信

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"); 

做多输入对话框,因为有些字段是必需的。如何让每个必填字段启用后启用“确定”按钮,或者点击按钮进行验证,并且在填充每个必填字段之前不要关闭窗格?

从Java API,我发现这一点:

选项 - 显示可能的选择,用户 可以使对象的数组;如果对象是组件,它们会被正确渲染; 非String对象使用其toString方法呈现;如果这个 参数为null,则选项由外观确定

所以,我不能将自定义按钮作为参数传递吗?

看起来像我将不得不让我自己的JDialog?对于这种情况,我不知道如何使它像JOptionPane一样返回int,任何推荐的教程?

在该示例中是options{"Aceptar", "Cancelar"}其是显示的按钮,

PS。我完全控制了我添加到JPanel的字段。

这是JOptionPane的截图:

enter image description here

回答

2

我不认为你可以取消激活JOptionPane的选择按钮,但仍然使用JOptionPane的一种方法是,只需重新显示它,如果没有设置必需的字段。您可以先显示错误消息JOptionPane首先描述错误,然后显示一个新的JOptionPane ,它保存与第二个参数相同的JPanel - 以便已输入的数据没有丢失。否则,你可能想创建自己的JDialog,顺便说一下,这并不难。

编辑
我错了。如果使用少量递归,您可以启用和禁用对话框按钮。

例如:

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

该代码使用监听器来检查JCheckBox的状态,但你可以有听众(DocumentListeners)听文本字段的文档,如果你希望知道他们是否有数据或不。然后代码获取包含JCheckBox的JRootPane,然后是根窗格的contentPane,并且此对话框的所有组件都由此保存。然后它通过对话框中的所有组件递归。如果一个组件是一个容器,它通过该容器递归。如果组件是一个AbstractButton(如任何JButton或复选框),它将启用或禁用 - 除了按钮设置在豁免按钮中。

更好的与文件的听众例如

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

我建议你来定义一些属性到您的JPanel扩展分类,并使用PropertyChangeListener听的发生变化,并启用/禁用相对按钮。

这是article

另一个问题可能是在组件层次结构中找到ok/cancel按钮,因为JDialog是通过JOptionPane创建的,并且没有对按钮的引用。这是一个有用的thread

您可以使用putClientProperty方法将属性添加到JComponent。 当给定属性发生更改时,会引发PropertyChanged事件。

因此,在您的示例中,您可以定义一个布尔属性,指示需要插入到JDialog中的布尔属性。然后添加一个PropertyChangeListener,通知何时启用/禁用ok按钮。