重新理解对象参数的用法


 最近一直在用Swing编程,碰到了一个问题,想的很长时间都没有解决,最终请教了高人一下:

问题是:父面板和子面板,父面板上有一个按钮,点击后弹出子面板,在子面板上填加相应的信息,最后把信息回传到父面板上,刚开始是这样设计:

if(e.getSource() == addArgsButton) {

    HTTPWEBDetailsPane httpWebDetailsPane = new HTTPWEBDetailsPane();
    argTemplItemList.addAll(httpWebDetailsPane.getArgTemplItemList());
}


HTTPWEBDetailsPane 是子面板,相应代码如下:

package com.mousedou.monitor.datashow.alarm.mainarea.schedule;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import Common.Action;
import Common.ArgTempl;
import Common.ArgTemplItem;
import Common.ArgType;
import Common.AssertType;
import Common.CollectType;
import Common.Element;
import Common.ElementType;
import Common.MonitorStep;
import Common.OrgRawRule;
import Common.ProtocolType;
import Common.RawOperate;
import Common.RawPosition;
import Common.RespAssert;
import Common.RespExpression;
import Common.RespRaw;
import Config.application.AppInfo;
import Config.application.ApplicationGrp;
import Config.application.ServiceInstance;
import Config.parameter.ParameterDef;
import Scheduler.NoExistAction;
import Scheduler.NoExistArgTempl;

import com.mousedou.monitor.alarmAnlyze.temp.ConvertUtil;
import com.mousedou.monitor.datashow.alarm.ParaDefManager;
import com.mousedou.monitor.datashow.alarm.mainarea.TableModel;
import com.mousedou.monitor.datashow.receive.Client;
import com.mousedou.monitor.datashow.receive.OperatorClient;

public class HTTPWEBDetailsPane implements ActionListener{
	
	private Logger log = LoggerFactory.getLogger(HTTPWEBDetailsPane.class);

	// 添加应用组窗口
	private JFrame frame;
	
	//主面板
	private JPanel pane;
	
	private Client client;
	
	
	//采集协议
	private ProtocolType protocolType;
	
	//参数模板
	private ArgTempl argTempl;
	
	//参数模板下拉框
	private JComboBox argTemplCB;
	
	
	//获得主机名
	public JTextField hostNameField;
	
	//获得端口号
	public JTextField portField;
	
	//获得路径
	public JTextField pathField;
	
	//获得方法名
	public String methodName;
	
	
	
	//ArgTemplItem列表,用来获取固定参数
	private List<ArgTemplItem> argTemplItemList ;
	
	
	public List<ArgTemplItem> getArgTemplItemList() {
		return argTemplItemList;
	}

	//添加固定参数按钮
	private JButton addArgsButton;
	
	//取消
	private JButton cancelButton;
	
	
	
	private static final Dimension JLabel_size = new Dimension(60, 25);
    private static final Dimension JTextField_size = new Dimension(110, 25);
    private static final Dimension JButton_size = new Dimension(60, 25);
    private static final Dimension JRadioButton_size = new Dimension(110, 25);
    private static final Dimension JComboBox_size = new Dimension(140, 25);
	
    //弹窗操作
    public HTTPWEBDetailsPane(){
    	super();
    	pane = new JPanel(new BorderLayout());
    	this.client = OperatorClient.getClient();
    	SwingUtilities.invokeLater(new Runnable() {

			@Override
			public void run() {
				frame = new JFrame();
				init(frame.getContentPane());
				frame.setTitle("HTTPWEBDetailsPane");
				frame.setSize(280, 260);
				frame.setLocation(400, 240);
				frame.setVisible(true);
				
			}

		});
    }
    
    
    private void init(Container container) {
		if (container instanceof JFrame) {
			((JFrame) container).setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		}
		initPane();
		container.add(pane, BorderLayout.CENTER);
	}
    
	private void initPane(){
		
		JPanel paneN = new JPanel();
		paneN.setPreferredSize(new Dimension(975, 10));
		paneN.setBackground(Color.WHITE);
		pane.add(paneN, BorderLayout.NORTH);
		
		JPanel paneS = new JPanel();
		paneS.setPreferredSize(new Dimension(975, 15));
		paneS.setBackground(Color.WHITE);
		pane.add(paneS, BorderLayout.SOUTH);
		
		JPanel paneE = new JPanel();
		paneE.setPreferredSize(new Dimension(15, 580));
		paneE.setBackground(Color.WHITE);
		pane.add(paneE, BorderLayout.EAST);
		
		JPanel paneW = new JPanel();
		paneW.setPreferredSize(new Dimension(15, 580));
		paneW.setBackground(Color.WHITE);
		pane.add(paneW, BorderLayout.WEST);
		
		JPanel paneC = new JPanel(new BorderLayout());
		paneC.setBackground(Color.WHITE);
		pane.add(paneC, BorderLayout.CENTER);
		setPaneC(paneC);
	}
	
	private void setPaneC(JPanel paneC){
		
		JPanel addArgsPane = new JPanel(new BorderLayout());
		addArgsPane.setPreferredSize(new Dimension(280, 260));
		JPanel addArgsPaneC = new JPanel(new GridLayout(4, 0));
		JPanel addArgsPaneC1 = new JPanel(new FlowLayout(FlowLayout.LEADING));
		addArgsPaneC1.add(getTitleLabel("主机名"));
		addArgsPaneC1.add(getHostName());
		addArgsPaneC.add(addArgsPaneC1);
		JPanel addArgsPaneC2 = new JPanel(new FlowLayout(FlowLayout.LEADING));
		addArgsPaneC2.add(getTitleLabel("端口号"));
		addArgsPaneC2.add(getPort());
		addArgsPaneC.add(addArgsPaneC2);
		JPanel addArgsPaneC3 = new JPanel(new FlowLayout(FlowLayout.LEADING));
		addArgsPaneC3.add(getTitleLabel("路径"));
		addArgsPaneC3.add(getPath());
		addArgsPaneC.add(addArgsPaneC3);
		JPanel addArgsPaneC4 = new JPanel(new FlowLayout(FlowLayout.LEADING));
		addArgsPaneC4.add(getTitleLabel("方法名"));
		addArgsPaneC4.add(getMethodCB());
		addArgsPaneC.add(addArgsPaneC4);
		addArgsPane.add(addArgsPaneC);
		
		JPanel addArgsPaneS = new JPanel(new FlowLayout());
		addArgsPaneS.setPreferredSize(new Dimension(280, 40));
		
		final JFrame addArgsPaneFrame = new JFrame();
		addArgsPaneS.add(getArgsSaveButton(addArgsPaneFrame));
		addArgsPaneS.add(new JLabel(" "));
		addArgsPaneS.add(getArgsCancelButton(addArgsPaneFrame));
		addArgsPane.add(addArgsPaneS, BorderLayout.SOUTH);
		
		paneC.add(addArgsPane, BorderLayout.CENTER);
		
		
	}
	
	/**
	 * 获得名为name的标签 右对齐
	 * @param name
	 * @return
	 */
	public JLabel getTitleLabel(String name){
		JLabel label = new JLabel(name, JLabel.TRAILING);
		label.setPreferredSize(JLabel_size);
		return label;
	}
	
	/**
	 * 获得主机名
	 */
	private JTextField getHostName() {
		hostNameField = new JTextField();
		hostNameField.setPreferredSize(JTextField_size);
		return hostNameField;
	}
	
	/**
	 * 获得端口号
	 */
	private JTextField getPort() {
		portField = new JTextField();
		portField.setPreferredSize(JTextField_size);
		return portField;
	}
	
	/**
	 * 获得路径
	 */
	private JTextField getPath() {
		pathField = new JTextField();
		pathField.setPreferredSize(JTextField_size);
		return pathField;
	}
	
	/**
	 * 获得方法名下拉框
	 */
	private JComboBox getMethodCB() {
		JComboBox methodCB = new JComboBox();
		methodCB.addItem(" ");
		methodCB.addItem("GET");
		methodCB.addItem("POST");
		methodCB.addItemListener(new ItemListener() {

			@Override
			public void itemStateChanged(ItemEvent e) {
				String s = (String)e.getItem();
				if(!s.equals(" ")){
					methodName = s;
				}else{
					methodName = null;
				}
			}
		});
		return methodCB;
	}
	
	
	/**
	 * 固定参数保存按钮
	 * @param frame
	 * @return
	 */
	private JButton getArgsSaveButton(final JFrame frame){
		addArgsButton = new JButton("保存");
		addArgsButton.setPreferredSize(JButton_size);
		addArgsButton.addActionListener(this);
		
		return addArgsButton;
	}
	
	/**
	 * 取消按钮
	 * @param frame
	 * @return
	 */
	private JButton getArgsCancelButton(final JFrame frame){
		cancelButton = new JButton("取消");
		cancelButton.setPreferredSize(JButton_size);
		cancelButton.addActionListener(this);
		return cancelButton;
	}
	
	
	@Override
	public void actionPerformed(ActionEvent e) {
		if(e.getSource() == addArgsButton) {
			String hostnameTemp = hostNameField.getText();
			String portTemp = portField.getText();
			String pathTemp = pathField.getText();
			String methodNameTemp = methodName;
			
			if(hostnameTemp == null || "".equals(hostnameTemp)){
				JOptionPane.showMessageDialog(null, "请填写主机名!", "警告", JOptionPane.WARNING_MESSAGE);
			}else if(portTemp == null || "".equals(portTemp)){
				JOptionPane.showMessageDialog(null, "请填写端口号!", "警告", JOptionPane.WARNING_MESSAGE);
			}else if(pathTemp == null || "".equals(pathTemp)){
				JOptionPane.showMessageDialog(null, "请填写路径!", "警告", JOptionPane.WARNING_MESSAGE);
			}else if(methodNameTemp == null || "".equals(methodNameTemp)){
				JOptionPane.showMessageDialog(null, "请选择参数名称!", "警告", JOptionPane.WARNING_MESSAGE);
			} else{
				List<ArgTemplItem> argItemList = new ArrayList<ArgTemplItem>();
				ArgTemplItem argTemplItem1 = new ArgTemplItem("hostname", "主机名", hostnameTemp.getBytes(), ConvertUtil.encodeArgType("String"), ".*", "访问的主机名");
				ArgTemplItem argTemplItem2 = new ArgTemplItem("port", "访问端口", portTemp.getBytes(), ConvertUtil.encodeArgType("int"), ".*", "访问的端口,默认为80");
				ArgTemplItem argTemplItem3 = new ArgTemplItem("path", "访问路径", pathTemp.getBytes(), ConvertUtil.encodeArgType("String"), ".*", "访问的文件名或路径");
				ArgTemplItem argTemplItem4 = new ArgTemplItem("methodName", "访问方法", methodNameTemp.getBytes(), ConvertUtil.encodeArgType("String"), ".*", "使用的方法“GET”或“POST”");
				
				argItemList.add(argTemplItem1);
				argItemList.add(argTemplItem2);
				argItemList.add(argTemplItem3);
				argItemList.add(argTemplItem4);
				
				argTemplItemList.addAll(argItemList);
				
				frame.dispose();
			}
		} else if(e.getSource() == cancelButton) {
			frame.dispose();
		}
		
	}
	
	public JPanel getHTTPWEBDetailsPane(){
		return pane;
	}
	
	public static void main(String[] args){
		SwingUtilities.invokeLater(new Runnable(){
			@Override
			public void run() {
				JFrame frame = new JFrame("HTTPWEBDetailsPane");
				HTTPWEBDetailsPane details = new HTTPWEBDetailsPane(null);
				frame.getContentPane().add(details.getHTTPWEBDetailsPane());
				frame.setSize(280, 260);
				frame.setLocation(400, 240);
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				frame.setVisible(true);
			}
			
		});
	}
	
	
	
}

正确的流程应该是弹出子面板后保存相应的数据到argTemplItemList,然后在父面板中调用子面板对象的getArgTemplItemList()方法,整好可以解决问题,就是上面第一段代码:

HTTPWEBDetailsPane httpWebDetailsPane = new HTTPWEBDetailsPane();
argTemplItemList.addAll(httpWebDetailsPane.getArgTemplItemList());

可实际上完全不是那么回事,因为这是两个线程,父面板是一个线程,子面板也是一个线程,调用子面板的同时父面板线程会继续运行下去,执行这一句代码:

httpWebDetailsPane.getArgTemplItemList();

这时候得到的ArgTemplItemList当然是空的了。

 

解决方案其实也很简单,就是把父面板中argTemplItemList作为子面板的参数传给子面板,再为子面板设计一个有参的构造方法,这样在子面板对这个参数做的改动就会自动反应到父面板上来。

正确的几外关键代码如下:

父面板中:

if("HTTP".equals(decodeProtocolType(protocolType))) {
					HTTPWEBDetailsPane httpWebDetailsPane = new HTTPWEBDetailsPane(argTemplItemList);
			}


子面板中:

//ArgTemplItem列表,用来获取固定参数
	private List<ArgTemplItem> argTemplItemList ;
//有参的构造参数
    public HTTPWEBDetailsPane(List<ArgTemplItem> argTemplItemList){
    	super();
    	this.argTemplItemList=argTemplItemList;
    	pane = new JPanel(new BorderLayout());
    	this.client = OperatorClient.getClient();
    	SwingUtilities.invokeLater(new Runnable() {

			@Override
			public void run() {
				frame = new JFrame();
				init(frame.getContentPane());
				frame.setTitle("HTTPWEBDetailsPane");
				frame.setSize(280, 260);
				frame.setLocation(400, 240);
				frame.setVisible(true);
				
			}

		});
    }


原理其实很简单,对象参数的用法,唉,基础真的很重要啊!



你可能感兴趣的:(编程,String,swing,null,Class,Path)