2015-10-13 15 views
8

'a başvurmadan açın. Tıklandığında, harici bir tarayıcıda açılacak bir bağlantı istiyorum. JavaFx 8: Bir tarayıcıdaki bir bağlantıyı Uygulama

final Hyperlink hyperlink = new Hyperlink("http://www.google.com"); 
hyperlink.setOnAction(t -> { 
    application.getHostServices().showDocument(hyperlink.getText()); 
}); 

Ancak Application bir başvuru yok: internet üzerinde atıf

olağan yöntem olarak görünmektedir. Bağlantı, bir fxml dosyası aracılığıyla açılan bir Denetleyiciden açılan Diyalog penceresinden açılır, böylece Uygulama nesnesine başvuru almak oldukça acı verici olur.

Bunu yapmanın kolay bir yolu bilen var mı? Bu AWT yığınına bir bağımlılık tanıtacak olduğunu ancak

URI uri = ...; 
if (Desktop.isDesktopSupported()){ 
    Desktop desktop = Desktop.getDesktop(); 
    if (desktop.isSupported(Desktop.Action.BROWSE)){ 
     desktop.browse(uri); 
    } 
} 

Not:

Alkış

cevap

14

Çözüm 1: Uygulamanız boyunca HostServices numaralı başvuruya başvurun.

Bu, muhtemelen tahmin ettiğiniz "oldukça acı verici" yaklaşıma benzer. MainController sonra

public void start(Stage primaryStage) throws Exception { 

    FXMLLoader loader = new FXMLLoader(getClass().getResource("main.fxml")); 
    Parent root = loader.load(); 
    MainController controller = loader.getController(); 
    controller.setHostServices(getHostServices()); 
    primaryStage.setScene(new Scene(root)); 
    primaryStage.show(); 

} 

ve:

public class DialogController { 

    @FXML 
    private Hyperlink hyperlink ; 

    private HostServices hostServices ; 

    public HostServices getHostServices() { 
     return hostServices ; 
    } 

    public void setHostServices(HostServices hostServices) { 
     this.hostServices = hostServices ; 
    } 

    @FXML 
    private void openURL() { 
     hostServices.openDocument(hyperlink.getText()); 
    } 
} 

Çözüm 2:

public class MainController { private HostServices hostServices ; public HostServices getHostServices() { return hostServices ; } public void setHostServices(HostServices hostServices) { this.hostServices = hostServices ; } @FXML private void showDialog() { FXMLLoader loader = new FXMLLoader(getClass().getResource("dialog.fxml")); Parent dialogRoot = loader.load(); DialogController dialogController = loader.getController(); dialogController.setHostServices(hostServices); Stage dialog = new Stage(); dialog.setScene(new Scene(dialogRoot)); dialog.show(); } } 

ve tabii DialogController ait

benziyor
Kullanım Ama temelde böyle bir şey yapsın ana servise basmak için bir kontrolör fabrikası denetleyicilere

Bu, daha temiz bir sürümdür.Şimdi

public class HostServicesControllerFactory implements Callback<Class<?>,Object> { 

    private final HostServices hostServices ; 

    public HostServicesControllerFactory(HostServices hostServices) { 
     this.hostServices = hostServices ; 
    } 

    @Override 
    public Object call(Class<?> type) { 
     try { 
      for (Constructor<?> c : type.getConstructors()) { 
       if (c.getParameterCount() == 1 && c.getParameterTypes()[0] == HostServices.class) { 
        return c.newInstance(hostServices) ; 
       } 
      } 
      return type.newInstance(); 
     } catch (Exception e) { 
      throw new RuntimeException(e); 
     } 
    } 
} 

: Yerine denetleyicileri alma ve bunları başlatmak için bir yöntem çağırma uygun bir yapıcı varsa, sen bir controllerFactory postayla oluşturulmasını yapılandırıp kontrolörün kurucusuna bir HostServices nesne geçirerek denetleyicileri oluşturmak Eğer FXML yüklediğinizde kontrolör fabrika kullanın:

public void start(Stage primaryStage) throws Exception { 
    FXMLLoader loader = new FXMLLoader(getClass().getResource("main.fxml")); 
    loader.setControllerFactory(new HostServicesControllerFactory(getHostServices())); 
    Parent root = loader.load(); 
    primaryStage.setScene(new Scene(root)); 
    primaryStage.show(); 
} 

ve yapıcı parametre olarak HostServices almaya Denetleyicilerinizi tanımlayın:

public class MainController { 

    private final HostServices hostServices ; 

    public MainController(HostServices hostServices) { 
     this.hostServices = hostServices ; 
    } 

    @FXML 
    private void showDialog() { 
     FXMLLoader loader = new FXMLLoader(getClass().getResource("dialog.fxml")); 
     loader.setControllerFactory(new HostServicesControllerFactory(hostServices)); 
     Parent dialogRoot = loader.load(); 
     Stage dialog = new Stage(); 
     dialog.setScene(new Scene(dialogRoot)); 
     dialog.show(); 
    }  
} 

ve tabii

public class DialogController { 

    @FXML 
    private Hyperlink hyperlink ; 

    private final HostServices hostServices ; 

    public DialogController(HostServices hostServices) { 
     this.hostServices = hostServices ; 
    } 

    @FXML 
    private void openURL() { 
     hostServices.openDocument(hyperlink.getText()); 
    } 
} 

Çözüm 3:Bu sefil çirkin bir çözümdür ve bunu şiddetle kullanmamanızı öneririz. Ben sadece onu eklemek istedim başka birine saldırmaksızın ifade edebileceğini ifade etmek istedim. Ana bilgisayar hizmetlerini statik bir alanda depolayın.

public class MainApp extends Application { 

    private static HostServices hostServices ; 

    public static HostServices getHostServices() { 
     return hostServices ; 
    } 

    public void start(Stage primaryStage) throws Exception { 

     hostServices = getHostServices(); 

     Parent root = FXMLLoader.load(getClass().getResource("main.fxml")); 
     primaryStage.setScene(new Scene(root)); 
     primaryStage.show(); 
    } 
} 

Sonra sadece

MainApp.getHostServices().showDocument(hyperlink.getText()); 

her yerde gerekiyor. Buradaki sorunlardan biri, ana bilgisayar hizmetlerine erişmesi gereken tüm denetleyiciler için uygulama türünüze bağımlılık getirmenizdir.


Çözüm 4 a tek HostServicesProvider tanımlayın. Bu çözüm 3'ten daha iyidir, ama yine de iyi bir çözüm imo değildir.

public enum HostServicesProvider { 

    INSTANCE ; 

    private HostServices hostServices ; 
    public void init(HostServices hostServices) { 
     if (this.hostServices != null) { 
      throw new IllegalStateException("Host services already initialized"); 
     } 
     this.hostServices = hostServices ; 
    } 
    public HostServices getHostServices() { 
     if (hostServices == null) { 
      throw new IllegalStateException("Host services not initialized"); 
     } 
     return hostServices ; 
    } 
} 

Şimdi sadece 5 bir bağımlılık enjeksiyon çerçeve kullanın

public void start(Stage primaryStage) throws Exception { 
    HostServicesProvider.INSTANCE.init(getHostServices()); 
    // just load and show main app... 
} 

ve

public class DialogController { 

    @FXML 
    private Hyperlink hyperlink ; 

    @FXML 
    private void openURL() { 
     HostServicesProvider.INSTANCE.getHostServices().showDocument(hyperlink.getText()); 
    } 
} 

Çözüm gerekir. Bu muhtemelen geçerli kullanım durumunuz için geçerli değildir, ancak bu (nispeten basit) çerçevelerin ne kadar güçlü olabileceği konusunda size bir fikir verebilir. Eğer afterburner.fx kullanıyorsanız

Örneğin, sadece uygulama start() veya init() yöntemde

Injector.setModelOrService(HostServices.class, getHostServices()); 

yapmak gerekir, ve Bahar kullanarak sonra

public class DialogPresenter { 

    @Inject 
    private HostServices hostServices ; 

    @FXML 
    private Hyperlink hyperlink ; 

    @FXML 
    private void showURL() { 
     hostServices.showDocument(hyperlink.getText()); 
    } 
} 

bir örnek here olduğunu.

+0

çirkin statik çözüm işe yaramaz ... getStage() olarak adlandırılan benim kontrolörü sınıfında bir yöntemi var getStaticHostServices. Kullanım durumumda en az çaba gerektiren çözümdür. –

+0

@WolfgangFahl Evet, muhtemelen. Yine de neden kullanmaya karşı şiddetle tavsiye ettiğim bir şeyi bile denediğinizden emin değilsiniz. –

+0

Hayır endişe Şimdi bir arabirim kullanıyorum herkese açık arabirim Bağlayıcı { public void browse (String url); Uygulamayı gizleyen } - statik malzeme bu şekilde gerekli değildir –

1

bir başka yolu (denenmemiş) java.awt.Desktop

deneyin kullanmak olacaktır. Tam bir JRE ile çalışıyorsanız, bu muhtemelen bir sorun değildir, ancak bir JRE (Java SE 9 & Jigsaw) ile çalışmak istiyorsanız veya uygulamanızı mobil cihazda çalıştırmak istiyorsanız bir sorun olabilir (javafxports).

Gelecekte support Desktop in JavaFX için açık bir sorun var.

3

Uygulamanızın içindeki bir düğmeyi tıklattığınızda bir url açmak istiyorsanız ve bir fxml denetleyici dosyası kullanıyorsanız, aşağıdakileri yapabilirsiniz ...HostServices nesne ve bu şekilde sizin sahneye eklemek için, Ana Uygulama Başlatma dosyasında İlk

stage.getProperties().put("hostServices", this.getHostServices()); 

Sonra fxml denetleyici dosyasında hostServices sahne nesneden nesne olsun ... bir işaretçi almak ve sonra showDocument() yöntemini yürütün.

HostServices hostServices = (HostServices)this.getStage().getProperties().get("hostServices"); 
hostServices.showDocument("http://stackoverflow.com/"); 

Ben daha farklı mesela getHostServices isim yoksa

/** 
* @return the stage from my mainAnchor1 node. 
*/ 
public Stage getStage() { 
    if(this.stage==null) 
     this.stage = (Stage) this.mainAnchor1.getScene().getWindow(); 
    return stage; 
} 
+0

mainAnchor1 nedir? – simpleuser

İlgili konular