📄 fitinput.java
字号:
/*
*@(#)FitInput.java 2.0 2005/05/04
*
*清华大学 精密仪器与机械学系
*范灿升 fancansheng@163.com
*/
package input;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.TitledBorder;
import java.io.*;
import java.util.Vector;
//导入系统类
import lib.Library;
import lib.DataFileFilter;
import lib.InvalidFileFormatException;
import algorithm.Fit;
import plot.ViewPlotFrame;
import function.LinearFunction;
import function.PolynomialFunction;
//导入自定义的类
/**
*该类所提供的方法是供给类{@link Modeling}调用的,用以产生拟合与插值的数据输入界面。
*@version 2.0, 2005/05/04
*@author 范灿升
*@see Modeling
*@see algorithm.Fit
*/
public class FitInput implements ActionListener,FocusListener
{
private int i,j;
private int n,m;//n是回归方程中自变量的数目,m是数据的组数
private Vector textFieldVector;//只要是新建的JTextField,都把它加入该向量,里面的元素为JTextField[]
private Vector checkBoxVector;//只要是新建的JCheckBox,都把它加入该向量,里面的元素为JCheckBox
private JTextField[] tempTextField;//为了方便把JTextField加入上述向量方便而建的临时变量
private JCheckBox tempCheckBox;//为了方便把JCheckBox加入上述向量方便而建的临时变量
private int textFieldCount;//标记已经产生多少个JTextField
private boolean multiInput;//标记是一元拟合还是多元拟合
private boolean[] selected;//标记JCheckBox是否被选中
private double[][] xMatrix;
private double[] yMatrix;
private double[] xData;
private JButton multiButton;
private JButton multiHelpButton;
private JButton oneButton;
private JButton saveButton;
private JButton openButton;
private JButton oneHelpButton;
private JComboBox comboBox;
private String tmp;
private boolean pass;
private boolean secondTime;
/**
*输入面板的父组件。
*/
public Component parentComponent;
/**
*数据在该面板上输入,包括自变量与因变量的数据。
*/
public JPanel inputPanel;
/**
*用来放置计算按钮和帮助按钮等。
*/
public JPanel computePanel;
/**
*用来放置inputPanel的容器。
*/
public JPanel mainPanel;
/**
*产生包含方程组相关参数的类。
*@param parentComponent 输入面板的上一层组件
*@param inputPanel 数据在该面板上输入
*@param computePanel 面板上的按钮为计算用按钮
*@param mainPanel mainPanel是用来放置inputPanel的容器
*/
public FitInput(Component parentComponent,JPanel inputPanel,JPanel computePanel,JPanel mainPanel)
{
this.parentComponent=parentComponent;
this.inputPanel=inputPanel;
this.computePanel=computePanel;
this.mainPanel=mainPanel;
}
/**
*显示多元线性回归的数据输入界面。
*<p>用户从该界面输入数据中的自变量和因变量。
*/
public void showMulti()
{
multiInput=true;
pass=false;//用于标记是否通过合法性检验
secondTime=false;
while(!pass)
{
if(secondTime==true)
tmp=JOptionPane.showInputDialog(parentComponent,"请输入一个不少于2的整数!\n请重新输入:","输入自变量数目",JOptionPane.WARNING_MESSAGE);
else
tmp=JOptionPane.showInputDialog(parentComponent,"请输入回归方程中自变量的数目:","输入自变量数目",JOptionPane.QUESTION_MESSAGE);
try
{
if(tmp==null)
return;
n=-1;
n=Integer.parseInt(tmp);
}
catch(NumberFormatException e)
{
secondTime=true;
}
if(n>=2)
pass=true;
else
secondTime=true;
}
//输入自变量数目
GridLayout inputPanelLayout=new GridLayout(0,n+2);//n个自变量,一个因变量和一个JCheckBox
inputPanel.setLayout(inputPanelLayout);
inputPanel.removeAll();
JLabel[] variableLabel=new JLabel[n+2];
variableLabel[0]=new JLabel("y",JLabel.CENTER);
variableLabel[0].setFont(Library.font);
inputPanel.add(variableLabel[0]);
for(i=1;i<variableLabel.length-1;i++)
{
variableLabel[i]=new JLabel("x"+i,JLabel.CENTER);
variableLabel[i].setFont(Library.font);
inputPanel.add(variableLabel[i]);
}
variableLabel[n+1]=new JLabel("使用数据",JLabel.CENTER);
variableLabel[n+1].setFont(Library.font);
inputPanel.add(variableLabel[n+1]);
//往输入面板中添加标签
textFieldVector=new Vector();
checkBoxVector=new Vector();
textFieldCount=0;
tempTextField=new JTextField[n+1];
textFieldCount++;
tempTextField[0]=new JTextField(Library.TEXTFIELD_LENGTH);
tempTextField[0].setToolTipText("第"+textFieldCount+"组:y");
inputPanel.add(tempTextField[0]);
for(i=1;i<tempTextField.length;i++)//自变量的下标从1开始
{
tempTextField[i]=new JTextField(Library.TEXTFIELD_LENGTH);
tempTextField[i].setToolTipText("第"+textFieldCount+"组:x"+i);
inputPanel.add(tempTextField[i]);
}
textFieldVector.add(tempTextField);
tempCheckBox=new JCheckBox("使用",false);
tempCheckBox.setFont(Library.font);
inputPanel.add(tempCheckBox);
checkBoxVector.add(tempCheckBox);
//往输入面板中添加输入域
tempTextField[tempTextField.length-1].addFocusListener(this);
TitledBorder border=new TitledBorder("输入数据点数据");
border.setTitleFont(Library.font);
inputPanel.setBorder(border);
BoxLayout computePanelLayout=new BoxLayout(computePanel,BoxLayout.X_AXIS);
computePanel.setLayout(computePanelLayout);
multiButton=new JButton("多元线性回归",new ImageIcon(Library.polyhedronIcont_Scaled));
multiButton.setFont(Library.font);
computePanel.removeAll();
computePanel.add(multiButton);
multiHelpButton=new JButton("帮助",new ImageIcon(Library.helpIcon_Scaled));
multiHelpButton.setFont(Library.font);
computePanel.add(multiHelpButton);
JScrollPane scrollPane=new JScrollPane(inputPanel);
mainPanel.removeAll();
mainPanel.add(scrollPane,BorderLayout.CENTER);
mainPanel.add(computePanel,BorderLayout.SOUTH);
//布局
multiButton.addActionListener(this);
multiHelpButton.addActionListener(this);
parentComponent.setSize(parentComponent.getPreferredSize());
parentComponent.setVisible(true);
}
/**
*显示一元拟合的数据输入界面,包括一元线性回归、多项式回归、三次样条插值。
*<p>用户从该界面输入数据中的自变量和因变量。
*/
public void showOne()
{
multiInput=false;
n=1;//为了与多元线性回归的输入程序代码一致,这里采用直接对n赋值的方法
GridLayout inputPanelLayout=new GridLayout(0,n+2);//一个自变量,一个因变量和一个JCheckBox
inputPanel.setLayout(inputPanelLayout);
inputPanel.removeAll();
JLabel[] variableLabel=new JLabel[n+2];
variableLabel[0]=new JLabel("y",JLabel.CENTER);
variableLabel[0].setFont(Library.font);
inputPanel.add(variableLabel[0]);
variableLabel[n]=new JLabel("x",JLabel.CENTER);
variableLabel[n].setFont(Library.font);
inputPanel.add(variableLabel[n]);
variableLabel[n+1]=new JLabel("使用数据",JLabel.CENTER);
variableLabel[n+1].setFont(Library.font);
inputPanel.add(variableLabel[n+1]);
//往输入面板中添加标签
textFieldVector=new Vector();
checkBoxVector=new Vector();
textFieldCount=0;
tempTextField=new JTextField[n+1];
textFieldCount++;
tempTextField[0]=new JTextField(Library.TEXTFIELD_LENGTH);
tempTextField[0].setToolTipText("第"+textFieldCount+"组:y");
inputPanel.add(tempTextField[0]);
tempTextField[n]=new JTextField(Library.TEXTFIELD_LENGTH);
tempTextField[n].setToolTipText("第"+textFieldCount+"组:x");
inputPanel.add(tempTextField[n]);
textFieldVector.add(tempTextField);
tempCheckBox=new JCheckBox("使用",false);
tempCheckBox.setFont(Library.font);
inputPanel.add(tempCheckBox);
checkBoxVector.add(tempCheckBox);
//往输入面板中添加输入域
tempTextField[tempTextField.length-1].addFocusListener(this);
TitledBorder border=new TitledBorder("输入数据点数据");
border.setTitleFont(Library.font);
inputPanel.setBorder(border);
BoxLayout computePanelLayout=new BoxLayout(computePanel,BoxLayout.Y_AXIS);
computePanel.setLayout(computePanelLayout);
computePanel.removeAll();
String[] comboBoxString={"选择处理类型","一元线性回归","多项式回归"
/////////////////
//,"三次样条插值"
/////////////////
};
comboBox=new JComboBox(comboBoxString);
comboBox.setFont(Library.font);
computePanel.add(comboBox);
oneButton=new JButton("数据分析",new ImageIcon(Library.polyhedronIcont_Scaled));
oneButton.setFont(Library.font);
computePanel.add(oneButton);
saveButton=new JButton("保存数据",new ImageIcon(Library.aidIcon_Scaled));
saveButton.setFont(Library.font);
computePanel.add(saveButton);
openButton=new JButton("导入数据",new ImageIcon(Library.aidIcon_Scaled));
openButton.setFont(Library.font);
computePanel.add(openButton);
oneHelpButton=new JButton(" 帮 助 ",new ImageIcon(Library.helpIcon_Scaled));
oneHelpButton.setFont(Library.font);
computePanel.add(oneHelpButton);
comboBox.setMaximumSize(new Dimension(oneButton.getPreferredSize().width,comboBox.getPreferredSize().height));
comboBox.setAlignmentX(0);
JScrollPane scrollPane=new JScrollPane(inputPanel);
mainPanel.removeAll();
mainPanel.add(scrollPane,BorderLayout.CENTER);
mainPanel.add(computePanel,BorderLayout.EAST);
//布局
oneButton.addActionListener(this);
saveButton.addActionListener(this);
openButton.addActionListener(this);
oneHelpButton.addActionListener(this);
parentComponent.setSize(parentComponent.getPreferredSize());
parentComponent.setVisible(true);
}
/**
*由ActionListener所指定的方法,响应用户单击按钮时的动作
*@param e 单击按钮所产生的事件
*/
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==multiButton)
{
m=0;
selected=new boolean[textFieldCount];
for(i=0;i<textFieldCount;i++)
{
if(((JCheckBox)checkBoxVector.get(i)).isSelected())
{
selected[i]=true;
m++;
}
else
selected[i]=false;
}
//统计应该使用哪些数据
yMatrix=new double[m];
xMatrix=new double[m][n+1];//由于常数项的存在,xMatrix的第1列恒为1
int index=0;
if(m<n+1)
{
JOptionPane.showMessageDialog(parentComponent,"所选的数据的组数必须不小于"+(n+1),"数据不足",JOptionPane.WARNING_MESSAGE);
return;
}
for(i=0;i<textFieldCount;i++)
{
if(selected[i])
{
for(j=0;j<n+1;j++)
{
try
{
if(j==0)
{
yMatrix[index]=Double.parseDouble(((JTextField[])textFieldVector.get(i))[j].getText());
xMatrix[index][0]=1;
}
else
xMatrix[index][j]=Double.parseDouble(((JTextField[])textFieldVector.get(i))[j].getText());
}
catch(NumberFormatException nException)
{
if(j==0)
tmp="第"+(i+1)+"组数据的y值不是有效的数字!\n如果不需要这组数据,请把复选框中的勾去掉。";
else
tmp="第"+(i+1)+"组数据的x"+j+"的值不是有效的数字!\n如果不需要这组数据,请把复选框中的勾去掉。";
JOptionPane.showMessageDialog(parentComponent,tmp,"输入错误",JOptionPane.WARNING_MESSAGE);
return;
}
}
index++;//index和i是很不相同的
}
}
//完成值的传递
try
{
Fit multiFit=new Fit(xMatrix,yMatrix);
double[] result=multiFit.multiFit();
StringBuffer buffer=new StringBuffer("相关系数为"+(float)result[result.length-1]+"\n");
buffer.append("回归方程为:\n");
buffer.append("y = "+(float)result[0]);
for(i=1;i<result.length-1;i++)
{
if(result[i]>=0)
buffer.append("+"+(float)result[i]+" * x"+i);
else if(result[i]<0)
buffer.append((float)result[i]+" * x"+i);
//处理正负号
if(i%3==0)
buffer.append("\n");
}
JOptionPane.showMessageDialog(parentComponent,buffer,
"回归分析结果",JOptionPane.INFORMATION_MESSAGE,new ImageIcon(Library.polyhedronIcont_Scaled));
}//把double在显示时转换为float显示效果会好一点
catch(NullPointerException nullE)
{
JOptionPane.showMessageDialog(parentComponent,
"数据有误。\n适合数据的回归方程有无穷多个。\n请重新检查数据!","数据错误",JOptionPane.WARNING_MESSAGE);
}
//显示求解结果
}
//multiButton的动作
if(e.getSource()==multiHelpButton)
{
ImageIcon helpMessage=new ImageIcon("resource\\MultiFitHelp.GIF");
JOptionPane.showMessageDialog(parentComponent,helpMessage,"输入帮助",JOptionPane.INFORMATION_MESSAGE,new ImageIcon(Library.helpIcon_Scaled));
}
if(e.getSource()==oneButton)
//一元拟合
{
m=0;
selected=new boolean[textFieldCount];
for(i=0;i<textFieldCount;i++)
{
if(((JCheckBox)checkBoxVector.get(i)).isSelected())
{
selected[i]=true;
m++;
}
else
selected[i]=false;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -