Tengo un botón en java marco que cuando se pulsa lee un valor de un campo de texto y utiliza esa cadena como un nombre de puerto de intentar conectarse a un dispositivo serie.

Si esta conexión es exitosa, el método devuelve true si no, devuelve false. Si devuelve true quiero el marco de desaparecer. Una serie de otros marcos precisada en otras clases, a continuación, aparecerá con opciones para controlar el dispositivo serie.

Mi problema es: el botón está conectado a una acción de escucha, cuando se pulsa este método es invocado. Si intento utilizar el marco.setVisible(true); método java lanza un resumen botón de error porque soy de los que efectivamente diciendo que desaparezca el marco que contiene el botón antes de que el botón pulse método ha salido. La eliminación de la trama.setVisible(true); permitir que el programa se ejecute correctamente, sin embargo me quedo con una persistente bastidor de conexión que ya no sirve.

Cómo puedo obtener el marco de desaparecer tras pulsar el botón?

package newimplementation1;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/**
*
* @author Zac
*/
public class ConnectionFrame extends JPanel implements ActionListener {
private JTextField textField;
private JFrame frame;
private JButton connectButton;
private final static String newline = "\n";
public ConnectionFrame(){
super(new GridBagLayout());
textField = new JTextField(14);
textField.addActionListener(this);
textField.setText("/dev/ttyUSB0");
connectButton = new JButton("Connect");
//Add Components to this panel.
GridBagConstraints c = new GridBagConstraints();
c.gridwidth = GridBagConstraints.REMAINDER;
c.fill = GridBagConstraints.HORIZONTAL;
add(textField, c);
c.fill = GridBagConstraints.BOTH;
c.weightx = 1.0;
c.weighty = 1.0;
add(connectButton, c);
connectButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
boolean success = Main.mySerialTest.initialize(textField.getText());
if (success == false) {System.out.println("Could not connect"); return;}
frame.setVisible(false);  //THIS DOES NOT WORK!!
JTextInputArea myInputArea = new JTextInputArea();
myInputArea.createAndShowGUI();
System.out.println("Connected");
}
});
}
public void actionPerformed(ActionEvent evt) {
//Unimplemented required for JPanel
}
public void createAndShowGUI() {
//Create and set up the window.
frame = new JFrame("Serial Port Query");
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
//Add contents to the window.
frame.add(new ConnectionFrame());
frame.setLocation(300, 0);
//Display the window.
frame.pack();
frame.setVisible(true);
frame.addComponentListener(new ComponentAdapter() {
@Override
public void componentHidden(ComponentEvent e) {
System.out.println("Exiting Gracefully");
Main.mySerialTest.close();
((JFrame)(e.getComponent())).dispose();
System.exit(0);
}
});
}
}
  • Es poco probable que la aplicación. debe utilizar más de una JFrame. Pequeños elementos de interfaz de usuario podría ser apareció en un JDialog o JOptionPane mientras que un CardLayout o una variedad de componentes Swing puede ser utilizado para incluir más de una interfaz de usuario (o ‘pantalla’) en un recipiente.
  • Para una mejor ayuda antes, publicar un SSCCE.
InformationsquelleAutor Zac | 2011-09-07

4 Comentarios

  1. 4

    Tu problema con esta línea:

      frame.add(new ConnectionFrame());

    Está creando una nueva ConnectionFrame objeto, y así el marco de que el botón se intenta cerrar no es el mismo que el que se muestra, y esta es la fuente de su problema.

    Si lo cambia a,

      //!! frame.add(new ConnectionFrame());
    frame.add(this);

    de modo que los dos JFrames son uno y el mismo, las cosas pueden funcionar más suavemente.

    Pero habiendo dicho eso, su diseño de todo huele mal y me gustaría repensar en una más OOP y menos estática de la moda. También, el uso de cuadros de diálogo, donde los diálogos son necesarios, no marcos, y en lugar de diálogos considere la posibilidad de intercambiar puntos de vista (JPanels) a través de CardLayout como una mejor opción.

    A mí mismo, me gustaría crear un «tonto» GUI para este, uno que crea un JPanel (aquí en mi ejemplo se extiende un JPanel para la simplicidad, pero me gustaría evitar que se amplía, si no es necesario), y me gustaría que aquel que está llamando a este código de decidir qué hacer con la información a través de algún tipo de control. Por ejemplo,

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    @SuppressWarnings("serial")
    public class ConnectionPanel extends JPanel {
    private JTextField textField;
    private JButton connectButton;
    private ConnectionPanelControl control;
    public ConnectionPanel(final ConnectionPanelControl control) {
    super(new GridBagLayout());
    this.control = control;
    ActionListener listener = new ActionListener() {
    public void actionPerformed(ActionEvent e) {
    if (control != null) {
    control.connectButtonAction();
    }
    }
    };
    textField = new JTextField(14);
    textField.addActionListener(listener);
    textField.setText("/dev/ttyUSB0");
    connectButton = new JButton("Connect");
    GridBagConstraints c = new GridBagConstraints();
    c.gridwidth = GridBagConstraints.REMAINDER;
    c.fill = GridBagConstraints.HORIZONTAL;
    add(textField, c);
    c.fill = GridBagConstraints.BOTH;
    c.weightx = 1.0;
    c.weighty = 1.0;
    add(connectButton, c);
    connectButton.addActionListener(listener);
    }
    public String getFieldText() {
    return textField.getText();
    }
    }

    De nuevo, algo fuera de la interfaz gráfica de usuario sencilla permitiría tomar decisiones sobre qué hacer con el texto que el campo de texto contiene y qué hacer con la interfaz gráfica que muestra este JPanel:

    public interface ConnectionPanelControl {
    void connectButtonAction();
    }

    También, es probable que hacer cualquier conexión en un subproceso en segundo plano para no congelar su interfaz gráfica de usuario, probablemente un SwingWorker. Tal vez algo como esto:

    import java.awt.event.ActionEvent;
    import java.util.concurrent.ExecutionException;
    import javax.swing.*;
    @SuppressWarnings("serial")
    public class MyMain extends JPanel {
    public MyMain() {
    add(new JButton(new ConnectionAction("Connect", this)));
    }
    private static void createAndShowGui() {
    JFrame frame = new JFrame("My Main");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(new MyMain());
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
    }
    public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
    public void run() {
    createAndShowGui();
    }
    });
    }
    }
    @SuppressWarnings("serial")
    class ConnectionAction extends AbstractAction {
    private MyMain myMain;
    private ConnectionPanel cPanel = null;
    private JDialog dialog = null;
    public ConnectionAction(String title, MyMain myMain) {
    super(title);
    this.myMain = myMain;
    }
    @Override
    public void actionPerformed(ActionEvent e) {
    if (dialog == null) {
    dialog = new JDialog(SwingUtilities.getWindowAncestor(myMain));
    dialog.setTitle("Connect");
    dialog.setModal(true);
    cPanel = new ConnectionPanel(new ConnectionPanelControl() {
    @Override
    public void connectButtonAction() {
    final String connectStr = cPanel.getFieldText();
    new MySwingWorker(connectStr).execute();
    }
    });
    dialog.getContentPane().add(cPanel);
    dialog.pack();
    dialog.setLocationRelativeTo(null);
    }
    dialog.setVisible(true);
    }
    private class MySwingWorker extends SwingWorker<Boolean, Void> {
    private String connectStr = "";
    public MySwingWorker(String connectStr) {
    this.connectStr = connectStr;
    }
    @Override
    protected Boolean doInBackground() throws Exception {
    //TODO: make connection and then return a result
    //right now making true if any text in the field
    if (!connectStr.isEmpty()) {
    return true;
    }
    return false;
    }
    @Override
    protected void done() {
    try {
    boolean result = get();
    if (result) {
    System.out.println("connection successful");
    dialog.dispose();
    } else {
    System.out.println("connection not successful");
    }
    } catch (InterruptedException e) {
    e.printStackTrace();
    } catch (ExecutionException e) {
    e.printStackTrace();
    }
    }
    }
    }
    • maldito .. de nuevo demasiado tarde 🙂
    • Wow gracias a todos los que respondieron de una forma increíblemente rápida. He publicado esta pregunta, a continuación, salió por 15 minutos, pensando que allí podría ser 1 respuesta si tuve suerte … y hubo 4!
    • por favor, consulte editar a mi respuesta anterior.
  2. 5

    Ejecutando el fragmento (después de quitar/ajustar alrededor de la clases personalizadas), arroja un NPE. La razón es que el marco estás accediendo es nulo. Y eso es porque nunca conjunto. Mejor no confiar en cualquier campo, deje el botón de encontrar su principal ancestro y ocultar que, al igual que en

            public void actionPerformed(final ActionEvent e) {
    boolean success = true;
    if (success == false) {
    System.out.println("Could not connect");
    return;
    }
    Window frame = SwingUtilities.windowForComponent((Component) e
    .getSource());
    frame.setVisible(false); //no problem :-)
    }
    • +1 para windowForComponent. Debe ser aceptado como una respuesta
  3. 1

    Su código sería mucho más legible si se denomina JFrame instancias xxxFrame, y JPanel instancias xxxPanel. Nomenclatura JPanel instancias xxxFrame hace cosas muy confuso.

    También sería de ayuda si usted se pega la traza de la pila de la excepción.

    Sospecho que el problema viene del hecho de que el marco es nulo. Esto es debido al hecho de que el marco de campo sólo se inicializa en el createAndShowGUI método, pero este método no muestra el actual panel de conexión, pero uno nuevo, que por lo tanto tienen un valor null campo marco:

    ConnectionFrame firstPanel = new ConnectionFrame();
    //The firstPanel's frame field is null
    firstPanel.createAndShowGUI();
    //the firstPanel's frame field is now not null, but
    //the above call opens a JFrame containing another, new ConnectionFrame, 
    //which has a null frame field

    El código de createAndShowGUI debe contener

    frame.add(this);

    lugar de

    frame.add(new ConnectionFrame());
  4. 1

    para el Swing GUI es mejor crear sólo una vez JFrame y otro De Nivel Superior De Los Contenedores sería JDialog o JWindow(onu-decoradas de forma predeterminada),

    simple ejemplo aquí

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    public class SuperConstructor extends JFrame {
    private static final long serialVersionUID = 1L;
    public SuperConstructor() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setPreferredSize(new Dimension(300, 300));
    setTitle("Super constructor");
    Container cp = getContentPane();
    JButton b = new JButton("Show dialog");
    b.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent evt) {
    FirstDialog firstDialog = new FirstDialog(SuperConstructor.this);
    }
    });
    cp.add(b, BorderLayout.SOUTH);
    JButton bClose = new JButton("Close");
    bClose.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent evt) {
    System.exit(0);
    }
    });
    add(bClose, BorderLayout.NORTH);
    pack();
    setVisible(true);
    }
    public static void main(String args[]) {
    EventQueue.invokeLater(new Runnable() {
    @Override
    public void run() {
    SuperConstructor superConstructor = new SuperConstructor();
    }
    });
    }
    private class FirstDialog extends JDialog {
    private static final long serialVersionUID = 1L;
    FirstDialog(final Frame parent) {
    super(parent, "FirstDialog");
    setPreferredSize(new Dimension(200, 200));
    setLocationRelativeTo(parent);
    setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
    setModalityType(Dialog.ModalityType.DOCUMENT_MODAL);
    JButton bNext = new JButton("Show next dialog");
    bNext.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent evt) {
    SecondDialog secondDialog = new SecondDialog(parent, false);
    }
    });
    add(bNext, BorderLayout.NORTH);
    JButton bClose = new JButton("Close");
    bClose.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent evt) {
    setVisible(false);
    }
    });
    add(bClose, BorderLayout.SOUTH);
    pack();
    setVisible(true);
    }
    }
    private int i;
    private class SecondDialog extends JDialog {
    private static final long serialVersionUID = 1L;
    SecondDialog(final Frame parent, boolean modal) {
    //super(parent); //Makes this dialog unfocusable as long as FirstDialog is visible
    setPreferredSize(new Dimension(200, 200));
    setLocation(300, 50);
    setModal(modal);
    setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
    setTitle("SecondDialog " + (i++));
    JButton bClose = new JButton("Close");
    bClose.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent evt) {
    setVisible(false);
    }
    });
    add(bClose, BorderLayout.SOUTH);
    pack();
    setVisible(true);
    }
    }
    }

    mejor sería re-uso de Nivel Superior de los Contenedores, como crear un montón de Nivel Superior de los Contenedores en tiempo de ejecución (memoria de posible falta)

Dejar respuesta

Please enter your comment!
Please enter your name here