📄 visualizepanel.java
字号:
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* VisualizePanel.java
* Copyright (C) 1999 Mark Hall, Malcolm Ware
*
*/
package weka.gui.visualize;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
import java.util.Random;
import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.SwingConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.filechooser.FileFilter;
import weka.core.Attribute;
import weka.core.FastVector;
import weka.core.Instance;
import weka.core.Instances;
import weka.gui.ExtensionFileFilter;
import weka.gui.Logger;
import eti.bi.common.Locale.Resource;
/**
* This panel allows the user to visualize a dataset (and if provided) a
* classifier's/clusterer's predictions in two dimensions.
*
* If the user selects a nominal attribute as the colouring attribute then
* each point is drawn in a colour that corresponds to the discrete value
* of that attribute for the instance. If the user selects a numeric
* attribute to colour on, then the points are coloured using a spectrum
* ranging from blue to red (low values to high).
*
* When a classifier's predictions are supplied they are plotted in one
* of two ways (depending on whether the class is nominal or numeric).<br>
* For nominal class: an error made by a classifier is plotted as a square
* in the colour corresponding to the class it predicted.<br>
* For numeric class: predictions are plotted as varying sized x's, where
* the size of the x is related to the magnitude of the error.
*
* @author Mark Hall (mhall@cs.waikato.ac.nz)
* @author Malcolm Ware (mfw4@cs.waikato.ac.nz)
* @version $Revision$
*/
public class VisualizePanel extends JPanel {
/** Inner class to handle plotting */
protected class PlotPanel extends JPanel implements Plot2DCompanion {
/** The actual generic plotting panel */
protected Plot2D m_plot2D = new Plot2D();
/** The instances from the master plot */
protected Instances m_plotInstances=null;
/** The master plot */
protected PlotData2D m_originalPlot=null;
/** Indexes of the attributes to go on the x and y axis and the attribute
to use for colouring and the current shape for drawing */
protected int m_xIndex=0;
protected int m_yIndex=0;
protected int m_cIndex=0;
protected int m_sIndex=0;
/** Axis padding */
private final int m_axisPad = 5;
/** Tick size */
private final int m_tickSize = 5;
/**the offsets of the axes once label metrics are calculated */
private int m_XaxisStart=0;
private int m_YaxisStart=0;
private int m_XaxisEnd=0;
private int m_YaxisEnd=0;
/** True if the user is currently dragging a box. */
private boolean m_createShape;
/** contains all the shapes that have been drawn for these attribs */
private FastVector m_shapes;
/** contains the points of the shape currently being drawn. */
private FastVector m_shapePoints;
/** contains the position of the mouse (used for rubberbanding). */
private Dimension m_newMousePos;
//////
/** Constructor */
public PlotPanel() {
this.setBackground(m_plot2D.getBackground());
this.setLayout(new BorderLayout());
this.add(m_plot2D, BorderLayout.CENTER);
m_plot2D.setPlotCompanion(this);
m_createShape = false;
m_shapes = null;////
m_shapePoints = null;
m_newMousePos = new Dimension();
this.addMouseListener(new MouseAdapter() {
///////
public void mousePressed(MouseEvent e) {
if ((e.getModifiers() & MouseEvent.BUTTON1_MASK) == MouseEvent.BUTTON1_MASK) {
//
if (m_sIndex == 0) {
//do nothing it will get dealt to in the clicked method
}
else if (m_sIndex == 1) {
m_createShape = true;
m_shapePoints = new FastVector(5);
m_shapePoints.addElement(new Double(m_sIndex));
m_shapePoints.addElement(new Double(e.getX()));
m_shapePoints.addElement(new Double(e.getY()));
m_shapePoints.addElement(new Double(e.getX()));
m_shapePoints.addElement(new Double(e.getY()));
// Graphics g = PlotPanel.this.getGraphics();
Graphics g = m_plot2D.getGraphics();
g.setColor(Color.black);
g.setXORMode(Color.white);
g.drawRect(((Double)m_shapePoints.elementAt(1)).intValue(),
((Double)m_shapePoints.elementAt(2)).intValue(),
((Double)m_shapePoints.elementAt(3)).intValue() -
((Double)m_shapePoints.elementAt(1)).intValue(),
((Double)m_shapePoints.elementAt(4)).intValue() -
((Double)m_shapePoints.elementAt(2)).intValue());
g.dispose();
}
//System.out.println("clicked");
}
//System.out.println("clicked");
}
//////
public void mouseClicked(MouseEvent e) {
if ((m_sIndex == 2 || m_sIndex == 3) &&
(m_createShape ||
(e.getModifiers() & MouseEvent.BUTTON1_MASK) == MouseEvent.BUTTON1_MASK)) {
if (m_createShape) {
//then it has been started already.
Graphics g = m_plot2D.getGraphics();
g.setColor(Color.black);
g.setXORMode(Color.white);
if ((e.getModifiers() & MouseEvent.BUTTON1_MASK) == MouseEvent.BUTTON1_MASK) {
m_shapePoints.addElement(new
Double(m_plot2D.convertToAttribX(e.getX())));
m_shapePoints.addElement(new
Double(m_plot2D.convertToAttribY(e.getY())));
m_newMousePos.width = e.getX();
m_newMousePos.height = e.getY();
g.drawLine((int)Math.ceil
(m_plot2D.convertToPanelX
(((Double)m_shapePoints.
elementAt(m_shapePoints.size() - 2)).
doubleValue())),
(int)Math.ceil
(m_plot2D.convertToPanelY
(((Double)m_shapePoints.
elementAt(m_shapePoints.size() - 1)).
doubleValue())),
m_newMousePos.width, m_newMousePos.height);
}
else if (m_sIndex == 3) {
//then extend the lines to infinity
//(100000 or so should be enough).
//the area is selected by where the user right clicks
//the mouse button
m_createShape = false;
if (m_shapePoints.size() >= 5) {
double cx = Math.ceil
(m_plot2D.convertToPanelX
(((Double)m_shapePoints.elementAt
(m_shapePoints.size() - 4)).doubleValue()));
double cx2 = Math.ceil
(m_plot2D.convertToPanelX
(((Double)m_shapePoints.elementAt
(m_shapePoints.size() - 2)).doubleValue())) -
cx;
cx2 *= 50000;
double cy = Math.ceil
(m_plot2D.
convertToPanelY(((Double)m_shapePoints.
elementAt(m_shapePoints.size() - 3)).
doubleValue()));
double cy2 = Math.ceil
(m_plot2D.convertToPanelY(((Double)m_shapePoints.
elementAt(m_shapePoints.size() - 1)).
doubleValue())) - cy;
cy2 *= 50000;
double cxa = Math.ceil(m_plot2D.convertToPanelX
(((Double)m_shapePoints.
elementAt(3)).
doubleValue()));
double cxa2 = Math.ceil(m_plot2D.convertToPanelX
(((Double)m_shapePoints.
elementAt(1)).
doubleValue())) - cxa;
cxa2 *= 50000;
double cya = Math.ceil
(m_plot2D.convertToPanelY
(((Double)m_shapePoints.elementAt(4)).
doubleValue()));
double cya2 = Math.ceil
(m_plot2D.convertToPanelY
(((Double)m_shapePoints.elementAt(2)).
doubleValue())) - cya;
cya2 *= 50000;
m_shapePoints.setElementAt
(new Double(m_plot2D.convertToAttribX(cxa2 + cxa)), 1);
m_shapePoints.setElementAt
(new Double(m_plot2D.convertToAttribY(cy2 + cy)),
m_shapePoints.size() - 1);
m_shapePoints.setElementAt
(new Double(m_plot2D.convertToAttribX(cx2 + cx)),
m_shapePoints.size() - 2);
m_shapePoints.setElementAt
(new Double(m_plot2D.convertToAttribY(cya2 + cya)), 2);
//determine how infinity line should be built
cy = Double.POSITIVE_INFINITY;
cy2 = Double.NEGATIVE_INFINITY;
if (((Double)m_shapePoints.elementAt(1)).
doubleValue() >
((Double)m_shapePoints.elementAt(3)).
doubleValue()) {
if (((Double)m_shapePoints.elementAt(2)).
doubleValue() ==
((Double)m_shapePoints.elementAt(4)).
doubleValue()) {
cy = ((Double)m_shapePoints.elementAt(2)).
doubleValue();
}
}
if (((Double)m_shapePoints.elementAt
(m_shapePoints.size() - 2)).doubleValue() >
((Double)m_shapePoints.elementAt
(m_shapePoints.size() - 4)).doubleValue()) {
if (((Double)m_shapePoints.elementAt
(m_shapePoints.size() - 3)).
doubleValue() ==
((Double)m_shapePoints.elementAt
(m_shapePoints.size() - 1)).doubleValue()) {
cy2 = ((Double)m_shapePoints.lastElement()).
doubleValue();
}
}
m_shapePoints.addElement(new Double(cy));
m_shapePoints.addElement(new Double(cy2));
if (!inPolyline(m_shapePoints, m_plot2D.convertToAttribX
(e.getX()),
m_plot2D.convertToAttribY(e.getY()))) {
Double tmp = (Double)m_shapePoints.
elementAt(m_shapePoints.size() - 2);
m_shapePoints.setElementAt
(m_shapePoints.lastElement(),
m_shapePoints.size() - 2);
m_shapePoints.setElementAt
(tmp, m_shapePoints.size() - 1);
}
if (m_shapes == null) {
m_shapes = new FastVector(4);
}
m_shapes.addElement(m_shapePoints);
m_submit.setText("Submit");
m_submit.setActionCommand("Submit");
m_submit.setEnabled(true);
}
m_shapePoints = null;
PlotPanel.this.repaint();
}
else {
//then close the shape
m_createShape = false;
if (m_shapePoints.size() >= 7) {
m_shapePoints.addElement(m_shapePoints.elementAt(1));
m_shapePoints.addElement(m_shapePoints.elementAt(2));
if (m_shapes == null) {
m_shapes = new FastVector(4);
}
m_shapes.addElement(m_shapePoints);
m_submit.setText("Submit");
m_submit.setActionCommand("Submit");
m_submit.setEnabled(true);
}
m_shapePoints = null;
PlotPanel.this.repaint();
}
g.dispose();
//repaint();
}
else if ((e.getModifiers() & MouseEvent.BUTTON1_MASK) == MouseEvent.BUTTON1_MASK) {
//then this is the first point
m_createShape = true;
m_shapePoints = new FastVector(17);
m_shapePoints.addElement(new Double(m_sIndex));
m_shapePoints.addElement(new
Double(m_plot2D.convertToAttribX(e.getX()))); //the new point
m_shapePoints.addElement(new
Double(m_plot2D.convertToAttribY(e.getY())));
m_newMousePos.width = e.getX(); //the temp mouse point
m_newMousePos.height = e.getY();
Graphics g = m_plot2D.getGraphics();
g.setColor(Color.black);
g.setXORMode(Color.white);
g.drawLine((int)Math.ceil
(m_plot2D.convertToPanelX(((Double)m_shapePoints.
elementAt(1)).doubleValue())),
(int)Math.ceil
(m_plot2D.convertToPanelY(((Double)m_shapePoints.
elementAt(2)).doubleValue())),
m_newMousePos.width, m_newMousePos.height);
g.dispose();
}
}
else {
if ((e.getModifiers() & InputEvent.BUTTON1_MASK) ==
InputEvent.BUTTON1_MASK) {
m_plot2D.searchPoints(e.getX(),e.getY(), false);
} else {
m_plot2D.searchPoints(e.getX(), e.getY(), true);
}
}
}
/////////
public void mouseReleased(MouseEvent e) {
if (m_createShape) {
if (((Double)m_shapePoints.elementAt(0)).intValue() == 1) {
m_createShape = false;
Graphics g = m_plot2D.getGraphics();
g.setColor(Color.black);
g.setXORMode(Color.white);
g.drawRect(((Double)m_shapePoints.elementAt(1)).
intValue(),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -