I have a question.
How does one initialize the JavaFX toolkit with the method I found in an earlier StackOverflow Question? The topic can be found here: JavaFX 2.1: Toolkit not initialized
I am trying to use a solution similar to this solution from that thread:
Problem: Non-trivial Swing GUI application needs to run JavaFX components. Application's startup process initializes the GUI after starting up a dependent service layer.
Solutions
Subclass JavaFX Application class and run it in a separate thread e.g.:*
public class JavaFXInitializer extends Application {
#Override
public void start(Stage stage) throws Exception {
// JavaFX should be initialized
someGlobalVar.setInitialized(true);
}
}
The only problem I have is: What do I do with
someGlobalVar.setInitialized(true); ?
I don't know what to fill in there, and some tips would be appreciated :)
I am writing this answer for the comment you have done about how to support (.mp3,.wav,.flac,.ogg) etc in java.For .mp3 you can use JLayer http://www.javazoom.net/projects.html search on web for examples.
About (.mp3,.wav.flac,.ogg) and some more you can use JavaZoom BasicPlayer which uses some external libraries to support them you can download the zip folder here(download without installer and you open the zip folder).
Then go on the folder lib and copy all the .jars except kj_dsp which can be used for visual representation on audio data and contains also a class about fast fourier transform(FFT).Also change MP3_SPI1.9.3 with MP3SPI1.9.4
Then add these .jars into your project libraries and just use:
BasicPlayer player = new BasicPlayer();
The whole thing uses Service Provider Interface (SPI) mechanism.
It runs on a separate thread so you don't have to worry.It works really well but the project is a little bit old.It's a good start!About docs check the website.
import com.sun.javafx.application.PlatformImpl;
public class JavaFXInitializer
{
public JavaFXInitializer()
{
initFx();
}
private synchronized static void initFx() {
PlatformImpl.startup(() -> {
});
}
}
Related
Yesterday I uploaded some project to my github It compilled fine, Today I'm trying to clone it from other computer, I followoed this guide, but when I'm trying to run the code I'm getting:
Error: Could not find or load main class gui.MainScreen
Caused by: java.lang.ClassNotFoundException: gui.MainScreen
I tried to do like this post, but I didn't understand his answer, can someone please post clearer answer? Screenshots will help a lot.
Code roughly as follows:
package gui;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainScreen extends JFrame
{
public MainScreen() throws IOException
{
....
this.pack();
this.setVisible(true);
}
}
public static void main(String[] args)
{
//avoid blocking the main thread
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
try {
new MainScreen();
} catch (IOException e) {
e.printStackTrace();
};
}
});
}
}
You need to have the main class in a separate file. From your screenshot, it looks like you have the main class within the MainScreen class. You can name the file that has the main class anything you want (don't name it main though, just to avoid confusion).
If your main class is indeed in a separate file, set the main class after cloning your project in eclipse. Check this link How to set the main class in Eclipse. I am not sure that information is present in the github project that you cloned. Go to Run Configurations and setup the fully qualified main class name and as the link says, you can also search the whole project, which will give you the main class. Set that and then run the project. Hopefully, that will work.
I do not know if this answer will be beneficial to you or not but the same issue happened with me. To fix this what I did was just deleted the project from workspace and again imported it back from the git folder and everything started working fine.
My suggestion for those who encounter this problem, is to create a new draft project in Eclipse, see that it's running well, and then compare it to the
project > preference > java build path
that there is there (by edit you can see the settings of the working project vs the not working).
You can use screenshots to be sure.
When we are cloning a project it makes sense that some setting of the project are not fit to our local Eclipse setting, so we need to handle that.
I have downloaded and installed the processing IDE from their official website, then I followed the instructions on how to import the libraries into eclipse. I have core.jar, gluegen-rt.jar and jogl-all.jar added to path. I have the code below which I'm trying to run but when I go to the run menu there is no run options whatsoever. I only see 'run configurations'. Is there anything I'm missing?
package week2;
import processing.core.*;
public class ProcessingTest extends PApplet{
private String URL = "https://c2.staticflickr.com/6/5254/5428199232_c3678ed2ac.jpg";
private PImage backgroundImg;
public void setup()
{
size(800, 800);
backgroundImg = loadImage(URL, "jpg");
backgroundImg.resize(800, 800);
background(backgroundImg);
}
public void draw()
{
}
//public static void main(String args[]){
// PApplet.main(new String[]{"--present", "week2.ProcessingTest"});
//}
}
As of Processing 3, PApplet no longer extends Applet (more info here). In other words, you can't run sketches as an applet anymore.
You'll have to put your main method back in and run it as an application instead.
If you really want to run as an applet, you'll have to create your own class that extends Applet or JApplet, and then add the Processing component to that. That can be pretty convoluted, plus applets are pretty much dead now anyway, so you're probably much better of deploying as an application- or even better, as JavaScript using Processing.js.
As a side note, you shouldn't have to rely on eclipse automatically detecting the run configuration. You should be able to go into the run configurations and create one yourself. That won't work for this specific case, but it's not a bad idea to get more comfortable with the "behind the scenes" stuff so cases like this are less confusing.
The gradle build of Gluon plugin (in Netbeans 8.0.2) for porting JavaFX to Android creates the following directory structures:
Source Packages [Java]
Android/Java Packages
Desktop/Java Packages
Ios/Java Packages
Each of these directories contain java packages inside them. Generally Gluon build would create the "main" class for us in one java package inside "Source Packages" directory [the name Packages with "Source Packages" might be misleading since it is not a Java package, its just a file system directory]. This main class extends Javafx Application class and thus is the entry point into our application.
The Android API is accessible only in Android/Java Packages directory for any java package created inside it. Say, the android.Vibrator class is only referr-able here.
The problem is, we cannot refer to a class created inside any Java package inside Android/Java directory to any java package created inside Source Packages [Java] directory!! If this is the case then how would we take the application forward from the start() method of javafx.Application into say android.Vibrator.
The gluon project structure has a snapshot at: How to reference android.jar in Gluon Project
As you know, JavaFXPorts project allows deploying JavaFX apps in Desktop, Android and iOS devices. When it's just pure JavaFX code, the project is added on the Main scope, and from there it will be visible in all those platforms.
Only in the case you need some platform specific code, you should add it on the corresponding package.
As you have mentioned, by default from the Main package you won't see the added code in a platform package, so you have to provide a way for that.
If you check the HelloPlatform sample on JavaFXPorts repository, you will find a PlatformService class to load the packages using ServiceLoader.
Another possibility is using Class.forName() to load dynamically the classes at runtime, once we know the platform where the app is running.
I suggest you have a look at the Gluon Down project, that manages for you several platform specific services, and provides you with uniform, platform-independent API.
For those services not available yet in Down (feel free to contribute), you can implement them like in this simple app created using Gluon Plugin.
Source Packages [Java]
First, create a getPlatform() method, and add the referred classes to each specific platform. For instance, add org.gluonoss.vibrator.GluonAndroidPlatform.java on Android package.
public class GluonPlatformFactory {
public static GluonPlatform getPlatform() {
try {
String platform = System.getProperty("javafx.platform", "desktop");
String path = "org.gluonoss.vibrator.GluonDesktopPlatform";
if(platform.equals("android")) {
path = "org.gluonoss.vibrator.GluonAndroidPlatform";
} else if(platform.equals("ios")) {
path = "org.gluonoss.vibrator.GluonIosPlatform";
}
return (GluonPlatform) Class.forName(path).newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
System.out.println("Platform Error "+e.getMessage());
}
return null;
}
}
Now, create an interface, with the method you want on all your platforms:
public interface GluonPlatform {
void vibrate();
}
Finally, on your main class retrieve the platform and call your method:
#Override
public void start(Stage stage) {
final Button button = new Button("Click me!");
button.setOnAction(e-> GluonPlatformFactory.getPlatform().vibrate());
StackPane root = new StackPane(button);
Rectangle2D visualBounds = Screen.getPrimary().getVisualBounds();
Scene scene = new Scene(root, visualBounds.getWidth(), visualBounds.getHeight());
stage.setScene(scene);
stage.show();
}
Desktop/Java Packages
Add the vibrate method. For now leave it empty, but you could add a Timeline to move the button, for instance.
public class GluonDesktopPlatform implements GluonPlatform {
#Override
public void vibrate() {
System.out.println("Vibrating!");
}
}
Android/Java Packages
Add the vibrate method. Notice that we have to use FXActivity, which is the bridge between the JavaFX thread and the Android activity.
public class GluonAndroidPlatform implements GluonPlatform {
#Override
public void vibrate() {
Vibrator v = (Vibrator) FXActivity.getInstance().getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(500);
}
}
Don't forget to add the required permission on your AndroidManifest file (you will find it under src/android/AndroidManifest.xml.
Now you can deploy the project and run it on Desktop (gradlew run) and it will work, and install it on Android (gradlew androidInstall), and it will work too.
I was working with
javax.imageio.ImageIO class
The one provided by sun doesn't provide support for reading .tif files. So if I try to read a .tif file, it just returns a null. Then I downloaded this api from oracle's website and included it in the classpath. This api uses jni as was evident from a .so file in that folder. After that I didn't have to change anything in my code and it worked. How could this happen? Wouldn't the class names have clashed?
There were 3 things in the api that i had downloaded:
clibwrapper_jiio.jar
jai_imageio.jar
libclib_jiio.so
I didn't have to do any additional import. In fact, the functionality provided by the ImageIO class was enchanced
I am really curious about how this works.
Here is the class in javax.imageio package. The class has been declared as final. And it does some weird complex stuff that I can't understand. Could someone explain how to achieve this effect with a simpler example.
http://docs.oracle.com/javase/7/docs/api/javax/imageio/ImageIO.html
ImageIO has a scanForPlugins(...) method. I'd imagine that on class load time it takes a peek around the CLASSPATH and looks for anything that could extend its functionality.
The javadoc which hints to this is here.
You could do something similar by putting a static block in one of your classes
public class MyClass {
public static scanForExtensions() {
... code looking for extensions goes here ...
... for each found extension, register them in the "ExtensionRegistry"
ExtensionRegistry.register(extension);
}
static {
scanForExtensions();
}
public void doSomething(String input) {
for (Extension extension : ExtensionRegistry.getExtensions()) {
if (extension.canHandle(input)) {
extension.handle(input);
return;
}
}
throw UnhandledInputException("No extension to handle " + input);
}
}
Java's Image IO works using the Service Provider Interface (see links below for more details).
JavaSound works the same way. To add support for (e.g.) MP3 to JavaSound, it is only necessary to add the mp3plugin.jar of the JMF to the run-time class-path, then JavaSound can decode MP3 files as easily as it can a WAV (using the exact same classes - very funky).
I expect the installation of JAI did a similar thing, by adding a bunch of service providers for different image types to the lib directory of the JRE.
ImageWriterSpi
Creating Extensible Applications With the Java Platform.
I have a java project that is referenced in j2me project and in android project.
In this project i would like to use conditional compilation.
Something like...
//#if android
...
//#endif
//if j2me
...
//#endif
I have been reading about this but i did not find anything useful yet.
You could use Antenna (there is a plugin for Eclipse, and you can use it with the Ant build system).
I'm using it in my projects in a way you've described and it works perfectly :)
EDIT: here is the example related to #WhiteFang34 solution that is a way to go:
In your core project:
//base class Base.java
public abstract class Base {
public static Base getInstance()
{
//#ifdef ANDROID
return new AndroidBaseImpl();
//#elif J2ME
return new J2MEBaseImpl();
//#endif
}
public abstract void doSomething();
}
//Android specific implementation AndroidBaseImpl.java
//#ifdef ANDROID
public class AndroidBaseImpl extends Base {
public void doSomething() {
//Android code
}
}
//#endif
//J2ME specific implementation J2MEBaseImpl.java
//#ifdef J2ME
public class J2MEBaseImpl extends Base {
public void doSomething() {
// J2Me code
}
}
//#endif
In your project that uses the core project:
public class App {
public void something {
// Depends on the preprocessor symbol you used to build a project
Base.getInstance().doSomething();
}
}
Than if you want to build for the Android, you just define ANDROID preprocessor symbol or J2ME if you want to do a build for a J2ME platform...
Anyway, I hope it helps :)
Perhaps you should consider creating interfaces around the logic that's specific to a profile (J2ME, Android or other in the future). Then create concrete implementations of your interface for each profile. Any common parts you could split out into an abstract base class for both implementations to extend. This way your logic for each profile is nicely separated for different concerns. For each profile just build the appropriate set of classes (you could separate them by package for example). It'll be easier to maintain, debug, test and understand in the long run.
Eclipse MTJ project provides preprocessing support as documented . This support was mainly targeted for tackling fragmentation problems on JavaME. I have not tested the preprocessing support together with the Android tooling but it may just work.