AWT Components in Default Processing Window

With a little help from a StackOverflow thread we are able to get the frame for Processing’s default window (https://stackoverflow.com/questions/39107750/java-and-processing-3-0-frame-class-deprecated-is-there-an-alternative). When asked to println(frame) it’s reported to be a javax.swing.JFrame, but apparently it’s really a java.awt.Frame. Therefore we can add awt components to the window as shown below. I was expecting the menubar to show up on the window but it appeared on my Mac’s main menubar. The push button and text field work as expected as long as you use an ActionListener for event handling.

/*
  Demonstrates menuBar, button, and text field components in default Processing window.
*/
import java.awt.*;
import java.awt.event.*;

java.awt.Frame frame;
java.awt.Canvas canvas;

void buildMenu() {
  // Added to Mac's main menubar not to app's window
  MenuBar  menubar = new MenuBar();
  Menu     menu = new Menu("menu");
  MenuItem item = new MenuItem("item");
  menu.add(item);
  menubar.add(menu);
  frame.setMenuBar(menubar);
  item.addActionListener(new ActionListener() {
    void actionPerformed(ActionEvent actionEvent) {
      println("menu item selected");
    }
  });
}

void buildWnd() {  
  // **** Text field **** //
  TextField ef = new TextField("Enter text:");
  ef.setBounds(50, 30, 280, 30);
  frame.add(ef);
  
  // **** Push button **** //
  Button btn = new Button("Press me.");
  btn.setBounds(100, 90, 100, 30);
  frame.add(btn);
  btn.addActionListener(new ActionListener() {
    void actionPerformed(ActionEvent actionEvent) {
      println("btn hit.");
      ef.setText("Don't forget to check out the menubar.");
    }
  });
}

void setup() {
  frame = ( (processing.awt.PSurfaceAWT.SmoothCanvas) ((processing.awt.PSurfaceAWT)surface).getNative()).getFrame();
  println("frame = " + frame);  // says it's a javax.swing.JFrame but apparently not true!
  canvas = (processing.awt.PSurfaceAWT.SmoothCanvas) ((processing.awt.PSurfaceAWT)surface).getNative();
  println("canvas = " + canvas);
  frame.setBounds(500, 300, 400, 200);
  // To avoid seeing canvas square set it to same size as frame
  canvas.setBounds(500, 300, 400, 200);
  buildMenu();
  buildWnd();
}

void draw() {
}

frame is a Java Swing JFrame

Add this import
import javax.swing.*;

and change the declaration
java.awt.Frame frame;
to
javax.swing.JFrame frame;

Then in setup() access the frame like this

frame = (javax.swing.JFrame) ((processing.awt.PSurfaceAWT.SmoothCanvas) surface.getNative()).getFrame();

Now you can add Swing as well as AWTcomponents. :grin:

I should point out that Sun is moving from Java Swing to JavaFX

1 Like

You could try adding this as first line in setup(), although possible other settings in Processing stop it working.

System.setProperty("apple.laf.useScreenMenuBar", "false");

Very helpful; thanks for looking at it. I tried changing the declaration, but didn’t get the casts made correctly, therefore made the erroneous assumption that it must not be a swing frame. I’ll try adding swing components next. I’m aware that the trend is to JavaFX, but unclear if Processing has made the switch.

Thank you for the reply. I’m aware of that line of code, but unfortunately it didn’t make a difference in this demo. I have put the menubar in a JFrame window using pure Java, so I know it works. As you point out, if we try and compete with the Processing runtime things aren’t always what they seem.

Yes, in setup() is probably too late. How about in an initializer block, outside of any method, if Processing doesn’t complain.

{
  System.setProperty("apple.laf.useScreenMenuBar", "false");
}

That is very debatable!

No change. Still doesn’t suppress it. I’m going to try JMenuBar now that I know frame is a swing frame and see if that makes a difference.

That is very debatable!

Java is not my native tongue and actually this is my second time around; first attempt was several years ago and the pundits were talking about it way back then. Apparently switch hasn’t occurred yet which is ok with me because most of the books that I have are for Swing and only one for FX.

Here’s how you get a menubar at the top of the default Processing window:

//https://www.javatpoint.com/java-jmenuitem-and-jmenu

import javax.swing.*;

javax.swing.JFrame frame;
java.awt.Canvas canvas;

void setup() {
  frame = (javax.swing.JFrame) ((processing.awt.PSurfaceAWT.SmoothCanvas) surface.getNative()).getFrame();
  frame.setBounds(500, 300, 400, 400);
  println("frame = " + frame);
  canvas = (processing.awt.PSurfaceAWT.SmoothCanvas) ((processing.awt.PSurfaceAWT)surface).getNative();
  println("canvas = " + canvas);
  canvas.setBounds(500, 300, 400, 400); // To avoid seeing default canvas square
  JMenu menu, submenu;
  JMenuItem i1, i2, i3, i4, i5;
  JMenuBar menubar = new JMenuBar();
  menu = new JMenu("Menu");
  submenu=new JMenu("Sub Menu");
  i1 = new JMenuItem("Item 1");
  i2 = new JMenuItem("Item 2");
  i3 = new JMenuItem("Item 3");
  i4 = new JMenuItem("Item 4");
  i5 = new JMenuItem("Item 5");
  menu.add(i1);
  menu.add(i2);
  menu.add(i3);
  submenu.add(i4);
  submenu.add(i5);
  menu.add(submenu);
  menubar.add(menu);
  frame.setJMenuBar(menubar);
  frame.setVisible(true);
}

void draw() {
}

Sorry, missed the obvious problem! :smile: Yes, that apple.laf.useScreenMenuBar property is specific to the Swing Apple look and feel. Glad you got it working.