1

对于 XLSX 文件 rt.getFontAtIndex(i) 中的某些单元格,部分只是崩溃,控制只是退出函数甚至调用函数。Out Swing 窗口仍然打开。我不知道为什么没有任何异常控制会超出代码。

    public static String addLinkTagInRichTextForUnderscores(XSSFRichTextString rt) {
        System.out.print("Was here 1\n");
        if(rt.length()==0 || rt == null) {
            return " ";
        }
        String outString = rt.toString();
        //String finalString = "";
        List<Integer> startIndexListOfUL = new ArrayList<Integer>();

        boolean continuing = false;
        System.out.println(outString +" A "+ rt.length() +"\n\n");

        for(int i=1;i<rt.length();i++) {
            System.out.print("Was here at font "+ i);
            XSSFFont font = null;
            try{
            //font = rt.getFontAtIndex(i);
            } catch(Error e){
                e.fillInStackTrace();
            }
            System.out.print("Was here too" + rt.getFontAtIndex(i));
            if(font!= null) {
                if(XSSFFont.U_SINGLE == font.getUnderline()) {

                    if(!continuing){
                        startIndexListOfUL.add(new Integer(i));
                        continuing = true;
                    }

                }else{
                    continuing = false;
                }
            } else {
                //System.out.println("No font " + i);
            }
        }

        System.out.println(startIndexListOfUL);

        if(startIndexListOfUL.size()==0) {
            //finalString = outString;
            return " ";
        } else {
            int spacing = 0;
            for(int i = 0; i<startIndexListOfUL.size(); i++) {
                outString =     insertStringAt(outString,startIndexListOfUL.get(i) + spacing,"<link>");
                spacing = spacing + 6;
            }
        }

        //just remove redundant <link> tags
        outString = outString.replaceAll("(<link>[\\s]?<link>)", "<link>");
        //System.out.println("Final >>>> " + outString);
        return outString;
    }
4

2 回答 2

2

XSSFRichTextString.getFontAtIndex() 的文档说它将返回一个 XSSFFont,如果没有应用字体或索引超出范围,则返回 null。所以你需要在使用它之前查看返回值是否为null(包括在System.out.print调用中),否则你会得到一个NullPointerException并且控件会离开代码块。

另外,请注意捕获错误无济于事 - NPE 是 RuntimeException,而不是 Error 的子类,因此无论如何都不会在您的 try/catch 块中捕获。除了少数例外(没有双关语),您应该在代码中进行适当的检查(确保返回的引用不为空,检查索引是否符合数组长度等),而不是试图捕获未经检查的异常。

于 2013-09-10T20:16:32.860 回答
1

如果您的问题是“为什么我的 Swing GUI 应用程序没有在后台线程崩溃的情况下崩溃?”,答案是 Swing GUI 与其他 Java 程序没有什么不同。如果您在任何程序中使线程崩溃,并且 1) 异常不会导致 JVM 崩溃,并且 2) 异常信息不会渗透到调用代码中,那么调用代码将幸福地不知道发生了任何事情.

解决方案是在发生这种情况时通知 Swing GUI。例如,如果您使用 SwingWorker 创建后台线程,它的get()方法将传递 SwingWorker 的 doInBackground 方法中可能发生的任何异常。例如:

import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.concurrent.ExecutionException;
import javax.swing.*;

public class SwingTest {
   private JPanel mainPanel = new JPanel();
   private JTextField numberField = new JTextField("5x", 5);

   @SuppressWarnings("serial")
   public SwingTest() {
      MyFailAction myFailAction = new MyFailAction();
      numberField.setAction(myFailAction);
      mainPanel.add(new JLabel("String to parse into an int:"));
      mainPanel.add(numberField);
      mainPanel.add(new JButton(myFailAction));
   }

   public JComponent getMainPanel() {
      return mainPanel;
   }

   private class MyFailAction extends AbstractAction {

      public MyFailAction() {
         super("Push to Fail");
         putValue(MNEMONIC_KEY, KeyEvent.VK_P);
      }

      @Override
      public void actionPerformed(ActionEvent arg0) {
         String text = numberField.getText();
         final MySwingWorker mySw = new MySwingWorker(text);
         mySw.addPropertyChangeListener(new PropertyChangeListener() {

            @Override
            public void propertyChange(PropertyChangeEvent evt) {
               if (evt.getPropertyName().equals("state")) {
                  if (evt.getNewValue().equals(SwingWorker.StateValue.DONE)) {
                     try {
                        // **** here I call get() on my SwingWorker ****
                        int value = mySw.get();
                        JOptionPane.showMessageDialog(mainPanel, "value is "
                              + value);
                     } catch (InterruptedException | ExecutionException e) {
                        if (e.getCause() instanceof NumberFormatException) {
                           String message = "A NumberFormatException has occurred when trying to parse \""
                                 + numberField.getText() + "\" to an int\n" +
                                 "Reseting field to \"0\"";
                           JOptionPane.showMessageDialog(mainPanel, message,
                                 "NumberFormatException",
                                 JOptionPane.ERROR_MESSAGE);
                        }

                        StringBuilder sb = new StringBuilder();
                        sb.append(e.getMessage() + "\n");
                        for (StackTraceElement ele : e.getStackTrace()) {
                           sb.append(ele.toString() + "\n");
                        }
                        sb.append("\n");
                        sb.append("*****   Cause:   *****\n");
                        sb.append(e.getCause().getLocalizedMessage());
                        for (StackTraceElement ele : e.getCause()
                              .getStackTrace()) {
                           sb.append(ele.toString() + "\n");
                        }
                        JTextArea textArea = new JTextArea(sb.toString());
                        JScrollPane message = new JScrollPane(textArea);
                        JOptionPane.showMessageDialog(mainPanel, message,
                              "Error Specifics", JOptionPane.ERROR_MESSAGE);
                        numberField.setText("0");
                     }
                  }
               }
            }
         });
         mySw.execute();
      }
   }

   private class MySwingWorker extends SwingWorker<Integer, Void> {
      private static final long SLEEP_DELAY = 1000;
      private String text;

      public MySwingWorker(String text) {
         this.text = text;
      }

      @Override
      protected Integer doInBackground() throws Exception {
         Thread.sleep(SLEEP_DELAY);
         int value = Integer.parseInt(text);
         return value;
      }
   }

   private static void createAndShowGui() {
      SwingTest swingTest = new SwingTest();

      JFrame frame = new JFrame("SwingTest");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(swingTest.getMainPanel());
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}
于 2013-09-10T20:14:51.867 回答