应用场合:做java界面时,用户做某些操作调用某方法,且方法不能及时返回,但,不想用户频繁做此操作,为了避免用户频繁操作,当这些操作做完后,弹出一个模态框,使得用户不能对该界面以及模态框做任何操作,直到方法返回后,模态框自动关闭,才可做其他操作,用此方法规范用户操作。例如,用户点击某按钮使得客户机向服务器请求资源,由于各种原因导致资源不能及时获取到,用户可能频繁点击该按钮,使得在此瞬间向服务器发送大量重复的资源请求,这些无效请求不仅加大服务器负载压力,还浪费带宽,反而加长资源请求时间,为了规避用户此操作,应该弹出一个模态框来取消方法返回前用户的控制权,当方法返回后再归还控制权,避免上述操作带来的恶性后果。
对此,做了一个工具类帮助实现模态框开启和关闭过程。代码如下:
public class ModelDialog extends JDialog{ private static final long serialVersionUID = 1L; private Container container; private String message; private Method method; private Object object; private Object[] args; private Object result; public ModelDialog() { super(); } public ModelDialog(JFrame parent, String message, Method method, Object object, Object[] args) { super(parent, true); this.message = message; this.method = method; this.object = object; this.args = args; } private void drawDialog() { Font font = new Font("宋体", Font.BOLD, 16); Container parent = getParent(); int parentLeft = parent.getX(); int parentTop = parent.getY(); int parentWidth = parent.getWidth(); int parentHeight = parent.getHeight(); int width = (this.message.length() + 4) * font.getSize(); int height = 5 * font.getSize(); setSize(width, height); setLocation(parentLeft + (parentWidth - width) / 2, parentTop + (parentHeight - height) / 2); this.container = getContentPane(); this.container.setLayout(null); setUndecorated(true); JPanel jpnlMessage = new JPanel(); jpnlMessage.setSize(width, height); jpnlMessage.setLayout(new BorderLayout()); jpnlMessage.setBackground(Color.white); jpnlMessage.setBorder(BorderFactory.createLineBorder(Color.black, 2)); this.container.add(jpnlMessage); JLabel jlblMessage = new JLabel(this.message, JLabel.CENTER); jlblMessage.setFont(font); jlblMessage.setSize(width, height); jlblMessage.setForeground(Color.blue); jlblMessage.setHorizontalTextPosition(JLabel.CENTER); jpnlMessage.add(jlblMessage, BorderLayout.CENTER); } private void dealMethod() { addFocusListener(new FocusAdapter() { @Override public void focusGained(FocusEvent e) { try { result = method.invoke(object, args); } catch (IllegalAccessException e1) { e1.printStackTrace(); } catch (IllegalArgumentException e1) { e1.printStackTrace(); } catch (InvocationTargetException e1) { e1.printStackTrace(); } //关闭模态框 dispose(); } }); } //显示模态框 public ModelDialog showDialog() { drawDialog(); dealMethod(); setVisible(true); return this; } //获取方法执行结果 public Object getResult() { return this.result; } }补充说明:当调用showDialog()方法,执行setVisible(true)后,后续代码将不执行,该线程进入waiting状态,所以不能再此后执行方法的反射调用以及模态框的关闭,为了解决该方法时,第一种思路是开启一个线程,在线程里执行setVisible(true)方法,但最后都以失败告终,模态框的功能实现了,但是不能在屏幕上显示。对此,换了一种思路,即dealMethod()方法,给模态框加上事件,当成功在屏幕上显示获取焦点后,执行方法的反射以及模态框的关闭,便可以成功实现模态框工具的功能。
作者:庞云刚 2019.10.31