The Processing IDE (4.0b6) is an easy to use Java editor as illustrated by this demo which adds numerous Swing components to the default Processing window. The default canvas, along with pre-programmed graphics, is removed prior to adding components and event handling is performed by adding various ‘listeners’. Processing’s draw() becomes non-functional and therefore graphics is handled by painting on a JPanel. Two unexpected things happen when the sketch is exported as an application: 1.) the menu bar disappears from the sketch frame and shows up on the Mac’s main menubar 2.) some (but not all) of the components are initially invisible until they are clicked on or one of the other visible components is selected. A work around is to add xxxx.repaint(); to the functions of these components, which should prevent the problem. Overall, I found this method easier to use than more complex Java editors, albeit with some idiosyncrasies. Basically there are four steps for each component: a.) instantiate with ‘new’ b.) setBounds c.) add to frame, and then add listener for event handling as required. Repaint() may be necessary if app components aren’t initially visible. The demo exported as an app to macos-x86_64 is shown below. Not tested on M1 or other platforms.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.io.*;
javax.swing.JFrame frame;
java.awt.Canvas canvas;
int _wndW = 700;
int _wndH = 600;
int radius = 20;
Color dotColor = Color.RED;
GPanel panel;
JLabel label;
JTextArea txtArea;
void menuBar() {
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("File");
JMenuItem open = new JMenuItem("Open...");
menu.add(open);
menuBar.add(menu);
menuBar.setToolTipText("menu bar");
frame.setJMenuBar(menuBar);
// **** Action **** //
open.addActionListener( new ActionListener() {
void actionPerformed(ActionEvent event) {
if (event.getSource() == open) {
JFileChooser fileChooser = new JFileChooser();
int i = fileChooser.showOpenDialog(fileChooser);
if (i == JFileChooser.APPROVE_OPTION) {
File file = fileChooser.getSelectedFile();
String filepath = file.getPath();
try {
BufferedReader buffer = new BufferedReader(new FileReader(filepath));
String s1 = "", s2 = "";
while ((s1 = buffer.readLine())!= null) {
s2 += s1 + "\n";
}
txtArea.setText(s2);
buffer.close();
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
}
);
println("EDT menuBar = " + javax.swing.SwingUtilities.isEventDispatchThread());
}
void textField() {
JTextField txtFld = new JTextField("");
txtFld.setBounds(50, 40, 280, 30);
frame.add(txtFld);
txtFld.setToolTipText("text field");
// **** Action **** //
txtFld.addActionListener( new ActionListener() {
void actionPerformed(ActionEvent actionEvent) {
label.setText(txtFld.getText());
}
}
);
txtFld.repaint(); // To make it visible after export application.
println("EDT txtFld = " + javax.swing.SwingUtilities.isEventDispatchThread());
}
void textArea() {
txtArea = new JTextArea();
JScrollPane scrlPane = new JScrollPane(txtArea);
scrlPane.setBounds(30, 240, 380, 280);
frame.add(scrlPane);
txtArea.setEditable(true);
txtArea.setToolTipText("text area");
// txtArea.setFont(new Font("Menlo", Font.BOLD, 16));
txtArea.setLineWrap(false);
txtArea.setWrapStyleWord(true);
txtArea.repaint();
println("EDT txtArea = " + javax.swing.SwingUtilities.isEventDispatchThread());
}
void button() {
JButton btn = new JButton("Press me.");
btn.setBounds(50, 90, 100, 30);
btn.setToolTipText("button");
frame.add(btn);
// **** Action **** //
btn.addActionListener( new ActionListener() {
void actionPerformed(ActionEvent actionEvent) {
label.setText("Don't forget to check out the menubar.");
}
}
);
btn.repaint();
println("EDT btn = " + javax.swing.SwingUtilities.isEventDispatchThread());
}
void sliderWithTicks() {
JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 100, 25);
slider.setBounds(30, 130, 250, 50);
frame.add(slider);
slider.setMinorTickSpacing(5);
slider.setMajorTickSpacing(10);
slider.setPaintTicks(true);
slider.setPaintLabels(true);
slider.setToolTipText("slider with ticks");
println("EDT sliderWithTicks = " + javax.swing.SwingUtilities.isEventDispatchThread());
}
void slider_plain() {
JSlider slider = new JSlider(JSlider.HORIZONTAL, 5, 70, 20);
slider.setBounds(360, 10, 120, 30);
slider.setToolTipText("slider no ticks");
frame.add(slider);
// **** Action **** //
slider.addChangeListener(new ChangeListener() {
void stateChanged(ChangeEvent changeEvent) {
radius = slider.getValue();
panel.repaint();
}
}
);
println("EDT slider = " + javax.swing.SwingUtilities.isEventDispatchThread());
}
void colorBtn() {
JButton colorBtn = new JButton("Color");
colorBtn.setBounds(480, 10, 80, 30);
colorBtn.setToolTipText("button");
frame.add(colorBtn);
// **** Action **** //
colorBtn.addActionListener( new ActionListener() {
void actionPerformed(ActionEvent actionEvent) {
dotColor = JColorChooser.showDialog(null, "Choose color", Color.RED);
panel.repaint();
}
}
);
colorBtn.repaint();
println("EDT colorBtn = " + javax.swing.SwingUtilities.isEventDispatchThread());
}
void checkBox() {
JCheckBox chkBox = new JCheckBox("OK");
chkBox.setBounds(150, 92, 60, 24);
frame.add(chkBox);
chkBox.setToolTipText("check box");
chkBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent evt) {
if (evt.getStateChange()==1) {
label.setText("check box checked");
} else {
label.setText("check box unchecked");
}
}
}
);
chkBox.repaint();
println("EDT checkBox = " + javax.swing.SwingUtilities.isEventDispatchThread());
}
void label() {
label = new JLabel();
label.setHorizontalAlignment(JLabel.CENTER);
label.setBounds(30, 10, 350, 30);
label.setText("Label for output display.");
label.setToolTipText("label");
frame.add(label);
label.repaint();
println("EDT label = " + javax.swing.SwingUtilities.isEventDispatchThread());
}
void radioGrp() {
ButtonGroup radioGrp = new ButtonGroup();
JRadioButton radio1 = new JRadioButton("A");
radio1.setSelected(true);
JRadioButton radio2 = new JRadioButton("B");
JRadioButton radio3 = new JRadioButton("C");
radio1.setBounds(200, 90, 45, 30);
radio2.setBounds(250, 90, 45, 30);
radio3.setBounds(300, 90, 60, 30);
radioGrp.add(radio1);
radioGrp.add(radio2);
radioGrp.add(radio3);
radio1.setToolTipText("radio button group");
frame.add(radio1);
frame.add(radio2);
frame.add(radio3);
radio1.addItemListener( new ItemListener() {
void itemStateChanged(ItemEvent evnt) {
if (evnt.getStateChange()==1) {
label.setText("Radio1 selected.");
}
}
}
);
radio2.addItemListener( new ItemListener() {
void itemStateChanged(ItemEvent evnt) {
if (evnt.getStateChange()==1) {
label.setText("Radio2 selected.");
}
}
}
);
radio3.addItemListener( new ItemListener() {
void itemStateChanged(ItemEvent evnt) {
if (evnt.getStateChange()==1) {
label.setText("Radio3 selected.");
}
}
}
);
radio1.repaint(); // So they will show up when exported to app.
radio2.repaint();
radio3.repaint();
println("EDT radioGrp = " + javax.swing.SwingUtilities.isEventDispatchThread());
}
void progressBar() {
JProgressBar pbar = new JProgressBar();
pbar.setBounds(50, 180, 250, 30);
pbar.setValue(75);
pbar.setToolTipText("progress bar");
frame.add(pbar);
pbar.repaint();
println("EDT progressBar = " + javax.swing.SwingUtilities.isEventDispatchThread());
}
void comboBox() {
String country[]={"France", "Australia", "U.S.A", "England", "New Zealand"};
JComboBox comboBox = new JComboBox(country);
comboBox.setBounds(550, 60, 130, 24);
comboBox.setToolTipText("comboBox");
frame.add(comboBox);
println("EDT comboBox = " + javax.swing.SwingUtilities.isEventDispatchThread());
}
void listControl() {
DefaultListModel<String> listArray = new DefaultListModel<>();
listArray.addElement("Item 1");
listArray.addElement("Item 2");
listArray.addElement("Item 3");
listArray.addElement("Item 4");
JList<String> list = new JList<>(listArray);
list.setBounds(560, 120, 100, 75);
list.setToolTipText("list");
frame.add(list);
// **** Listener **** //
list.addListSelectionListener( new ListSelectionListener() {
void valueChanged(ListSelectionEvent evnt) {
label.setText(list.getSelectedValue() + " was selected.");
}
}
);
list.repaint();
println("EDT list = " + javax.swing.SwingUtilities.isEventDispatchThread());
}
void spinner() {
//syntax: (init, min, max, step)
SpinnerModel value = new SpinnerNumberModel(5, 0, 100, 1);
JSpinner spinner = new JSpinner(value);
spinner.setBounds(300, 130, 50, 30);
spinner.setToolTipText("spinner");
((JSpinner.DefaultEditor) spinner.getEditor()).getTextField().setEditable(false);
frame.add(spinner);
println("EDT spinner = " + javax.swing.SwingUtilities.isEventDispatchThread());
}
void tabbedPane() {
JPanel panel1 = new JPanel();
panel1.setBackground(Color.BLUE);
JPanel panel2 = new JPanel();
panel2.setBackground(Color.GREEN);
JPanel panel3 = new JPanel();
panel3.setBackground(Color.RED);
JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.setBounds(420, 230, 250, 150);
tabbedPane.add("Tab 1", panel1);
tabbedPane.add("Tab 2", panel2);
tabbedPane.add("Tab 3", panel3);
tabbedPane.setToolTipText("tabbed pane");
frame.add(tabbedPane);
// **** Action **** //
tabbedPane.addChangeListener(new ChangeListener() {
void stateChanged(ChangeEvent changeEvent) {
int index = tabbedPane.getSelectedIndex();
label.setText(tabbedPane.getTitleAt(index) + " was selected.");
}
}
);
tabbedPane.repaint();
println("EDT tabbedPane = " + javax.swing.SwingUtilities.isEventDispatchThread());
}
void table() {
String data[][] = {
{"Boat", "Yellow", "Yes"},
{"Car", "Magenta", "Yes"},
{"House", "White", "No"}
};
String header[] = {"ITEM", "COLOR", "FOR SALE"};
JTable table = new JTable(data, header);
table.setSelectionForeground(Color.WHITE);
table.setToolTipText("table");
JScrollPane scrlPane = new JScrollPane(table);
scrlPane.setBounds(430, 400, 220, 80);
frame.add(scrlPane);
// **** Listener **** //
ListSelectionModel cellSelectionModel = table.getSelectionModel();
cellSelectionModel.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
cellSelectionModel.addListSelectionListener(new ListSelectionListener() {
void valueChanged(ListSelectionEvent evnt) {
String selectedData = null;
int[] selectedRow = table.getSelectedRows();
int[] selectedColumns = table.getSelectedColumns();
for (int i = 0; i < selectedRow.length; i++) {
for (int j = 0; j < selectedColumns.length; j++) {
selectedData = (String) table.getValueAt(selectedRow[i], selectedColumns[j]);
label.setText(selectedData + " was selected.");
}
}
}
}
);
println("EDT table = " + javax.swing.SwingUtilities.isEventDispatchThread());
}
class GPanel extends JPanel {
GPanel() {
setBounds(380, 60, 150, 150);
setBorder(BorderFactory.createLineBorder(Color.BLACK));
}
@Override
void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor (dotColor);
g.fillOval(getWidth()/2 - radius, getHeight()/2 - radius, radius * 2, radius * 2);
}
}
void panel() {
panel = new GPanel();
panel.setToolTipText("panel");
frame.add(panel);
panel.repaint();
println("EDT panel = " + javax.swing.SwingUtilities.isEventDispatchThread());
}
void buildWnd() {
panel();
textArea();
checkBox();
radioGrp();
label();
progressBar();
colorBtn();
comboBox();
listControl();
spinner();
tabbedPane();
table();
menuBar();
textField();
button();
sliderWithTicks();
slider_plain();
}
void setup() {
frame = (javax.swing.JFrame) ((processing.awt.PSurfaceAWT.SmoothCanvas) surface.getNative()).getFrame();
canvas = (processing.awt.PSurfaceAWT.SmoothCanvas) ((processing.awt.PSurfaceAWT)surface).getNative();
frame.setBounds(500, 300, _wndW, _wndH);
frame.remove(canvas);
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
buildWnd(); // Builds components on EventDispatchThread
}
});
}