// action can be Runnable or a function name static JButton jThreadedButton(S text, O action) { ret swing(func -> JButton { S text2 = dropPrefix("[disabled] ", text); JButton btn = basicJButton(text2); if (l(text2) < l(text)) btn.setEnabled(false); btn.setToolTipText(btn.getText()); if (action != null) btn.addActionListener(actionListenerInNewThread(action, btn)); ret btn; }); } static JButton jThreadedButton(S text, Runnable action) { ret jThreadedButton(text, (O) action); }