2

Disclaimer: I am very new to Java, but I've been building .NET applications for 13 years.

I'm trying to build this Java application that does some basic calculations for tutoring. It's honestly not that big of a program, but I can't even get it to the Hello, World! state! I have a requirement that's making it difficult:

GUI should be built using javax.swing components jButton, jLabel, jTextField, jTextArea, jFrame, and jPanel.

So, I downloaded NetBeans 7.3 and created a JavaFX in Swing application. The default code obviously works but it uses Button instead of JButton:

private void createScene() {
    Button btn = new Button();
    btn.setText("Say 'Hello World'");
    btn.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent event) {
            System.out.println("Hello World!");
        }
    });
    StackPane root = new StackPane();
    root.getChildren().add(btn);
    fxContainer.setScene(new Scene(root));
}

so I when I change it to use a JButton I have to also change the type the root is built from. While banging my head against the wall I found an example here (not directly related) that used the JRootPane and I thought that might work in place of the StackPane. So I refactored the code like this:

private void createScene() {
    JButton btn = new JButton();
    btn.setText("Say 'Hello World'");
    JRootPane root = new JRootPane();
    root.getContentPane().add(btn);
    fxContainer.setScene(new Scene(root));
}

and that code is fine except for fxContainer.setScene(new Scene(root)); because root isn't a Parent.

FYI, the application class implements JApplet and has a main and init that looks like this:

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            try {
                UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
            } catch (Exception e) {
            }
            
            JFrame frame = new JFrame("Tutoring Calculator");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            
            JApplet applet = new TutoringCalculator();
            applet.init();
            
            frame.setContentPane(applet.getContentPane());
            
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
            
            applet.start();
        }
    });
}

@Override
public void init() {
    fxContainer = new JFXPanel();
    fxContainer.setPreferredSize(new Dimension(JFXPANEL_WIDTH_INT, JFXPANEL_HEIGHT_INT));
    add(fxContainer, BorderLayout.CENTER);
    // create JavaFX scene
    Platform.runLater(new Runnable() {
        @Override
        public void run() {
            createScene();
        }
    });
}

How can I fulfill the requirement stated above? Am I really going about this whole thing the wrong way?

SSCCE

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package tutoringcalculator;

import java.awt.BorderLayout;
import java.awt.Dimension;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JRootPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

/**
 *
 * @author Owner
 */
public class TutoringCalculator extends JApplet {
    
    private static final int JFXPANEL_WIDTH_INT = 300;
    private static final int JFXPANEL_HEIGHT_INT = 250;
    private static JFXPanel fxContainer;

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
                } catch (Exception e) {
                }
                
                JFrame frame = new JFrame("Tutoring Calculator");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                
                JApplet applet = new TutoringCalculator();
                applet.init();
                
                frame.setContentPane(applet.getContentPane());
                
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
                
                applet.start();
            }
        });
    }
    
    @Override
    public void init() {
        fxContainer = new JFXPanel();
        fxContainer.setPreferredSize(new Dimension(JFXPANEL_WIDTH_INT, JFXPANEL_HEIGHT_INT));
        add(fxContainer, BorderLayout.CENTER);
        // create JavaFX scene
        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                createScene();
            }
        });
    }
    
    private void createScene() {
        JButton btn = new JButton();
        btn.setText("Say 'Hello World'");
        JRootPane root = new JRootPane();
        root.getContentPane().add(btn);
        fxContainer.setScene(new Scene(root));
    }
}
Community
  • 1
  • 1
Mike Perrenoud
  • 66,820
  • 29
  • 157
  • 232
  • 2
    1) For better help sooner, post an [SSCCE](http://sscce.org/). 2) At this stage, stick with pure Swing & don't mix it with Java-FX controls. The two are separate component toolkits! – Andrew Thompson May 15 '13 at 04:05
  • Did you understand the comment about not mixing Swing & Java FX components? The SSCCE still does that. – Andrew Thompson May 15 '13 at 04:18
  • @AndrewThompson, so how would I fulfill the requirement `GUI should be built using javax.swing components...` if I don't use JavaFX? Is `javafx.swing` not the same as JavaFX? – Mike Perrenoud May 15 '13 at 04:19
  • `"so how would I fulfill the requirement GUI should be built using javax.swing components... if I don't use JavaFX? Is javafx.swing not the same as JavaFX?"` -- Don't use javafx.swing components, simple as that. – Hovercraft Full Of Eels May 15 '13 at 04:29
  • 1
    They are two completely separate frameworks (even though it may allow components from one in the other) – Craig May 15 '13 at 04:30
  • @Michael, just for note : swing and javafx-1.3, javafx-2.0+ are different frameworks. Javafx-1.3 is a script language for gui and not supported by oracle any more. JavaFX-2 and swing have some degree of interaction : components of one of them can be used inside the other framework application. But in common case they are just different, like winForms and WPF. – Alexander Kirov May 15 '13 at 09:42
  • @AlexanderKirov, that makes a lot of sense. They built in that Windows Forms container for WPF, but generally speaking, you wouldn't want to do that. So if I just stuck with swing then (e.g. `JFrame`, `JButton`, `JTextField`, etc.) I would be better off right? – Mike Perrenoud May 15 '13 at 12:02

1 Answers1

5

This code works either as an applet or desktop app. here:

import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.*;

// <applet code=TutoringCalculator width=400 height=400></applet>
public class TutoringCalculator extends JApplet {

    // The size of an applet is set by the HTML!
    //private static final int JFXPANEL_WIDTH_INT = 300;
    //private static final int JFXPANEL_HEIGHT_INT = 250;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame("Tutoring Calculator");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                JApplet applet = new TutoringCalculator();
                applet.init();

                frame.setContentPane(applet.getContentPane());

                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

                applet.start();
            }
        });
    }

    private JPanel swingContainer;

    @Override
    public void init() {
        swingContainer = new JPanel(new BorderLayout());
        add(swingContainer, BorderLayout.CENTER);
        createScene();
    }

    private void createScene() {
        JButton btn = new JButton();
        btn.setText("Say 'Hello World'");
        JRootPane root = new JRootPane();
        root.getContentPane().add(btn);
        swingContainer.add(root);
    }
}

I could not be bothered figuring why you are using a RootPane so I left that as is.

Further tips

  • The spec. mentions JFrame but not JApplet. Since applets are significantly harder to develop, debug and deploy, I suggest you focus entirely on getting it working in a frame.
  • For frame positioning, you cannot go by setLocationByPlatform(true). See this answer for demo.
Community
  • 1
  • 1
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • `Since applets are significantly harder to develop...`, with that in mind, can I simply base my application against a `JFrame` instead? – Mike Perrenoud May 15 '13 at 12:01
  • This is working well, thanks a lot! One question, how do I set the size of the window? I've tried setting it on the `root`, `swingContainer`, `applet`, and `frame`. – Mike Perrenoud May 16 '13 at 08:01
  • *"One question,"* On SO it is 'one answer per question'. It is not a 'one stop fix my code shop'. So if you have another question, *start another question* on a new thread. – Andrew Thompson May 16 '13 at 08:15