我正在尝试使用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是在关闭窗口时退出应用程序的首选方法。