Question

I'm trying to make a file transfer notification using Swing. The idea is that when my application is offered a file through the network, the user receives a JOptionPane asking if he or she wants to accept said file offer, in the event their answer is yes I want to open a JFileChooser so they can browse to the location where they want to save the file.

The problem I'm having is that both work just fine individually but when I set them up so that the JOptionPane opens the JFileChooser my application deadlocks.

Does anyone have an idea what is going wrong here? I tried debugging but haven't found any strange behaviour that would suggest why it would deadlock.

EDIT: the below sample code seems to work just fine, making me believe that the problem might lie in another thread. Further details:

I am using an Application Thread, ApplicationLayer Thread and a 'Main' Thread, The Main thread generates a byte array based on a String I define, then it sends the generated byte array through my ApplicationLayer into my Application.

The ApplicationLayer is an Observable and the Application is it's Observer.

When the ApplicationLayer receives said byte array it parses it back into a string and notifies it's observer that it has done so.

The Application then in turn is notified of this. In my even the Application notices the String is a file offer and accordingly calls upon the 'saveFile' method as seen in the code below.

The code:

  package application;

    public class GUI extends JFrame implements ActionListener, ItemListener, Observer {

private JPanel cp = new JPanel();
private JPanel ulp = new JPanel();
private JTextField  myMessage;
private JTextArea   taMessages;
    // Menu Bar Elements
JMenuBar menuBar;
JMenu menu, submenu;

public GUI(){
    super();    
    this.setLayout(new BorderLayout());

    setPreferredSize(new Dimension(800, 600));
    setMinimumSize(new Dimension(800, 600));

    buildBarMenu();
    buildChatMenu();

    addWindowListener(new WindowAdapter() {
        public void windowClosing(final WindowEvent e) {
            e.getWindow().dispose();
        }
        public void windowClosed(final WindowEvent e) {
            System.exit(0);
        }
    }
            );

    pack();
    validate();
    setVisible(true);

}

    public static void main(final String[] args) {
    try {
        for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
            if ("Nimbus".equals(info.getName())) {
                UIManager.setLookAndFeel(info.getClassName());
                break;
            }
        }
    } catch (Exception e) {
        // If Nimbus is not available, fall back to cross-platform
        try {
                     UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
        } catch (Exception ex) {

        }
    }
    new GUI();
    }
    private void buildBarMenu(){
    // Create the menu bar
    JMenuBar menuBar = new JMenuBar();

    // Create a menu
    JMenu menu = new JMenu("File");

    menu.setHorizontalTextPosition(SwingConstants.CENTER);
    menu.setVerticalTextPosition(SwingConstants.BOTTOM);

    menuBar.add(menu);

    // SendFile Item
    JMenuItem sendFileItem = new JMenuItem("Send File");
    sendFileItem.addActionListener(new ActionListener(){
        @Override
        public void actionPerformed(ActionEvent e) {
            saveFile(); // Put whatever here
        }
    });
    // Exit item
    JMenuItem exitItem = new JMenuItem("Exit");
    exitItem.addActionListener(new ActionListener(){
        @Override
        public void actionPerformed(ActionEvent e) {

            System.exit(0);
        }
    });
    menu.add(sendFileItem);
    menu.add(exitItem);

    this.setJMenuBar(menuBar);
    }

private void buildChatMenu() {

    this.add(cp, BorderLayout.CENTER);
    this.add(ulp, BorderLayout.EAST);

}

/**
 * Method to be called for saving files when a file transfer
 * request is received
 * @return the path to save the file to
 */
public String saveFile(){

    int choice = JOptionPane.showConfirmDialog(GUI.this, "You are being offered a file, accept?", "File Offer",
            JOptionPane.YES_NO_OPTION);

    if (choice == JOptionPane.YES_OPTION){
        System.out.println("yes");
        JFileChooser c = new JFileChooser();

        int rVal = c.showOpenDialog(GUI.this);
        if (rVal == JFileChooser.APPROVE_OPTION) {

        }
        if (rVal == JFileChooser.CANCEL_OPTION) {

        }

    }else{
        System.out.println("no");
    }
    return null;

}

public void save2(){
    JFileChooser c = new JFileChooser();


    int rVal = c.showOpenDialog(GUI.this);
    if (rVal == JFileChooser.APPROVE_OPTION) {
        System.exit(0);

    }
    if (rVal == JFileChooser.CANCEL_OPTION) {
        System.exit(0);

    }
}


@Override
public void itemStateChanged(ItemEvent e) {
    // TODO Auto-generated method stub

}

@Override
public void actionPerformed(ActionEvent e) {
    // TODO Auto-generated method stub

}

    @Override
public void update(Observable o, Object arg) {


    if(arg instanceof ChatMessage){
        cp.addMessage(((ChatMessage) arg).getNickname(), ((ChatMessage) arg).getMessage());
    }
    else if(arg instanceof FileOfferMessage){

        cp.addMessage("FILE OFFER", ((FileOfferMessage) arg).getFileName() + " | File Size: " + ((FileOfferMessage) arg).getFileSize() + " bytes");
        saveFile();
    }


}


   }
Was it helpful?

Solution

Any code that uses Swing components has to run in the EventDispatchThread. Your main() method should call invokeLater and perform the GUI operations (including the look and feel parts) in a passed Runnable.

P.S. While you're at it, this is the preferred way of exiting an application on window closure.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top