我正在尝试使用Swing进行文件传输通知。
这个想法是,当通过网络向我的应用程序提供文件时,用户会收到一个JOptionPane询问他或她是否要接受所述文件提供,如果他们的回答是“是”,我想打开一个JFileChooser,因此他们可以浏览到要保存文件的位置。

我遇到的问题是两者都可以单独正常工作,但是当我设置它们以便JOptionPane打开JFileChooser我的应用程序死锁时,它们都可以正常工作。

有人知道这里出了什么问题吗?我尝试调试,但是没有发现任何奇怪的行为来说明为什么会死锁。

编辑:下面的示例代码似乎正常工作,使我相信问题可能出在另一个线程中。更多细节:

我正在使用应用程序线程,ApplicationLayer线程和“主”线程,
主线程根据我定义的字符串生成字节数组,
然后它将生成的字节数组通过我的ApplicationLayer发送到我的应用程序中。

ApplicationLayer是可观察的,Application是它的观察者。

当ApplicationLayer接收到所述字节数组时,它将其解析回字符串,并通知其观察者已这样做。

然后依次通知应用程序。在我的应用程序中,我甚至注意到String是一个文件提供,并因此调用了'saveFile'方法,如下面的代码所示。

代码:

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


}


   }

最佳答案

使用Swing组件的任何代码都必须在EventDispatchThread中运行。您的main()方法应调用invokeLater并在传递的Runnable中执行GUI操作(包括外观部分)。

附言在使用它时,this是在关闭窗口时退出应用程序的首选方法。

09-28 13:00