JavaFX ডক্স রাষ্ট্র যে একটি WebView
প্রস্তুত যখন Worker.State.SUCCEEDED
উপনিত তবে, যদি না আপনি একটি সময় (অর্থাত অপেক্ষা করুন Animation
, Transition
, PauseTransition
, ইত্যাদি), একটি ফাঁকা পৃষ্ঠা অনুষ্ঠিত হয়।
এটি পরামর্শ দেয় যে ওয়েবভিউয়ের অভ্যন্তরে এমন একটি ইভেন্ট রয়েছে যা এটি ক্যাপচারের জন্য পড়ছে, তবে এটি কী?
আছে GitHub থেকে 7,000 ওভার কোড স্নিপেট যা ব্যবহারSwingFXUtils.fromFXImage
কিন্তু তাদের অধিকাংশই হয় সম্পর্কহীন বলে মনে WebView
, ইন্টারেক্টিভ (মানুষের মুখোশ race অবস্থা) অথবা নির্বিচারে স্থানান্তর (যে কোন জায়গায় 100 মিঃসে থেকে 2,000ms করার জন্য) ব্যবহার করুন।
আমি চেষ্টা করেছিলাম:
এর মাত্রা (উচ্চতা এবং প্রস্থের বৈশিষ্ট্যের প্রয়োগগুলি , যা এই বিষয়গুলি পর্যবেক্ষণ করতে পারে) এর
changed(...)
মধ্যে থেকে শুনছেনWebView
DoubleProperty
ObservableValue
- - টেকসই না। কখনও কখনও, মানটি রঙের রুটিন থেকে পৃথকভাবে পরিবর্তিত হয় বলে মনে হয় আংশিক সামগ্রী।
অন্ধভাবে
runLater(...)
এফএক্স অ্যাপ্লিকেশন থ্রেডে কিছু এবং সমস্ত কিছু বলছে ।- Any অনেক কৌশল এটি ব্যবহার করে তবে আমার নিজস্ব ইউনিট পরীক্ষাগুলি (পাশাপাশি অন্যান্য বিকাশকারীদের কাছ থেকে কিছু দুর্দান্ত প্রতিক্রিয়া) ব্যাখ্যা করে যে ঘটনাগুলি প্রায়শই ইতিমধ্যে সঠিক থ্রেডে থাকে এবং এই কলটি অনর্থক। আমি সবচেয়ে ভাল চিন্তা করতে পারি এটি সারিগুলির মধ্যে স্থির হওয়ার জন্য যথেষ্ট পরিমাণে যুক্ত করে যা এটি কারও পক্ষে কার্যকর।
একটি ডিওএম শ্রোতা / ট্রিগার বা জাভাস্ক্রিপ্ট শ্রোতা / ট্রিগার যুক্ত করে
WebView
- -
SUCCEEDED
ফাঁকা ক্যাপচার থাকা সত্ত্বেও ডাকা হবে তখনই উভয় জাভাস্ক্রিপ্ট এবং DOM সঠিকভাবে লোড হয়েছে বলে মনে হচ্ছে । ডোম / জাভাস্ক্রিপ্ট শ্রোতাদের সহায়তা বলে মনে হচ্ছে না।
- -
প্রধান এফএক্স থ্রেডটি অবরুদ্ধ না করে একটি
Animation
বাTransition
কার্যকরভাবে "ঘুম" ব্যবহার করা ।- Approach এই পদ্ধতির কাজ করে এবং যদি বিলম্ব যথেষ্ট দীর্ঘ হয় তবে ইউনিট পরীক্ষার 100% পর্যন্ত ফল পাওয়া যায়, তবে রূপান্তরের সময়টি ভবিষ্যতের কিছু মুহুর্ত বলে মনে হয় যে আমরা কেবল অনুমান এবং খারাপ নকশা করছি। পারফরম্যান্ট বা মিশন-সমালোচনামূলক অ্যাপ্লিকেশনগুলির জন্য, এটি প্রোগ্রামারকে গতি বা নির্ভরযোগ্যতার মধ্যে একটি ট্রেডঅফ করতে বাধ্য করে, এটি ব্যবহারকারীর পক্ষে সম্ভাব্য দু'টিই অভিজ্ঞতা।
কল করার ভাল সময় কখন WebView.snapshot(...)
?
ব্যবহার:
SnapshotRaceCondition.initialize();
BufferedImage bufferedImage = SnapshotRaceCondition.capture("<html style='background-color: red;'><h1>TEST</h1></html>");
/**
* Notes:
* - The color is to observe the otherwise non-obvious cropping that occurs
* with some techniques, such as `setPrefWidth`, `autosize`, etc.
* - Call this function in a loop and then display/write `BufferedImage` to
* to see strange behavior on subsequent calls.
* - Recommended, modify `<h1>TEST</h1` with a counter to see content from
* previous captures render much later.
*/
টুকিটাকি সংকেতলিপি:
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Worker;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.image.WritableImage;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Logger;
public class SnapshotRaceCondition extends Application {
private static final Logger log = Logger.getLogger(SnapshotRaceCondition.class.getName());
// self reference
private static SnapshotRaceCondition instance = null;
// concurrent-safe containers for flags/exceptions/image data
private static AtomicBoolean started = new AtomicBoolean(false);
private static AtomicBoolean finished = new AtomicBoolean(true);
private static AtomicReference<Throwable> thrown = new AtomicReference<>(null);
private static AtomicReference<BufferedImage> capture = new AtomicReference<>(null);
// main javafx objects
private static WebView webView = null;
private static Stage stage = null;
// frequency for checking fx is started
private static final int STARTUP_TIMEOUT= 10; // seconds
private static final int STARTUP_SLEEP_INTERVAL = 250; // millis
// frequency for checking capture has occured
private static final int CAPTURE_SLEEP_INTERVAL = 10; // millis
/** Called by JavaFX thread */
public SnapshotRaceCondition() {
instance = this;
}
/** Starts JavaFX thread if not already running */
public static synchronized void initialize() throws IOException {
if (instance == null) {
new Thread(() -> Application.launch(SnapshotRaceCondition.class)).start();
}
for(int i = 0; i < (STARTUP_TIMEOUT * 1000); i += STARTUP_SLEEP_INTERVAL) {
if (started.get()) { break; }
log.fine("Waiting for JavaFX...");
try { Thread.sleep(STARTUP_SLEEP_INTERVAL); } catch(Exception ignore) {}
}
if (!started.get()) {
throw new IOException("JavaFX did not start");
}
}
@Override
public void start(Stage primaryStage) {
started.set(true);
log.fine("Started JavaFX, creating WebView...");
stage = primaryStage;
primaryStage.setScene(new Scene(webView = new WebView()));
// Add listener for SUCCEEDED
Worker<Void> worker = webView.getEngine().getLoadWorker();
worker.stateProperty().addListener(stateListener);
// Prevents JavaFX from shutting down when hiding window, useful for calling capture(...) in succession
Platform.setImplicitExit(false);
}
/** Listens for a SUCCEEDED state to activate image capture **/
private static ChangeListener<Worker.State> stateListener = (ov, oldState, newState) -> {
if (newState == Worker.State.SUCCEEDED) {
WritableImage snapshot = webView.snapshot(new SnapshotParameters(), null);
capture.set(SwingFXUtils.fromFXImage(snapshot, null));
finished.set(true);
stage.hide();
}
};
/** Listen for failures **/
private static ChangeListener<Throwable> exceptListener = new ChangeListener<Throwable>() {
@Override
public void changed(ObservableValue<? extends Throwable> obs, Throwable oldExc, Throwable newExc) {
if (newExc != null) { thrown.set(newExc); }
}
};
/** Loads the specified HTML, triggering stateListener above **/
public static synchronized BufferedImage capture(final String html) throws Throwable {
capture.set(null);
thrown.set(null);
finished.set(false);
// run these actions on the JavaFX thread
Platform.runLater(new Thread(() -> {
try {
webView.getEngine().loadContent(html, "text/html");
stage.show(); // JDK-8087569: will not capture without showing stage
stage.toBack();
}
catch(Throwable t) {
thrown.set(t);
}
}));
// wait for capture to complete by monitoring our own finished flag
while(!finished.get() && thrown.get() == null) {
log.fine("Waiting on capture...");
try {
Thread.sleep(CAPTURE_SLEEP_INTERVAL);
}
catch(InterruptedException e) {
log.warning(e.getLocalizedMessage());
}
}
if (thrown.get() != null) {
throw thrown.get();
}
return capture.get();
}
}
সম্পর্কিত:
- পুরো ওয়েব পৃষ্ঠার স্ক্রিনশটটি কেবল দৃশ্যমান অংশ নয়, জাভাএফএক্স ওয়েবভিউ উপাদানটিতে লোড হয়েছে
- আমি কি প্রোগ্রামটিমে সিনের স্ন্যাপশট ক্যাপচার করতে পারি?
- পুরো পৃষ্ঠার স্ক্রিনশট, জাভা
- জাভাএফএক্স ২.০+ ওয়েবভিউ / ওয়েবইংগাইন কোনও ছবিতে ওয়েব পৃষ্ঠাকে রেন্ডার করে
- জাভাফেক্সে পর্যায়ের উচ্চতা এবং প্রস্থ নির্ধারণ করুন
- জাভাএফএক্স: ওয়েবভিউ ব্যবহার করার সময় কীভাবে মঞ্চটিকে পুনরায় আকার দিন
- ট্যাবেসেল এম্বেড থাকা ওয়েবভিউয়ের সঠিক আকারের আকার
- https://docs.oracle.com/javase/8/javafx/embedded-browser-tutorial/add-browser.htm#CEGDIBBI
- http://docs.oracle.com/javafx/2/swing/swing-fx-interoperability.htm#CHDIEEJE
- https://bugs.openjdk.java.net/browse/JDK-8126854
- https://bugs.openjdk.java.net/browse/JDK-8087569
Platform.runLater
পরীক্ষা করা হয়েছিল এবং এটি ঠিক করে না। আপনি যদি একমত না হন তবে নিজের জন্য এটি চেষ্টা করুন। আমি ভুল হতে পেরে খুশি হব, এটি সমস্যাটি বন্ধ করবে।
SUCCEEDED
(যার মধ্যে শ্রোতা এফএক্স থ্রেডে আগুন জ্বলন করে) সঠিক কৌশল। যদি সারিবদ্ধ ইভেন্টগুলি দেখানোর কোনও উপায় থাকে তবে আমি চেষ্টা করে খুশি হব। আমি ওরাকল ফোরামে মন্তব্যগুলির মাধ্যমে স্পার্স পরামর্শ এবং কিছু এসও প্রশ্নের সন্ধান পেয়েছি যা WebView
ডিজাইনের মাধ্যমে নিজের থ্রেডে চালানো উচিত, তাই পরীক্ষার কয়েক দিন পরে আমি সেখানে শক্তি নিবদ্ধ করছি। যদি সেই অনুমানটি ভুল হয় তবে দুর্দান্ত। আমি যেকোন যুক্তিসঙ্গত পরামর্শের জন্য উন্মুক্ত যা নির্বিচারে অপেক্ষার সময়গুলি ছাড়াই সমস্যার সমাধান করে।
loadContent
পদ্ধতি ব্যবহার করার সময় বা কোনও ফাইলের URL লোড করার সময় ঘটেছিল appears