2016-09-11 10 views
0

シングルサインオンを使用するログインを作成しています。これを行うには、ユーザーがログインする会社がSSOを有効にしている場合は、JavaFX WebViewが開き、ユーザーはログインできるようになります。このログインは完全にWebベースなので、私の側で実際にデータをキャプチャする必要はありません。JavaFXアプリケーションでshowAndWaitを使用する

私は2つのクラス、LoginManagerSSOを持っています。 LoginManagerは、会社がSSOEnabledであるかどうかを確認し、そうであればSSOに移動します。ここから、UIを作成してPlatform.runLater()を使用して、webviewというメソッドを開きます。しかし、私のプログラムはinitJFXPanelに行き、即座にLoginManagerに戻ってコードを実行すると問題が発生します。

SSOをすべて通過して特定のWebページに到達し、次にframe.dispose()を使用してから、LoginManagerに戻って続行してください。私はStageshowAndWait()を使用する必要があると思うが、私はこれについてどうやって行くのかは分からない。

私はinitJFXPanel内のステージを作成しようとしたが、それが何かをする機会を得る前に、それが戻ってLoginManagerに行くように、これは動作しませんでした、と私はまたcreatePopupのステージを設定しようとしたが、私は何を使用するかわかりませんでしたステージやシーンとして。

LoginManagerクラスすべてのヘルプは高く評価され

public class SSO { 

    private JFrame frame; 
    private JFXPanel fxPanel; 
    private JPanel containerPanel; 
    final static String WEBVIEW = "WebView"; 

    public SSO(){ 
     createPopup(); 
    } 

    private void createPopup(){ 

     Dimension size = new Dimension(480, 80); 

     frame = new JFrame("Web Login"); 
     frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 

     containerPanel = new JPanel(new CardLayout()); 

     fxPanel = new JFXPanel(); 
     fxPanel.setSize(size); 

     Platform.runLater(() -> initJFXPanel(frame, fxPanel)); 

     containerPanel.add(fxPanel, WEBVIEW); 

     frame.add(containerPanel, BorderLayout.CENTER); 

     frame.setPreferredSize(size); 
     frame.setResizable(false); 
     frame.getRootPane().setWindowDecorationStyle(JRootPane.NONE); 

     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 

    } 

    private void initJFXPanel(final JFrame frame, final JFXPanel fxPanel){ 

     Group group = new Group(); 
     Scene scene = new Scene(group); 
     fxPanel.setScene(scene); 

     WebView webview = new WebView(); 

     group.getChildren().add(webview); 
     webview.setMinSize(500, 640); 
     webview.setMaxSize(500, 640); 

     CookieManager cookieManager = new CookieManager(); 
     java.net.CookieHandler.setDefault(cookieManager); 

     webview.getEngine().load("http://google.com/"); 


     if(webview.getEngine().getLocation().equalsIgnoreCase("cookie url")) { 
      // harvest the cookies 
     } 
     else if(webview.getEngine().getLocation().equalsIgnoreCase("end url")) { 
      frame.dispose(); 
     } 

    } 

} 

public class LoginManager { 

    private boolean bSSOEnabled = true; 

    private void Login() { 

     // get company details 

     if(bSSOEnabled) { 
      new SSO(); 
     } 

     // once SSO is done, continue with execution 
    } 
} 

SSOクラス:

は、ここに私のコードです。私は一日中このことに固執しており、何をすべきか分からない。

+0

1.あなたは、SwingやJavaFXのを混在させる必要がありますか? 1つのツールキットしか使用できないのであれば、より簡単になります。同じアプリケーションで 'JFrame'と' Stage'の両方を使いたくないのであれば、Swingを使うことを約束しているなら 'JFXPanel'に' WebView'を埋め込み、 'JFrame'に表示するのは正しいアプローチ。 2. 'LoginManager'の' login() 'メソッドはどのスレッドから呼び出されますか? –

+0

@James_D 1.いいえ特に何も使う必要はありません。私はUIを書いていなかった、他の誰かがやった、プロジェクトを放棄した後、私はそれで集中していたので、それが最良の方法であれば、showAndWaitを実装するために必要です。2.私はそれがメインのものだと思いますか? – Rachael

+0

残りのUIは既にSwingまたはJavaFXで記述されていますか? –

答えて

0

アプリケーションがSwingアプリケーションで、あなたはWebViewを使用する必要がある場合は、正しいアプローチは、あなたのコードに示されているものですすなわちSwingのウィンドウを使用してJFXPanelWebViewを埋め込みます。 2つのフレームワークのウィンドウを混在させるのは悪い考えですので、Stageを使用しないことをお勧めします。

ユーザーがウィンドウを閉じるまで、つまりJavaFX Stage.showAndWait()呼び出しのSwingに相当するコードをSwingブロックで使用する方法は、JDialogを使用してモーダルにすることです。他のウィンドウへの入力をブロックするだけでなく、これは、ダイアログが閉じられるまで(AWT Event Dispatchスレッドの)実行をブロックします。

これを少し難解にするのは、AWTイベントディスパッチスレッド、JavaFXアプリケーションスレッド、およびメインスレッドの3つのスレッドを使用することです。モーダルダイアログを表示するとAWT Event Dispatchスレッドがブロックされますが、(問題が正しく分かれば)メインスレッドをブロックする必要があります。さらに、AWT Event DispatchスレッドでSwingコンポーネントを作成、変更、および表示するだけで、JavaFXアプリケーションスレッドでJavaFXノードを作成、変更、および表示する必要があります。あなたがSSOをインスタンス化した場合、ダイアログが却下されるまで今、コードがブロックされます

public class SSO { 

    private JDialog dialog; 
    private JFXPanel fxPanel; 
    private JPanel containerPanel; 
    final static String WEBVIEW = "WebView"; 

    public SSO(){ 
     // creates Swing components: MUST be called on AWT Event thread 
     createPopup(); 
    } 

    private void createPopup(){ 

     Dimension size = new Dimension(480, 80); 

     dialog = new JDialog(); 
     dialog.setTite("Web Login"); 

     // make dialog modal: 
     dialog.setModalityType(ModalityType.APPLICATION_MODAL); 

     // oops: don't want this: 
     // dialog.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
     // but this: 
     dialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 

     containerPanel = new JPanel(new CardLayout()); 

     fxPanel = new JFXPanel(); 
     fxPanel.setSize(size); 

     Platform.runLater(() -> initJFXPanel(dialog, fxPanel)); 

     containerPanel.add(fxPanel, WEBVIEW); 

     dialog.add(containerPanel, BorderLayout.CENTER); 

     dialog.setPreferredSize(size); 
     dialog.setResizable(false); 
     dialog.getRootPane().setWindowDecorationStyle(JRootPane.NONE); 

     dialog.pack(); 
     dialog.setLocationRelativeTo(null); 
     dialog.setVisible(true); 

    } 

    private void initJFXPanel(final JDialog dialog, final JFXPanel fxPanel){ 

     Group group = new Group(); 
     Scene scene = new Scene(group); 
     fxPanel.setScene(scene); 

     WebView webview = new WebView(); 

     group.getChildren().add(webview); 
     webview.setMinSize(500, 640); 
     webview.setMaxSize(500, 640); 

     CookieManager cookieManager = new CookieManager(); 
     java.net.CookieHandler.setDefault(cookieManager); 

     webview.getEngine().load("http://google.com/"); 


     if(webview.getEngine().getLocation().equalsIgnoreCase("cookie url")) { 
      // harvest the cookies 
     } 
     else if(webview.getEngine().getLocation().equalsIgnoreCase("end url")) { 
      // this will hide the dialog and release the event dispatch thread 
      // that is waiting for it, but it must be called on the event dispatch thread 
      // not sure of your exact requirements, but you may need to do this 
      // in the if clause as well? 
      SwingUtilities.invokeLater(() -> dialog.setVisible(false)); 
     } 

    } 

} 

は、だから私はあなたがこのような何かをしたいと思います。ただし、AWT Event Dispatchスレッドでこれを行う必要があります。メインスレッドで完了するのを待つトリックは、 FutureTaskとしてを呼び出し、 SwingUtilities.invokeLater()にサブミットし、メインスレッドに戻って FutureTaskget()と呼び出してください。これはタスクが完了するまでブロックされます完了する。ここで注意する必要があります:あなたが誤ってイベントディスパッチスレッドでこれを行うと、デッドロック状態になります。イベントディスパッチスレッドがブロックされ、イベントディスパッチスレッド上で何かが起きるのを待っています。安全であることを守る。

だからあなたのコードは、おそらくこのように見える必要があります:

public class LoginManager { 

    private boolean bSSOEnabled = true; 

    private void Login() { 

     // get company details 

     if(bSSOEnabled) { 
      if (SwingUtilities.isEventDispatchThread()) { 
       // already on EDT, just invoke the SSO which will block 
       // until the dialog is dismissed: 
       new SSO(); 
      } else { 
       // create FutureTask to show dialog, etc: 
       FutureTask<Void> ssoTask = new FutureTask<>(SSO:new, null); 
       // submit task to AWT event dispatch thread: 
       SwingUtilities.invokeLater(ssoTask); 
       // wait for task to complete, i.e. for dialog to be dismissed: 
       try { 
        ssoTask.get(); 
       } catch (InterruptedException exc) { 
        // thread was interrupted, representing cancelation of some kind: 
        System.out.println("Thread interrupted"); 
        Thread.currentThread().interrupt(); 
       } catch (ExecutionException ee) { 
        // something went wrong... 
        throw new RuntimeException(ee); 
       } 
      } 
     } 



    // once SSO is done, continue with execution 
    } 
} 
+0

これは素晴らしいです、ありがとうございます!ダイアログのフレームを入れ替えると、LoginManagerのスレッドコードがなくても動作しているように見えますが、これはプログラムに悪影響を及ぼしますか? – Rachael

関連する問題