web-dev-qa-db-ja.com

JavaFXはimageViewの画像を変更します

基本的に、データベースからimageViewに画像をロードするメソッドと、画像を変更する2番目のメソッドがあります。例外を取得せずに両方のメソッドを正常に実行していますが、changeImage()メソッドのsetImageの後に、何を更新する必要があり、どのように更新する必要がありますか(シーン、ステージ)全然可能です。 javafxのswingにrepaint()のようなメソッドがないことを知っているので、これにどのようにアプローチしますか?

public class MainMenuController implements Initializable {

    /**
     * Initializes the controller class.
     */
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // TODO
    }

    private AnchorPane stck1;

 @FXML
    private AnchorPane openSecondWindow(ActionEvent event) throws Exception {
        GUIController ctrl = new GUIController();
        Stage stage = new Stage();
       setStck1((AnchorPane) FXMLLoader.load(InteractiveFictionGame2.class.getResource("GUI.fxml")));
        ImageView img_1 = new ImageView(ctrl.loadImg().getImage());
        img_1.setPreserveRatio(true);
        img_1.setSmooth(true);
        img_1.setCache(true);
        getStck1().getChildren().add(img_1);
        Scene scene = new Scene(getStck1());
        stage.setTitle("Interactive Fiction Game");
        stage.setScene(scene);
         stage.setFullScreen(true);
       // stage.sizeToScene();
        stage.show();
       return getStck1();
    }






public class GUIController implements Initializable {

    @FXML
    private TabPane tb1;

    /**
     * Initializes the controller class.
     *
     * @param url
     */
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // TODO
    }
    @FXML
    private ImageView img_1;





 public ImageView loadImg() {

        try {

            con = DriverManager.getConnection(Host, unm, pswrd);
            stmnt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
            rs = stmnt.executeQuery(SQL);
            rs.next();
            fis = rs.getBinaryStream(4);
            imgt = javax.imageio.ImageIO.read(fis);
            Image newImg = SwingFXUtils.toFXImage(imgt, null);
            img_1 = new ImageView();
            img_1.setImage(newImg);
            rs.close();
            stmnt.close();

            con.close();
        } catch (Exception e) {
            System.out.println("Not working");
        }
        return img_1;
    }


public void changeImage() {
..
            fis = rs.getBinaryStream(1);
            imgt = javax.imageio.ImageIO.read(fis);
            Image newImg = SwingFXUtils.toFXImage(imgt, null);
            img_1.setImage(newImg);
...
 } catch (Exception e) {
            System.out.println("Not working");
        }
        return img_1;
    }
5
Kylar Stern

あなたの問題

@FXMLを使用して挿入するメンバーノードがコントローラーにある場合は、newコンストラクターを使用して新しいオブジェクトインスタンスを作成し、その新しいオブジェクトを既存の参照に割り当てないでください。代わりに、作成したFXMLでオブジェクトを使用してください。

あなたが持っている:

@FXML
private ImageView img_1;

それはいいです。次に、loadImgには、次のものがあります。

img_1 = new ImageView();
img_1.setImage(newImg);

それは悪いです。 FXMLドキュメントをロードしたときにFXMLLoaderが作成したImageViewがすでにあります。次に、FXMLローダーは、img_1アノテーションを使用したため、そのImageViewを@FXML参照に割り当てました。

修正方法

したがって、必要なのは、新しいImageViewの作成を停止し、次のように記述することだけです。

img_1.setImage(newImg);

これで完了です。

なぜ機能するのか

ImageViewのImageプロパティは、監視可能なプロパティです。 JavaFXシステムは、変更がないかImageプロパティを監視し、変更された場合は、ImageViewの画面に表示されている画像を自動的に更新します。再描画呼び出しを実行する必要はありません(どのような場合でも呼び出すような再描画ルーチンはありません)。

背景資料

JavaFXシーングラフアーキテクチャをよりよく理解したい場合は、Oracleチュートリアルをお読みください。

いくつかのヒント

  • InputStreamから直接JavaFXイメージを作成する 、このタスクにImageIOとSwingFXUtilsを使用する必要はありません。
  • Task を使用してデータベースと通信すると、アプリケーションの応答性が向上する可能性があります。
  • データベースからではなく、ファイルまたはhttp経由で画像を読み取る方がおそらく簡単です。

免責事項

ここで指摘されている問題の他に、提供していないコードに他のエラーがあり、アプリケーションを希望どおりに動作させることができない場合があります。

11
jewelsea

Java私はここで卒業します:
JavaFX用語プロジェクトでは、setOnActionイベント(ボタンをクリック)時にimageViewオブジェクトを更新する必要がありました。これにより、プログラムユーザーは一連の画像をクリックすることができました。

以下はうまくいきました:
最初にImageインスタンスとImageViewインスタンスを作成します。

Image imageObject = new Image();
ImageView imageViewObject = new ImageView();

次に、コード内でボタンイベントを実行すると、(次の)画像が次のように割り当てられて更新されます。

btn.setOnAction(e -> {
    imageIndex++;
    imageFilename = imageNamesArray.get(imageIndex);
    imageObject = new Image(imageFilename);  
    imageViewObject.setImage(imageObject);
}

注:私のプロジェクトのファイル名は、ArrayList()の文字列要素として保存されたjpgファイル(名前)です。ボタンをクリックすると、配列インデックスが次のjpgファイル名(およびパスまたはURL)にインクリメントされ、新しい画像が表示されます。したがって、前述の回答のように、ImageViewObjectを1つだけ作成しますが、毎回新しい画像を画像オブジェクト「imageObject」に再割り当てします。

1
Brian H Combes