Embed PApplet intp JApplet - java

How can I embed a PApplet into a JApplet ?
I wanted to add it to a JPanel inside the applet, but I couldn't.
If any of you know how I can do this. ??

As of Processing 3, you can no longer do this. PApplet no longer extends Applet, so it can't be treated as a component.
For 95% of users, this is okay. Applets are dead anyway, so you really shouldn't be using them. If at all possible, you should try deploying with Processing.js.
If you need to execute a Processing sketch from Java code, then you should use the PApplet.main("YourSketchNameHere"); function to launch it. Processing will take care of the window for you.
If you really need to treat a PApplet as a component, then you're going to have to go through its PSurface. The PSurface class contains a getNative() function that returns an object that can be treated as a component. But that's overkill for most Processing users.

Prior to Processing 3, this code should have worked for you as #Kevin has explained. So, if your question is directed towards understanding a legacy code here is what you will need to know:
import javax.swing.JFrame;
import javax.swing.JPanel;
class MyPApplet extends PApplet implements ActionListener{
#Override
public void setup() {
super.setup();
// setup
}
#Override
public void draw() {
// my draw code
}
}
public class PAppletDemo {
public static void main(String[] args) {
final JFrame frame = new JFrame("PApplet in Java Application");
JPanel panel = new JPanel();
//create an instance of your processing applet
final MyPApplet applet = new MyPApplet();
applet.init();
panel.add(applet); // From processing 3, this will give you error that applet is not a Component
frame.add(panel);
frame.setSize(applet.getSize().width, applet.getSize().height +200);
frame.setVisible(true);
}
}
To circumvent this, you will need to use PSurface getNative() function. Please refer to the example and discussion given on this link.

Related

Methods from external class accessible but GUI Components not

I have a weird Problem with my Java GUI.
I can access the Methods in the Main Class from another Class but i cannot access the Swing Components.
Let me show you how i built the whole thing
Main Class:
public class GUI extends JFrame {
static Code c = new Code();
static Draw panel = new Draw();
JTextArea codelog;
JLabel lblFile;
...
...
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
GUI frame = new GUI();
frame.create();
}
});
}
public void create() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(1280,720);
...
...
contentPane = new JPanel();
setContentPane(contentPane);
contentPane.setBackground(Color.DARK_GRAY);
GridBagLayout gbl_contentPane = new GridBagLayout();
setResizable(false);
...
...
panel.setBackground(Color.BLACK);
gbc_panel.fill = GridBagConstraints.BOTH;
gbc_panel.gridx = 1;
gbc_panel.gridy = 1;
contentPane.add(panel, gbc_panel);
codelog = new JTextArea();
codelog.setEditable(true);
JScrollPane scrollPane_1 = new JScrollPane(codelog);
codelog.setLineWrap(true);
scrollPane_1.setVerticalScrollBarPolicy(
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
codelog.setVisible(true);
scrollPane_1.setVisible(true);
GridBagConstraints gbc_scrollPane_1 = new GridBagConstraints();
gbc_scrollPane_1.gridheight = 2;
gbc_scrollPane_1.gridwidth = 4;
gbc_scrollPane_1.fill = GridBagConstraints.BOTH;
gbc_scrollPane_1.gridx = 8;
gbc_scrollPane_1.gridy = 1;
contentPane.add(scrollPane_1, gbc_scrollPane_1);
...
...
}
public void refresh(){
panel.repaint();
}
}
I am using static Code c and static Draw panel to avoid multiple instances as i also have to create Objects of the Main class in other classes.
The other Class named Code
public class Code {
...
...
static GUI g = new GUI();
String test;
...
...
public void hpgl(){
g.codelog.append(test); // gives me nullPointerException !!
g.refresh // works
...
...
}
}
The Problem is that i can access the Methods of the Main Class (GUI) from other classes (such as Code) but i cannot access the Components (such as JTextArea).
The refresh() Method in the Main Class proves it. I can access the Method and in the Main Class the repaint() works. But if i try to repaint from another class using GUI.panel.repaint() it won't work because i would in that case access the panel directly from Code Class.
The Same goes for the JTextArea. I am trying to append codelog from Code but it won't let me do it. If i create a Method in Main Class which appends the Textarea and then call the Method from Code Class it works. But using g.codelog.append(test) gives me a Java null pointer exception
So i can access the Methods but i cannot access the Swing Components.
Can you guys please help me. I don't want to have to write an extra Method in the Main Class for every single Swing Component i want to modify.
Thank You
The UI which is visible on the screen is not the same UI you have created in your Code class. If you want Code to be able to access the UI properties, you will need to pass a reference of the GUI to it.
Having said that, I would be apposed to exposing the UI components directly to any class an instead provide getters and setters (where applicable) to provide access to the information been managed. This prevents rouge classes from making changes to the UI which it should be allowed to do (like remove components)
Depending on what you are doing, an Observer Pattern might be a better choice, where by Code is notified by GUI when something it might be interested in changes. If done through the use of interfaces, this will reduce the coupling between your classes and make it more flexible
Beware static is not a mechanism for providing cross object communication and should be avoid if at all possible, especially in something as dynamic as a GUI.
I was able to solve the Problem following MadProgrammer's Suggestion.
This is what i changed.
I have 3 Classes:
Main Class
Draw
Code
Main Class
public class GUI extends JFrame {
Draw panel = new Draw(this);
Code c = new Code(this);
...
...
}
Code Class
public class Code {
private GUI g;
private Draw b;
public Code(GUI g){
this.g = g;
}
...
...
}
Draw Class
public class Draw extends JPanel{
private GUI x;
private Code c;
public Draw(GUI x){
this.x = x;
}
...
...
}
I removed all the Static declarations. It is now working. I can access the Swing Components in the Main Class now.
Is this the Professional way to do it? or is there still room for improvement. This is the first time i used the passing reference way to do it. Until now i always used static Objects.
Thank You

Best practise regarding static context

When writing a standalone java application, I see a lot of beginners code in the static context.
I used to get around this problem by creating an instance of the class in main, and working from the constructor.
I've added a few examples of a very simple standalone program, and would like to know if there are best practises for "leaving" the static context.
I would also like to know if there are things a standalone java program should be doing in the static context or specifically in the main method, what it's function is besides being the entry point of every standalone java program.
Any reading material is also welcome!
import javax.swing.JFrame;
import javax.swing.JLabel;
public class ExampleStatic
{
JLabel label;
public static void main(String[] args)
{
//Option 1 - Work from static context:
JFrame frame = new JFrame();
frame.setBounds(10,10,100,100);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel staticlabel = new JLabel("static");
frame.add(staticlabel);
frame.setVisible(true);
//Option 2 - Create instance, call initialisation function
ExampleStatic e = new ExampleStatic();
e.initialise();
//Option 3 - Create instance, handle initialisation in constructor
new ExampleStatic(true);
}
public ExampleStatic(){}
public ExampleStatic(boolean init)
{
JFrame frame = new JFrame();
frame.setBounds(10,10,100,100);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
label = new JLabel("constructor");
frame.add(label);
frame.setVisible(true);
}
public void initialise()
{
JFrame frame = new JFrame();
frame.setBounds(10,10,100,100);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
label = new JLabel("init function");
frame.add(label);
frame.setVisible(true);
}
}
Option 2 and Option 3 both are fine, as both provide the loose coupling as well if you want to use your instance somewhere else in other classes you can use it easily. But if everything you will write in Main method you are going to loose the scope and its reusability.
The JVM needs main to be static, after that you're free to do what you want. I would call a non-static "second main" that would handle initialization and then any further processing in different methods (or classes).
I would avoid putting things in the constructor, unless you really feel it's the right place for them.

What's Wrong WIth My Code involving JFrames

It's Giving me an error saying that "The method setContentPane(Container) in the type JFrame is not applicable for the arguments (GamePanel)"
Here is my Code:
package main;
import javax.swing.JFrame;
public class Game {
public static void main(String[] args){
JFrame window = new JFrame("Dragon Tales");
window.setContentPane(new GamePanel());
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setResizable(false);
}
}
I am following a tutorial exactly and his screen shows no errors at all.
Your GamePanel class does not extend any Swing GUI component such as Container or one of its children. Probably it should extend JPanel.
i.e.,
import javax.swing.JPanel;
public class GamePanel extends JPanel {
// .... etc
}
Please don't add the urgent or "help as soon as possible" bit. Yes your question is very important, but it is no more important than anyone else's.
Edit: Mad's link is worth putting in the answer: The Oracle Swing Tutorial.

combobox selection won't load/initialize class in a new window

SEE UPDATE AT THE BOTTOM!!
I've tried to figured out how to do this for a couple of days but so far I have had no luck.
Basically what I want to do is have a combobox, which when an option is selected loads an applet, and passes a value to the applet.
Here is the code for the ComboBox class, which is supposed to open the other class in a new window. The other class is the main class for an applet. They are both in the same project but in different packages. I know that there aren't any errors with the rest of the code.
//where I evaluate the selection and then open SteadyStateFusionDemo
// more selections just showing one code block
combo.addItemListener(new ItemListener(){
public void itemStateChanged(ItemEvent ie){
String str = (String)combo.getSelectedItem();
if (str.equals("NSTX")) {
machine = "A";
JFrame frame = new JFrame ("MyPanel2");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
SteadyStateFusionDemo d = new SteadyStateFusionDemo();
frame.getContentPane().add (new SteadyStateFusionDemo());
d.init();
frame.pack();
frame.setVisible (true);
And just to cover everything here is the beginning of the init() method of SteadyStateFusionDemo as well as the main method in the class. Too much code to post otherwise. There are several different privates before the init method.
//method that initializes Applet or SteadyStateFusionDemo class
public void init() {
//main method of the SteadyStateFusionDemo class
public static void main (String[] args) {
JFrame frame = new JFrame ("MyPanel");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add (new SteadyStateFusionDemo());
frame.pack();
frame.setVisible (true);
What am I doing wrong? Why doesn't my class load?
UPDATED: Changed the code so that a JFrame opens and then the JApplet loads inside. I have successfully done this in a test Java applet but for some odd reason it won't work with this Applet. I even set up the test in a similar way (The code for this is virtually the same, except with different class names, and of course a much, much shorter init() method). Can someone help me figure out why this isn't working? Also, a JFrame will open if I delete the lines referring to SteadyStateFusionDemo, but once I reference it won't work. Why does this happen?
UPDATE:
Based on your feedback, it seems you are trying to achieve the following:
Use the code of an existing Applet (found here) in a Desktop application (i.e. in a JFrame).
Converting an Applet to a Desktop application is an "undertakable" task, the complexity of which depends on how much "Applet-specific" stuff is used by the Applet. It can be as simple as creating a JFrame and adding myFrame.setContentPane(new myApplet().getContentPane()); or as complex as...hell.
This tutorial might be a good place to start.
After taking a look at the Applet at hand, it seems to be fairly easy to convert it. The only complicating factor is the use Applet's methods getCodeBase() and getImage(URL) (somewhere in the code). These two methods result in a NullPointerException if the Applet is not deployed as...an Applet.
So, what you can do is override those two methods in order to return the intended values (without the exception). The code could look like this:
/* Import the necessary Applet entry-point */
import ssfd.SteadyStateFusionDemo;
/* Subclass SSFD to override "problematic" methods */
SteadyStateFusionDemo ssfd = new SteadyStateFusionDemo() {
#Override
public URL getCodeBase() {
/* We don't care about the code-base any more */
return null;
}
#Override
public Image getImage(URL codeBase, String imgPath) {
/* Load and return the specified image */
return Toolkit.getDefaultToolkit().getImage(
this.getClass().getResource("/" + imgPath));
}
};
ssfd.init();
/* Create a JFrame and set the Applet as its ContentPane */
JFrame frame = new JFrame();
frame.setContentPane(ssfd);
/* Configure and show the JFrame */
...
The complete code for an example JFrame Class can be found here.
Of course, you need to have all Classes from the original Applet accessible to your new Class (e.g. put the original Applet in your classpath).

Different windows with the same code?

This is the "main" class (doesn't contain the main method)
import javax.swing.*;
import java.awt.*;
//import java.lang.Object;
//import java.awt.event.ActionListener;
//import java.awt.event.;
public class Program {
public JFrame frame;
public JPanel header;
public JPanel text;
public JPanel body;
public JTextField input;
public JButton agregar;
public List listA;
public List listB;
public Program(String title) {
frame = new JFrame(title);
frame.setSize(500,600);
frame.setResizable(false);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
header = new JPanel();
header.setBackground(new Color(255,204,50));
header.setBounds(0,0,500,100);
text = new JPanel();
text.setBackground(new Color(255,204,100));
text.setBounds(0,100,500,50);
text.setLayout(null);
//Inicializando la "entrada"
input = new JTextField(20);
input.setBounds(50,13,300,25);
text.add(input);
agregar = new JButton();
agregar.setBounds(360,12,80,25);
agregar.setText("Agregar");
text.add(agregar);
//Listo
body = new JPanel();
body.setBackground(new Color(255,204,150));
body.setBounds(0,150,500,450);
//Lo que está dentro del body
listA = new List(20);
body.add(listA);
listB = new List(20);
body.add(listB);
//Listo
//Añadir todos los paneles al frame principal
frame.add(header);
frame.add(text);
frame.add(body);
}
}
And this is the MAIN class (This one contains the main method):
public class Main {
public static void main(String[] args) {
new Program("Ordenamiento Recursivo");
}
}
Each time I run the application, the UI components are presented differently, please see attached screen shot.
Well, thanks to everyone who responded the post, I finished the program and I'm very happy with the final result, here it is:
In case anyone wants to take a look at the code, here it is: Link
Problems:
You're call setVisible(true) on your JFrame before adding components and this will lead to unreliable drawing of your program's graphics and is why you are seeing different results. Don't do this, but rather call it after you've added all to the top-level Window.
As the others are saying, read up and learn to use the layout managers.
Different windows with the same code?
I think that is very simple and possible by implements CardLayout
I'd suggest don't opening a new Top-Level Container, only if is there really important reason then use JDialog or JOptionPane
Be sure to construct the GUI on the EDT. Not doing so can cause unpredictable results.
Call pack() after the components are added using layouts and then call setVisible(true).
You will need a layout manager for your form so setting the layout manager to null is not the thing to do.
Work in progress here ... https://gist.github.com/2510570
Couple of changes. Not quite finished yet, but check out the following
Have Program extend a JFrame.
Have set a layout manager.
Update
Finally I knocked this up in IntelliJ's form designer.
https://gist.github.com/2512197
Where you want to attach behaviour to the buttons search through the code for the comments that ask you to add code. Although I did this in the InteliJ Ultimate (this one that costs money) I think that no-cost free to download Community Edition UI designer also paints Swings GUIs. Very quick and easy. Netbeans also has a good GUI painter.
The Swing Tutorial on oracle.com is worth reviewing also.

Categories