2016-11-26 6 views
0

イメージのWebサイトをスクラップしてイメージファイルの名前とプロパティをリストに配置するプログラムを作成していますが、問題はGUIを使用してURLからデータを取得しようとするときですプログラムは私のテーブルモデルの情報を表示するのに約20〜30秒かかりますが、GUIなしで(コンソールとシンプルなシステムからprintlnで)実行すると、わずか2〜4秒しかかかりません。ここに私のGUIコード:GUIでプログラムを実行するのが遅い

public class ImageDownloader extends JFrame { 

private JPanel contentPane; 
private JTextField urlTextField; 
private JButton btnCheck; 
private JButton btnDownload; 
private JButton btnDownloadAll; 
private JTable table; 

private String imgUrl; 
private String url; 

Document document; 
Elements media; 

public static void main(String[] args) { 
    EventQueue.invokeLater(new Runnable() { 
     public void run() { 
      try { 
       ImageDownloader frame = new ImageDownloader(); 
       frame.setVisible(true); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    }); 
} 

public ImageDownloader() { 
    setTitle("Image Downloader"); 
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    setBounds(100, 100, 565, 300); 
    contentPane = new JPanel(); 
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); 
    contentPane.setLayout(new BorderLayout(0, 0)); 
    setContentPane(contentPane); 

    JPanel panel = new JPanel(); 
    FlowLayout flowLayout = (FlowLayout) panel.getLayout(); 
    flowLayout.setAlignment(FlowLayout.LEFT); 
    contentPane.add(panel, BorderLayout.NORTH); 

    JLabel lblWebsiteUrl = new JLabel("Website URL:"); 
    panel.add(lblWebsiteUrl); 

    urlTextField = new JTextField(); 
    panel.add(urlTextField); 
    urlTextField.setColumns(30); 

    btnCheck = new JButton("Check"); 
    btnCheck.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
      List<Images> images = new ArrayList<>(); 

      url = urlTextField.getText(); 

      if(url.isEmpty()) { 
       JOptionPane.showMessageDialog(ImageDownloader.this, "Please enter a website URL", "Input Error", JOptionPane.ERROR_MESSAGE); 
      } else { 

       try { 
        document = Jsoup.connect(urlTextField.getText()).userAgent("Mozilla").timeout(10 * 1000).get(); 

        media = document.select("[src]"); 

        for(Element src : media) { 
         if(src.tagName().equals("img")) { 
          imgUrl = src.attr("abs:src"); 
          URL url = new URL(imgUrl); 
          long size = url.openConnection().getContentLengthLong(); 
          images.add(new Images(src.tagName(), src.attr("abs:src"), src.attr("width"), src.attr("height"), size)); 
         } 
        } 

        ImageDownloaderTableModel tableModel = new ImageDownloaderTableModel(images); 

        table.setModel(tableModel); 
       } catch (IOException e1) { 
        JOptionPane.showMessageDialog(ImageDownloader.this, "Error loading website, The site that you are trying to reach is either down or does not exist..", "Error Loading", JOptionPane.ERROR_MESSAGE); 
        e1.printStackTrace(); 
       } 
      } 
     } 
    }); 
    panel.add(btnCheck); 

    JPanel panel_1 = new JPanel(); 
    contentPane.add(panel_1, BorderLayout.SOUTH); 

    btnDownloadAll = new JButton("Download All"); 
    btnDownloadAll.addActionListener(new ActionListener() { 

     public void actionPerformed(ActionEvent arg0) { 
      try { 
       media = document.select("img"); 

       for(Element src : media) { 
        String strImgUrl = src.attr("abs:src"); 
        downloadImage(strImgUrl); 
       } 
      } catch(Exception ex) { 
       ex.printStackTrace(); 
      } 
     }   
    }); 
    panel_1.add(btnDownloadAll); 

    btnDownload = new JButton("Download"); 
    panel_1.add(btnDownload); 

    JScrollPane scrollPane = new JScrollPane(); 
    contentPane.add(scrollPane, BorderLayout.CENTER); 

    table = new JTable(); 
    scrollPane.setViewportView(table); 
} 

public static void downloadImage(String imgUrl) { 
    String strImgUrl = imgUrl.substring(imgUrl.lastIndexOf("/") + 1); 

    try { 
     URL urlImage = new URL(imgUrl); 
     InputStream in = urlImage.openStream(); 

     byte[] buffer = new byte[4096]; 
     int n = -1; 

     OutputStream os = new FileOutputStream(strImgUrl); 

     while((n = in.read(buffer)) != -1) { 
      os.write(buffer, 0, n); 
     } 

     os.close(); 

     System.out.println("Saved.."); 
    } catch(IOException ex) { 
     ex.printStackTrace(); 
    } 
} 
} 
+0

SwingWorkerのように、バックグラウンドスレッドではなく、Swingイベントスレッドですべての重労働をしているようです。なぜですか? –

答えて

3

SwingWorkerクラスのドキュメントには、あなたの状況の優れた要約を持っています

時間のかかるタスクは、イベントディスパッチスレッド上で実行するべきではありません。そうしないと、アプリケーションが応答しなくなります。

あなたのケースでは、1つまたは複数のファイルをダウンロードするのは時間がかかる作業で、Event Dispatch Thread(別名EDT)からダウンロードしています。

SwingWorkerのは、あなたがいずれかで行うとき、またはバックグラウンドスレッドでの実行時間の長いタスクの実行を持っているし、UIへのアップデートを提供する必要がある状況のために設計されています

はSwingWorkerのクラスは、あなたの問題への解決策を提供します処理中。


私はまた、アクションリスナー(またはアクション)は、コードの長い部分を含むべきではないことを主張するだろう。それをメソッド内にラップし、メソッドをアクションリスナー(アクション)から呼び出す方が良いです。 を使用してモーダルダイアログを開いている場合は、その新しいダイアログを開く前にすべての保留中のUIメッセージが処理されるようにそのメソッドをinvokeLaterとします。これは、他のUI関連の問題(フォーカスに関連する問題が頭に浮かぶ)を横断する一般的なアドバイスです。

たとえば、JButtonのActionListenerからinvokeLaterがイベントディスパッチスレッドから呼び出された場合、保留中のすべてのイベントが処理されるまで、doRun.run()は遅延されます。

2

まあ、答えは非常に簡単で明らかです。アプリケーションをGUIモードで実行すると、ビジュアル化とグラフィックス用の余分なスレッドと、JPanelまたはJButtonのようなすべてのコンポーネントがあります。これらはプログラムのために特別な処理を行い、ネットワークスレッドとメインのGUIスレッドの間にコンテキストスイッチがあります。

コンソールプリントは、グラフィックス処理が煩雑ではなく、より高速に実行できます。

また、AFAIKネットワークはのブロックの動作をブロックします。つまり、ネットワークコールが完了するまで待つ必要があります。これは、コンテキストがGUIスレッドからネットワークスレッドに移動して再び戻ってくる理由です。

関連する問題