gui.java

来自「Weka」· Java 代码 · 共 2,050 行 · 第 1/5 页

JAVA
2,050
字号
/*
 *    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.
 */

/*
 *    GUI.java
 *    Copyright (C) 2007 University of Waikato, Hamilton, New Zealand
 *
 */
package weka.classifiers.bayes.net;

import weka.core.FastVector;
import weka.core.Instances;
import weka.core.OptionHandler;
import weka.core.SerializedObject;
import weka.core.Utils;
import weka.gui.ExtensionFileFilter;
import weka.gui.GenericObjectEditor;
import weka.gui.PropertyDialog;
import weka.gui.graphvisualizer.BIFFormatException;
import weka.gui.graphvisualizer.BIFParser;
import weka.gui.graphvisualizer.GraphNode;
import weka.gui.graphvisualizer.HierarchicalBCEngine;
import weka.gui.graphvisualizer.LayoutCompleteEvent;
import weka.gui.graphvisualizer.LayoutCompleteEventListener;
import weka.gui.graphvisualizer.LayoutEngine;
import weka.gui.visualize.PrintablePanel;
import weka.classifiers.bayes.net.BIFReader;
import weka.classifiers.bayes.net.BayesNetGenerator;
import weka.classifiers.bayes.net.EditableBayesNet;
import weka.classifiers.bayes.net.MarginCalculator;
import weka.classifiers.bayes.net.MarginCalculator.JunctionTreeNode;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.beans.PropertyEditor;
import java.io.*;
import java.util.Random;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;
import javax.swing.table.AbstractTableModel;

/**
 * GUI interface to Bayesian Networks. Allows editing Bayesian networks
 * on screen and provides GUI interface to various Bayesian network facilities
 * in Weka, including random network generation, data set generation and
 * Bayesion network inference.
 * 
 * @author Remco Bouckaert (remco@cs.waikato.ac.nz)
 * @version $Revision: 1.1 $
 */
public class GUI extends JPanel implements LayoutCompleteEventListener {

	/** for serialization */
	private static final long serialVersionUID = -2038911085935515624L;

	/** The current LayoutEngine */
	protected LayoutEngine m_layoutEngine;

	/** Panel actually displaying the graph */
	protected GraphPanel m_GraphPanel;

	/** Container of Bayesian network */
	EditableBayesNet m_BayesNet = new EditableBayesNet(true);

	/** String containing file name storing current network */
	protected String m_sFileName = "";
	/** used for calculating marginals in Bayesian netwowrks */
	MarginCalculator m_marginCalculator = null;

	/**
	 * used for calculating marginals in Bayesian netwowrks when evidence is
	 * present
	 */
	MarginCalculator m_marginCalculatorWithEvidence = null;

	/** flag indicating whether marginal distributions of each of the nodes 
	 * should be shown in display.
	 */
	boolean m_bViewMargins = false;
	boolean m_bViewCliques = false;

	/** data selected from file. Used to train a Bayesian network on */
	Instances m_Instances = null;

	/** Text field for specifying zoom */
	final JTextField m_jTfZoom;
	/** toolbar containing buttons at top of window */
	final JToolBar m_jTbTools;
	/** status bar at bottom of window */
	final JLabel m_jStatusBar;
	/** TextField for node's width */
	private final JTextField m_jTfNodeWidth = new JTextField(3);
	/** TextField for nodes height */
	private final JTextField m_jTfNodeHeight = new JTextField(3);
	/** this contains the m_GraphPanel GraphPanel */
	JScrollPane m_jScrollPane;

	/** path for icons */
	private final String ICONPATH = "weka/classifiers/bayes/net/icons/";

	/** current zoom value */
	private double m_fScale = 1;

	/** standard width of node */
	private int m_nNodeHeight = 2 * getFontMetrics(getFont()).getHeight();
	/** standard height of node */
	final static int DEFAULT_NODE_WIDTH = 50;
	private int m_nNodeWidth = DEFAULT_NODE_WIDTH;
	/** width of node, allowing for some padding */	
	final static int PADDING = 10;
	private int m_nPaddedNodeWidth = DEFAULT_NODE_WIDTH + PADDING;


	/** used when using zoomIn and zoomOut buttons */
	private int [] m_nZoomPercents = { 10, 25, 50, 75, 100, 125, 150, 175, 200, 225, 250, 275, 300, 350, 400, 450, 500,
			550, 600, 650, 700, 800, 900, 999 };

	/** actions triggered by GUI events */
	Action a_new = new ActionNew();

	Action a_quit = new ActionQuit();
	Action a_save = new ActionSave();
	ActionExport a_export = new ActionExport();
	ActionPrint a_print = new ActionPrint();
	Action a_load = new ActionLoad();
	Action a_zoomin = new ActionZoomIn();
	Action a_zoomout = new ActionZoomOut();
	Action a_layout = new ActionLayout();

	Action a_saveas = new ActionSaveAs();

	Action a_viewtoolbar = new ActionViewToolbar();

	Action a_viewstatusbar = new ActionViewStatusbar();

	Action a_networkgenerator = new ActionGenerateNetwork();

	Action a_datagenerator = new ActionGenerateData();

	Action a_datasetter = new ActionSetData();

	Action a_learn = new ActionLearn();
	Action a_learnCPT = new ActionLearnCPT();

	Action a_help = new ActionHelp();

	Action a_about = new ActionAbout();

	ActionAddNode a_addnode = new ActionAddNode();

	Action a_delnode = new ActionDeleteNode();
	Action a_cutnode = new ActionCutNode();
	Action a_copynode = new ActionCopyNode();
	Action a_pastenode = new ActionPasteNode();
	Action a_selectall = new ActionSelectAll();

	Action a_addarc = new ActionAddArc();

	Action a_delarc = new ActionDeleteArc();

	Action a_undo = new ActionUndo();

	Action a_redo= new ActionRedo();
	
	Action a_alignleft = new ActionAlignLeft();
	Action a_alignright = new ActionAlignRight();
	Action a_aligntop = new ActionAlignTop();
	Action a_alignbottom = new ActionAlignBottom();
	Action a_centerhorizontal = new ActionCenterHorizontal();
	Action a_centervertical = new ActionCenterVertical();
	Action a_spacehorizontal = new ActionSpaceHorizontal();
	Action a_spacevertical = new ActionSpaceVertical();
	
	/** node currently selected through right clicking */
	int m_nCurrentNode = -1;
	/** selection of nodes */
	Selection m_Selection = new Selection();
	/** selection rectangle drawn through dragging with left mouse button */
	Rectangle m_nSelectedRect = null;

	
	class Selection {
		FastVector m_selected;
		public Selection() {
			m_selected = new FastVector();
		} // c'tor
		public FastVector getSelected() {return m_selected;}
		void updateGUI() {
			if (m_selected.size() > 0) {
				a_cutnode.setEnabled(true);
				a_copynode.setEnabled(true);
			} else {
				a_cutnode.setEnabled(false);
				a_copynode.setEnabled(false);
			}
			if (m_selected.size() > 1) {
				a_alignleft.setEnabled(true);
				a_alignright.setEnabled(true);
				a_aligntop.setEnabled(true);
				a_alignbottom.setEnabled(true);
				a_centerhorizontal.setEnabled(true);
				a_centervertical.setEnabled(true);
				a_spacehorizontal.setEnabled(true);
				a_spacevertical.setEnabled(true);
			} else {
				a_alignleft.setEnabled(false);
				a_alignright.setEnabled(false);
				a_aligntop.setEnabled(false);
				a_alignbottom.setEnabled(false);
				a_centerhorizontal.setEnabled(false);
				a_centervertical.setEnabled(false);
				a_spacehorizontal.setEnabled(false);
				a_spacevertical.setEnabled(false);
			}
		} // updateGUI
		
		public void addToSelection(int nNode) {
			for (int iNode = 0; iNode < m_selected.size(); iNode++) {
				if (nNode == (Integer) m_selected.elementAt(iNode)) {
					return;
				}
			}
			m_selected.addElement(nNode);
			updateGUI();
		} // addToSelection
		
		public void addToSelection(int [] iNodes) {
			for (int iNode = 0; iNode < iNodes.length; iNode++) {
				addToSelection(iNodes[iNode]);
			}
			updateGUI();
		} // addToSelection
		
		public void addToSelection(Rectangle selectedRect) {
			for (int iNode = 0; iNode < m_BayesNet.getNrOfNodes(); iNode++) {
				if (contains(selectedRect, iNode)) {
					addToSelection(iNode);
				}
			}
		} // addToSelection
		
		public void selectAll() {
			m_selected.removeAllElements();
			for (int iNode = 0; iNode < m_BayesNet.getNrOfNodes(); iNode++) {
				m_selected.addElement(iNode);
			}
			updateGUI();
		} // selectAll

		boolean contains(Rectangle rect, int iNode) {
			return rect.intersects((m_BayesNet.getPositionX(iNode)) * m_fScale,
					(m_BayesNet.getPositionY(iNode)) * m_fScale,
					m_nPaddedNodeWidth * m_fScale, m_nNodeHeight * m_fScale);
		} // contains
		
		public void removeFromSelection(int nNode) {
			for (int iNode = 0; iNode < m_selected.size(); iNode++) {
				if (nNode == (Integer) m_selected.elementAt(iNode)) {
					m_selected.removeElementAt(iNode);
				}
			}
			updateGUI();
		} // removeFromSelection

		public void toggleSelection(int nNode) {
			for (int iNode = 0; iNode < m_selected.size(); iNode++) {
				if (nNode == (Integer) m_selected.elementAt(iNode)) {
					m_selected.removeElementAt(iNode);
					updateGUI();
					return;
				}
			}
			addToSelection(nNode);
		} // toggleSelection

		public void toggleSelection(Rectangle selectedRect)	{
			for (int iNode = 0; iNode < m_BayesNet.getNrOfNodes(); iNode++) {
				if (contains(selectedRect, iNode)) {
					toggleSelection(iNode);
				}
			}
		} // toggleSelection
		
		public void clear() {
			m_selected.removeAllElements();
			updateGUI();
		}
		
		public void draw(Graphics g) {
			if (m_selected.size() == 0) {
				return;
			}

			for (int iNode = 0; iNode < m_selected.size(); iNode++) {
				int nNode = (Integer) m_selected.elementAt(iNode);
				int nPosX = m_BayesNet.getPositionX(nNode);
				int nPosY = m_BayesNet.getPositionY(nNode);
				g.setColor(Color.BLACK);
				int nXRC = nPosX + m_nPaddedNodeWidth - m_nNodeWidth - (m_nPaddedNodeWidth - m_nNodeWidth) / 2;
				int nYRC = nPosY;
				int d = 5;
				g.fillRect(nXRC, nYRC, d, d); 
				g.fillRect(nXRC, nYRC + m_nNodeHeight, d, d); 
				g.fillRect(nXRC + m_nNodeWidth, nYRC, d, d); 
				g.fillRect(nXRC + m_nNodeWidth, nYRC + m_nNodeHeight, d, d); 
			}
		} // draw
	} // Selection

	ClipBoard m_clipboard = new ClipBoard();
	
	class ClipBoard {
		String m_sText = null;
		public ClipBoard() {
			if (a_pastenode != null) {
				a_pastenode.setEnabled(false);
			}
		}
		public boolean hasText() {return m_sText != null;}
		public String getText() { 
			return m_sText;
		}
		public void setText(String sText) {
			m_sText = sText;
			a_pastenode.setEnabled(true);
		}
	} // class ClipBoard
	
	/** Base class used for definining actions
	 * with a name, tool tip text, possibly an icon and accelerator key. 
	 * */
	class MyAction extends AbstractAction {
		/** for serialization */
		private static final long serialVersionUID = -2038911111935517L;

		public MyAction(String sName, String sToolTipText, String sIcon, String sAcceleratorKey) {
			super(sName);
			//setToolTipText(sToolTipText);
			putValue(Action.SHORT_DESCRIPTION, sToolTipText);
			putValue(Action.LONG_DESCRIPTION, sToolTipText);
			if (sAcceleratorKey.length() > 0) {
				KeyStroke keyStroke = KeyStroke.getKeyStroke(sAcceleratorKey);
				putValue(Action.ACCELERATOR_KEY, keyStroke);
			}
			putValue(Action.MNEMONIC_KEY, (int) sName.charAt(0));
			java.net.URL tempURL = ClassLoader.getSystemResource(ICONPATH + sIcon + ".png");
			if (tempURL != null) {
				putValue(Action.SMALL_ICON, new ImageIcon(tempURL));
			} else {
				putValue(Action.SMALL_ICON, new ImageIcon(new BufferedImage(20,20, BufferedImage.TYPE_4BYTE_ABGR)));
				//System.err.println(ICONPATH + sIcon + ".png not found for weka.gui.graphvisualizer.Graph");

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?