OpenOffice crashes when i'm trying to launch an addon in linux, but it fine in windows. Addon is written in javafx. The crash happens occasionally not always and it happens only at the launch, if program loads then it works fine.
logs:
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Fatal exception: Signal 6
Stack:
/opt/openoffice4/program/libuno_sal.so.3(+0x37a9a)[0x7f3b84896a9a]
/opt/openoffice4/program/libuno_sal.so.3(+0x37bcc)[0x7f3b84896bcc]
/opt/openoffice4/program/libuno_sal.so.3(+0x37c69)[0x7f3b84896c69]
/usr/lib/libc.so.6(+0x33b20)[0x7f3b834e4b20]
/usr/lib/libc.so.6(gsignal+0x37)[0x7f3b834e4a97]
/usr/lib/libc.so.6(abort+0x16a)[0x7f3b834e5e6a]
/usr/lib/libstdc++.so.6(_ZN9__gnu_cxx27__verbose_terminate_handlerEv+0xfd)[0x7f3b83dcff5d]
/usr/lib/libstdc++.so.6(+0x5ee56)[0x7f3b83dcde56]
/usr/lib/libstdc++.so.6(+0x5de59)[0x7f3b83dcce59]
/usr/lib/libstdc++.so.6(__gxx_personality_v0+0x10a)[0x7f3b83dcd65a]
/usr/lib/libgcc_s.so.1(+0xfff3)[0x7f3b83863ff3]
/usr/lib/libgcc_s.so.1(_Unwind_Resume+0x57)[0x7f3b83864517]
/opt/openoffice4/program/libvcl.so(+0x17fffe)[0x7f3b7fb42ffe]
/opt/openoffice4/program/libuno_sal.so.3(+0x36862)[0x7f3b84895862]
/opt/openoffice4/program/libuno_sal.so.3(+0x37c4a)[0x7f3b84896c4a]
/usr/lib/libc.so.6(+0x33b20)[0x7f3b834e4b20]
/usr/lib/libc.so.6(gsignal+0x37)[0x7f3b834e4a97]
/usr/lib/libc.so.6(abort+0x16a)[0x7f3b834e5e6a]
/usr/lib/libstdc++.so.6(_ZN9__gnu_cxx27__verbose_terminate_handlerEv+0x16d)[0x7f3b83dcffcd]
/usr/lib/libstdc++.so.6(+0x5ee56)[0x7f3b83dcde56]
/usr/lib/libstdc++.so.6(+0x5eea1)[0x7f3b83dcdea1]
/usr/lib/libstdc++.so.6(+0x5f0b8)[0x7f3b83dce0b8]
/opt/openoffice4/program/soffice.bin(__gxx_personality_v0+0x28c)[0x40108c]
/opt/openoffice4/program/soffice.bin(_Znwm+0x17)[0x401137]
/opt/openoffice4/program/libvclplug_gtk.so(+0x260f5)[0x7f3b77fa40f5]
/opt/openoffice4/program/libvclplug_gtk.so(+0x2610a)[0x7f3b77fa410a]
/opt/openoffice4/program/libvclplug_gtk.so(+0x25ba9)[0x7f3b77fa3ba9]
/usr/lib/libgdk-x11-2.0.so.0(+0x58173)[0x7f3b76613173]
/usr/lib/libglib-2.0.so.0(g_main_context_check+0x181)[0x7f3b76efc671]
/usr/lib/libglib-2.0.so.0(+0x49c33)[0x7f3b76efcc33]
/usr/lib/libglib-2.0.so.0(g_main_loop_run+0xc2)[0x7f3b76efd022]
/usr/lib/libgtk-x11-2.0.so.0(gtk_main+0xb7)[0x7f3b7699f3f7]
/opt/java/jre/lib/amd64/libglass.so(Java_com_sun_glass_ui_gtk_GtkApplication__1runLoop+0x7d)[0x7f3b135c8bed]
[0x7f3b49018c39]
/opt/openoffice4/program/soffice: line 121: 18278 Aborted (core dumped) "$sd_prog/$sd_binary" "$#"
Any idea on what causes the crash?
fragment of code where GUI init happens:
public class AboutDialog {
private final static Paint DIALOG_COLOR = Color.BEIGE;
private static JFrame dialog = new JFrame();
private String windowName = "";
public AboutDialog(String windowName) {
this.windowName = windowName;
showDialog();
}
private void showDialog() {
if(OOUtil.isLinux()){
initGUI();
}else
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
initGUI();
}
});
}
public void initGUI() {
dialog.setResizable(false);
dialog.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
Image icon = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB_PRE);
dialog.setIconImage(icon);
position(dialog);
dialog.setTitle(windowName);
dialog.setResizable(false);
final JFXPanel fxPanel = new JFXPanel();
dialog.setContentPane(fxPanel);
dialog.setAlwaysOnTop(true);
Platform.runLater(new Runnable() {
#Override
public void run() {
Scene scene = new Scene(new AboutController(AboutDialog.this), 300, 250);
fxPanel.setScene(scene);
dialog.setVisible(true);
}
});
}
public JFrame getDialog() {
return dialog;
}
Related
I have a splash screen :
I need to have the animation of the progress bar (Indeterminate) but it doesn't work.
It's maybe due to because my thread is running in my initilize methode.
public class splashscreenController implements Initializable {
#Override
public void initialize(URL location, ResourceBundle resources) {
new SplashScreen().run();
}
class SplashScreen extends Task {
#Override
public Object call() {
Platform.runLater(new Runnable() {
#Override
public void run()
Parent root = null;
try {
Thread.sleep(3000);
root = FXMLLoader.load(getClass().getResource("../gui/NewUI.fxml"));
} catch (InterruptedException | IOException e) {
e.printStackTrace();
}
Stage stage = new Stage();
stage.initStyle(StageStyle.UNDECORATED);
assert root != null;
Scene scene = new Scene(root, 1280, 720);
stage.setScene(scene);
stage.show();
MainJavaFx.setPrimaryStage(stage);
((Stage) panParent.getScene().getWindow()).close();
}
});
return null;
}
}
}
There are 2 issues in your code:
new SplashScreen().run();
A Task does not provide functionality for running on a new thread. run is executed on the calling thread.
class SplashScreen extends Task {
#Override
public Object call() {
Platform.runLater(new Runnable() {
#Override
public void run() {
// placeholder for parts of your code
longRunningOperation();
guiUpdate();
}
});
return null;
}
}
Even if you execute this task on a seperate thread, the Runnable passed to Platfrom.runLater is executed on the JavaFX application thread and doing long-running operations from this runnable freezes the GUI.
Do all the long-running operations on the background thread instead and only do short updates using Platfrom.runLater.
new Thread(new SplashScreen()).start();
class SplashScreen extends Task {
#Override
public Object call() throws IOException, InterruptedException {
Thread.sleep(3000);
final Parent root = FXMLLoader.load(getClass().getResource("../gui/NewUI.fxml"));
Platform.runLater(new Runnable() {
#Override
public void run() {
Stage stage = new Stage();
stage.initStyle(StageStyle.UNDECORATED);
Scene scene = new Scene(root, 1280, 720);
stage.setScene(scene);
stage.show();
MainJavaFx.setPrimaryStage(stage);
((Stage) panParent.getScene().getWindow()).close();
}
});
return null;
}
}
Note that since you're not using the functionality provided by Task, you could simply implement Runnable with your class instead of inheriting from Task.
I'm currently trying to create a Splash Screen for my program since it takes some time to start up.
The problem is that it takes a while to create the GUI (creating dialogues, updating tables etc.). And I can't move the GUI creation to a background thread (like the "Task" class), since I'll get an "Not on FXApplication Thread" exception.
I tried using:
Platform.runLater(new Runnable() {
public void run() {
//create GUI
}
}
And the "call" method of a Task:
public class InitWorker extends Task<Void> {
private Model model;
private ViewJFX view;
public InitWorker(Model model) {
this.model = model;
}
#Override
protected Void call() throws Exception {
View view = new View();
Collection collection = new Collection();
//do stuff
}
}
When I wrote the program in Swing I could just display and update the Splash Screen on the EventDispatchThread, without any real concurreny. The code looked like this:
public void build() {
MainOld.updateProgressBar(MainOld.PROGRESSBAR_VALUE++, "Creating Menus");
menuCreator = new MenuCreatorOld (model, this);
menuCreator.createMenu();
MainOld.updateProgressBar(MainOld.PROGRESSBAR_VALUE, "Creating Toolbar");
toolBar = menuCreator.createToolBar();
createWesternPanelToolBar();
shoppingPanel = new ShoppingListOld(model, this, collectionController, shoppingController, controller);
centerTabbedPane = new JTabbedPane();
MainOld.updateProgressBar(MainOld.PROGRESSBAR_VALUE++, "Creating Collection");
collectionPanel = new CollectionOld(model, collectionController, this, controller);
MainOld.updateProgressBar(MainOld.PROGRESSBAR_VALUE++, "Creating Wish List");
wishPanel = new WishListOld(model, this, collectionController, wishController, controller);
MainOld.updateProgressBar(MainOld.PROGRESSBAR_VALUE++, "Creating Folders Table");
//and so on
}
public static void updateProgressBar(int progressValue, String text) {
System.out.println("Loading Bar Value:"+progressValue);
progressBar.setValue(progressValue);
loadingLabel.setText(text);
progressBar.setString(text);
}
Is there any way to create the GUI in the background while displaying a Splash Screen with a loading bar?
Edit:
I had a look at my code and was able to decrease the startup time by 5 seconds. Most of the dialogs pull data from the database when they are created. So I moved the creation of the dialogs into their getter methods. That resulted in an improvement of 3 seconds. But I would still like to know if there is in a way to create the GUI on a background thread.
Edit:
As suggested, I also tried using "RunLater" in a "Task".
This way I can create the GUI and display the SplashScreen, but I can't update the progress bar and progress label, since the GUI creation blocks the JavaFX application thread. The progress bar and label are only updated, after the GUI has been fully created.
Here's an example you guys can run (I removed the splash screen and only kept the progress bar and progress label):
public class InitWorker extends Task<Void> {
private static ProgressBar progressBar;
private static Label progressLabel;
private static double PROGRESS_MAX = 5;
private double loadingValue;
public InitWorker() {
loadingValue = 0;
}
#Override
protected void succeeded() {
System.out.println("Succeeded");
}
#Override
protected void failed() {
System.out.println("Failed");
}
#Override
protected Void call() throws Exception {
System.out.println("RUNNING");
Platform.runLater(new Runnable() {
public void run() {
displaySplashScreen();
for(int i=0; i<10; i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
updateProgressBar(loadingValue++, "Label "+i);
Stage stage = new Stage();
Label label = new Label("Label " + i);
VBox panel = new VBox();
panel.getChildren().add(label);
Scene scene = new Scene(panel);
stage.setScene(scene);
stage.centerOnScreen();
stage.show();
}
// updateProgressBar(1, "Initializing...");
}});
return null;
}
public void updateProgressBar(double loadingValue, String text) {
progressBar.setProgress(loadingValue / PROGRESS_MAX);
progressLabel.setText(text);
}
public static void displaySplashScreen() {
Stage progressBarStage = new Stage();
progressBar = new ProgressBar();
Scene progressBarScene = new Scene(progressBar);
progressBarStage.setScene(progressBarScene);
Stage progressLabelStage = new Stage();
progressLabel = new Label("Loading...");
progressLabel.setPadding(new Insets(5));
progressLabel.setStyle("-fx-background-color: red");
Scene progressLabelScene = new Scene(progressLabel);
progressLabelStage.setScene(progressLabelScene);
double progressBarWidth = 500;
double progressBarHeight = 75;
//muss angezeigt werden, um sie abhängig von Größe zu positionieren
progressBarStage.show();
progressLabelStage.show();
//
progressBarStage.setWidth(progressBarWidth);
progressBarStage.setHeight(progressBarHeight);
progressBarStage.centerOnScreen();
progressBarStage.centerOnScreen();
progressLabelStage.setY(progressLabelStage.getY() + 25);
}
}
See Task documentation titled "A Task Which Modifies The Scene Graph", which provides an example:
final Group group = new Group();
Task<Void> task = new Task<Void>() {
#Override protected Void call() throws Exception {
for (int i=0; i<100; i++) {
if (isCancelled()) break;
final Rectangle r = new Rectangle(10, 10);
r.setX(10 * i);
Platform.runLater(new Runnable() {
#Override public void run() {
group.getChildren().add(r);
}
});
}
return null;
}
};
The above example add the rectangles to the scene graph via a 100 runLater calls. A more efficient way to do this would be to add the rectangles to a group not attached to the active scene graph, then only add the group to the active scene graph in the runLater call. For example:
final Group groupInSceneGraph = new Group();
Task<Void> task = new Task<Void>() {
#Override protected Void call() throws Exception {
final Group localGroup = new Group();
for (int i=0; i<100; i++) {
if (isCancelled()) break;
final Rectangle r = new Rectangle(10, 10);
r.setX(10 * i);
localGroup.getChildren().add(r);
}
Platform.runLater(new Runnable() {
#Override public void run() {
groupInSceneGraph.add(localGroup);
}
});
return null;
}
};
You can create and modify most scene graph objects off of the JavaFX application thread (including loading FXML), as long as the objects aren't attached to the active scene graph. By active scene graph I mean a scene graph which is currently attached as a scene to a displayed stage. (A complicated control such as a WebView may be an exception to this rule and may require creation on the JavaFX application thread).
You must only attach the scene graph objects created off of the JavaFX application thread to the active scene graph on the JavaFX application thread (for example using Platform.runLater()). And, you must work with them on the JavaFX application thread as long they continue to be attached to the active scene graph.
I'm trying to create a Javafx application that takes screenshots from a URL. Where I'm running into issues is with threading. In my main method, I'm trying to run the two screenshots but it's getting stuck after loading the first page. I've tried to wrap the monitorPageStatus() (since it calls the actual saveToPng() function) method in a task that is submitted to the executor (code below). How can I properly submit the task to the executor so both screenshots are taken?
public class InsightScreenshot {
{
// Clever way to init JavaFX once
JFXPanel fxPanel = new JFXPanel();
}
private Browser browser;
public Stage stage;
private Timer timer = new java.util.Timer();
private ExecutorService exec = Executors.newSingleThreadExecutor(r -> {
Thread t = new Thread(r);
t.setDaemon(true); // allows app to exit if tasks are running
return t ;
});
#SuppressWarnings("restriction")
/**
*
* #param url
* #param imageName add png extension
*/
public void showWindow(String url, String imagePath) {
// JavaFX stuff needs to be done on JavaFX thread
Platform.runLater(new Runnable() {
private Stage window;
#SuppressWarnings("restriction")
#Override
public void run() {
Stage window = new Stage();
window.setTitle(url);
browser = new Browser(url);
monitorPageStatus(imagePath, window);
VBox layout = new VBox();
layout.getChildren().addAll(browser);
Scene scene = new Scene(layout);
window.setScene(scene);
//window.setOnCloseRequest(we -> System.exit(0));
window.show();
}
});
}
private void monitorPageStatus(String imageName, Stage window) {
timer.schedule(new TimerTask() {
#SuppressWarnings("restriction")
public void run() {
Platform.runLater(() -> {
if (browser.isPageLoaded()) {
System.out.println("Page now loaded, taking screenshot...");
saveAsPng(imageName);
window.close();
cancel();
} else
System.out.println("Loading page...");
});
}
}, 1000, 1000);
}
private void saveAsPng(String imageName) {
WritableImage image = browser.snapshot(new SnapshotParameters(), null);
//TODO change file path?
File file = new File(imageName);
try {
ImageIO.write(SwingFXUtils.fromFXImage(image, null), "png", file);
System.out.println("Screenshot saved as " + imageName);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
InsightScreenshot pic = new InsightScreenshot();
pic.showWindow("ttps://www.google.com", "/images/google.png");
InsightScreenshot pic2 = new InsightScreenshot();
pic2.showWindow("https://www.facebook.com", "/images/fb.png");
}
}
I have a JPanel with multiple components in it - like a few JLabels, JTextBoxes, JComboBoxes, JCheckBoxes etc.
I want to display a pop up help window if the user hovers over these components for say 3 secs.
So far I added a MouseListener to one of my Components and it does display the required pop up and help. However I can't achieve it after 3 sec delay. As soon as the user moves the mouse to through that area of the component the pop up displays. This is very annoying as the components are almost unusable. I have tried using MouseMotionListener and having the below code in mouseMoved(MouseEvent e) method. Gives the same effect.
Any suggestion on how can I achieve the mouse hover effect - to display the pop up only after 3 sec delay?
Sample Code:(Mouse Entered method)
private JTextField _textHost = new JTextField();
this._textHost().addMouseListener(this);
#Override
public void mouseEntered(MouseEvent e) {
if(e.getSource() == this._textHost())
{
int reply = JOptionPane.showConfirmDialog(this, "Do you want to see the related help document?", "Show Help?", JOptionPane.YES_NO_OPTION);
if(reply == JOptionPane.YES_OPTION)
{
//Opens a browser with appropriate link.
this.get_configPanel().get_GUIApp().openBrowser("http://google.com");
}
}
}
Use a Timer in mouseEntered(). Here's a working example:
public class Test {
private JFrame frame;
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Test test = new Test();
test.createUI();
}
});
}
private void createUI() {
frame = new JFrame();
JLabel label = new JLabel("Test");
label.addMouseListener(new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent me) {
startTimer();
}
});
frame.getContentPane().add(label);
frame.pack();
frame.setVisible(true);
}
private void startTimer() {
TimerTask task = new TimerTask() {
#Override
public void run() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JOptionPane.showMessageDialog(frame, "Test");
}
});
}
};
Timer timer = new Timer(true);
timer.schedule(task, 3000);
}
}
We have a JDialog that contains a single stage with multiple scenes. Each scene has a next button. When the user clicks "next" we call stage.setScene. This works fine on Windows and Linux, but on Mac, setScene never returns. The application hangs, and it appears to be a thread deadlock. Here is a sample app that reproduces the problem. We have also tried various java 7 builds and java8 pre-release. We think we have found a couple workarounds, but we would like to understand why this code has problems on Mac. Sample app with bug:
public class SampleFxInsideSwing
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new SampleFxInsideSwing().initFX();
}
});
}
private void initFX()
{
JDialog dialog = new JDialog();
dialog.setSize(new Dimension(500,500));
final JFXPanel stage = new JFXPanel();
dialog.add(stage);
Platform.runLater(new Runnable()
{
#Override
public void run()
{
Button nextButton = new Button("Next");
nextButton.setOnAction(new EventHandler<ActionEvent>()
{
//#Override
public void handle(ActionEvent event)
{
try
{
System.out.println("Clicked");
AnchorPane parent = FXMLLoader.load(SampleFxInsideSwing.class.getResource("SampleFxml.fxml"));
Scene secondScene = new Scene(parent);
stage.setScene(secondScene);
System.out.println("Displaying second scene!");
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
Group group = new Group();
group.getChildren().add(nextButton);
Scene scene1 = new Scene(group);
stage.setScene(scene1);
}
});
dialog.setVisible(true);
}
}