prefuse学习笔记(MV和MP3点播)
最近,学了一久的prefuse,感觉进度很慢,下面是我花了一个多星期才做了能拿出手的小程序,实现明星的MV和MP3点播的小程序,数据库用的MYSQL,库中有两张表一张stars表是记录明星资料的,另外一张表disk是用来记录明星唱片信息的,用prefuse可视化时从stars表中选取明星名称绑定到一个下拉的选择列中,供用户选择。
做的时候应注意以下几点:
1.mysql数据库我选的编码是utf8,所以在用JDBC连接时要说明用的编码,不然在查询时中文会产生乱码,找不到数据(以下红色文字)。
public static final String driverName= "com.mysql.jdbc.Driver";
// path for database
public static final String dbURL= "jdbc:mysql://localhost:3306/ontology?useUnicode=true&characterEncoding=utf8";
//username
public static final String userName= "root";
//password
public static final String userPwd= "sql123";
2.唱片中显示的图片,数据库中只存图片路径,加载时按存的路径加载。
3.由于JAVA的多媒体插件JMF只给播放avi的一些格式的视频,所以在MV浏览时,我选择调用本地的播放器。
4.做唱片提示信息时,tooltip无法换行显示的问题,我在另一篇文章中已提到,大家可以参考。
下面我先贴上效果图:
这是从列表选择所有明星的唱片
MV点播:
MP3点播:
import java.awt.BorderLayout; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.geom.Point2D; import java.text.NumberFormat; import java.util.Iterator; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.JOptionPane; import javax.swing.BoxLayout; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JToolBar; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import prefuse.Constants; import prefuse.Display; import prefuse.Visualization; import prefuse.action.ActionList; import prefuse.action.GroupAction; import prefuse.action.ItemAction; import prefuse.action.RepaintAction; import prefuse.action.animate.ColorAnimator; import prefuse.action.animate.LocationAnimator; import prefuse.action.animate.QualityControlAnimator; import prefuse.action.animate.VisibilityAnimator; import prefuse.action.assignment.DataShapeAction; import prefuse.action.assignment.FontAction; import prefuse.action.assignment.ColorAction; import prefuse.action.assignment.SizeAction; import prefuse.action.filter.VisibilityFilter; import prefuse.action.layout.AxisLayout; import prefuse.action.layout.RandomLayout; import prefuse.action.layout.graph.ForceDirectedLayout; import prefuse.activity.Activity; import prefuse.activity.ActivityAdapter; import prefuse.activity.ActivityListener; import prefuse.activity.SlowInSlowOutPacer; import prefuse.controls.*; import prefuse.data.Schema; import prefuse.data.Table; import prefuse.data.expression.AndPredicate; import prefuse.data.io.DelimitedTextTableReader; import prefuse.data.query.ListQueryBinding; import prefuse.data.tuple.TupleSet; import prefuse.render.DefaultRendererFactory; import prefuse.render.LabelRenderer; import prefuse.util.ColorLib; import prefuse.util.FontLib; import prefuse.util.PrefuseLib; import prefuse.util.UpdateListener; import prefuse.util.force.DragForce; import prefuse.util.force.ForceItem; import prefuse.util.force.ForceSimulator; import prefuse.util.force.NBodyForce; import prefuse.util.force.SpringForce; import prefuse.util.ui.BrowserLauncher; import prefuse.util.ui.JFastLabel; import prefuse.visual.VisualItem; import prefuse.visual.sort.ItemSorter; import prefuse.data.io.sql.*; public class Stars extends Display{ private static final String data= "data"; //jdbc driver name public static final String driverName= "com.mysql.jdbc.Driver"; // path for database public static final String dbURL= "jdbc:mysql://localhost:3306/ontology?useUnicode=true&characterEncoding=utf8"; //username public static final String userName= "root"; //password public static final String userPwd= "sql123"; private static String sql=null; private JFastLabel title; private JComboBox toolbar; private JPanel panel; private ListQueryBinding yearsQ; public Stars(Table t) { super(new Visualization()); m_vis.add(data,t); LabelRenderer nodeRenderer=new LabelRenderer("diskname","diskimage"); nodeRenderer.setHorizontalAlignment(Constants.LEFT); nodeRenderer.setImagePosition(Constants.TOP); nodeRenderer.setHorizontalPadding(0); nodeRenderer.setVerticalPadding(0); nodeRenderer.setMaxImageDimensions(200,200); nodeRenderer.setRoundedCorner(10, 10); yearsQ= new ListQueryBinding(t, "name"); m_vis.setRendererFactory(new DefaultRendererFactory(nodeRenderer)); ColorAction text = new ColorAction(data,VisualItem.TEXTCOLOR, ColorLib.gray(0)); FontAction fonts = new FontAction(data, FontLib.getFont("宋体&新宋体",15)); ActionList init = new ActionList(); init.add(text); init.add(fonts); init.add(new RandomLayout()); m_vis.putAction("init", init); //更新动作序列 ActionList update = new ActionList(); update.add(new ColorAction(data, VisualItem.STROKECOLOR) { //选中项红色高亮显示 public int getColor(VisualItem item) { return ColorLib.rgb((item.isHover()? 255 : 0), 0, 0); } }); update.add(new RepaintAction()); m_vis.putAction("update", update); //变换明星时用的过渡动画 ActionList animate = new ActionList(400); animate.setPacingFunction(new SlowInSlowOutPacer()); animate.add(new QualityControlAnimator()); animate.add(new VisibilityAnimator(data)); animate.add(new LocationAnimator(data)); animate.add(new ColorAnimator(data)); animate.add(new RepaintAction()); m_vis.putAction("animate", animate); m_vis.alwaysRunAfter("init", "animate"); // we run this to make sure the forces are stabilized ActionList preforce = new ActionList(2000); preforce.add(new DataMountainForceLayout(true)); m_vis.putAction("preforce", preforce); //功能是当拖动图片接近时,附近其它图片发生位移 final ForceDirectedLayout fl = new DataMountainForceLayout(false); ActivityListener fReset = new ActivityAdapter() { public void activityCancelled(Activity a) { fl.reset(); } }; ActionList forces = new ActionList(Activity.INFINITY); forces.add(fl); forces.add(update); forces.addActivityListener(fReset); m_vis.putAction("forces", forces); setSize(1000,650); setDamageRedraw(true); // disable due to Java2D image clipping errors setBorder(BorderFactory.createEmptyBorder(30,20,5,20)); //按提供的顺序渲染图片 setItemSorter(new DataMountainSorter()); //监听鼠标事件 addControlListener(new WheelZoomControl()); addControlListener(new DragControl()); addControlListener(new DataMouseControl()); addControlListener(new FocusControl(0, "update")); //显示控件 OnInitComponent(); // pre-load images, otherwise they will be loaded asynchronously nodeRenderer.getImageFactory().preloadImages(m_vis.items(),"diskimage"); // initialize and present the interface m_vis.run("init"); m_vis.runAfter("preforce", "update"); m_vis.run("preforce"); } public static Table GetData(String sql) { DatabaseDataSource datasrc =null; Table table=null; try { // declare a datasource datasrc = ConnectionFactory.getDatabaseConnection(driverName, dbURL, userName, userPwd); //create a table of data table= datasrc.getData(sql); } catch (Exception e) { e.printStackTrace(); System.exit(1); } return table; } public void OnInitComponent() { title= new JFastLabel(" "); title.setPreferredSize(new Dimension(350, 20)); title.setVerticalAlignment(SwingConstants.BOTTOM); title.setBorder(BorderFactory.createEmptyBorder(3,0,0,0)); title.setFont(FontLib.getFont("宋体", Font.PLAIN, 16)); //toolbar.addActionListener(new MyAction()); Box box= new Box(BoxLayout.X_AXIS); box.add(Box.createHorizontalStrut(10)); box.add(title); box.add(Box.createHorizontalGlue()); toolbar=yearsQ.createComboBox(); toolbar.addActionListener(new MyAction()); panel= new JPanel(new BorderLayout()); panel.add(this, BorderLayout.CENTER); panel.add(box, BorderLayout.SOUTH); panel.add(toolbar,BorderLayout.NORTH); JFrame frame = new JFrame("明星MV和歌曲点播"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(panel); frame.pack(); frame.setVisible(true); } public static void main(String[] args) { sql="select Stars.name as name,disk.diskid as diskid,disk.diskname as diskname,disk.diskimage as diskimage,"+ "disk.type as type,disk.postdate as postdate,disk.info as info from Stars,disk " +"where Stars.id=disk.id"; Table table=GetData(sql); if(table.getRowCount()>0) { Stars tview= new Stars(table);//生成显示类 } } //高寒渲染顺序值 public class DataMountainSorter extends ItemSorter { public int score(VisualItem item) { return (int)(10000*item.getY()); } } // end of inner class DataMountainComparator public class DataMouseControl extends ControlAdapter { private boolean IsPlay=false; private String CurrentMusic=null; public void itemEntered(VisualItem item, MouseEvent e) { Display d = (Display)e.getSource(); String msg="<html>专辑名称:"+item.getString("diskname")+"<br>艺术家:"+item.getString("name") +"<br>类型:"+item.getString("type") +"<br>发行时间:"+item.getString("postdate")+"<br>唱片信息:"+item.getString("info")+"</html>"; d.setToolTipText(msg); } public void itemExited(VisualItem item, MouseEvent e) { Display d = (Display)e.getSource(); d.setToolTipText(null); } public void itemClicked(VisualItem item, MouseEvent e) { if (!SwingUtilities.isLeftMouseButton(e)) return; if ( e.getClickCount()==2) { if(item.getString("type").equals("MP3")) { String s=System.getProperty("user.dir")+"\\src\\"+item.getString("diskname")+".mp3"; if(IsPlay==false) { PlayMusic.PlayMp3(s); CurrentMusic=s; IsPlay=true; String playinfo=item.getString("diskname")+" :正在播放中..."; title.setText(playinfo); } else { PlayMusic.StopPlayer(); IsPlay=false; title.setText(""); } //System.out.println(CurrentMusic); } else { String id = item.getString("diskname"); BrowserLauncher.showDocument("file://"+System.getProperty("user.dir")+"\\src\\"+id+".flv"); } } } public void itemPressed(VisualItem item, MouseEvent e) { if (!SwingUtilities.isLeftMouseButton(e)) return; // set the focus to the current node Visualization vis = item.getVisualization(); vis.getFocusGroup(Visualization.FOCUS_ITEMS).setTuple(item); Display d = (Display)e.getComponent(); vis.run("forces"); } public void itemReleased(VisualItem item, MouseEvent e) { if (!SwingUtilities.isLeftMouseButton(e)) return; // clear the focus Visualization vis = item.getVisualization(); vis.getFocusGroup(Visualization.FOCUS_ITEMS).clear(); vis.cancel("forces"); } } private static final String ANCHORITEM = "_anchorItem"; private static final Schema ANCHORITEM_SCHEMA = new Schema(); static { ANCHORITEM_SCHEMA.addColumn(ANCHORITEM, ForceItem.class); } public class DataMountainForceLayout extends ForceDirectedLayout { public DataMountainForceLayout(boolean enforceBounds) { //第二个参数指出是否所有节点都显示在现在布局之内 //是否是动画模式 super("data",enforceBounds,false); ForceSimulator fsim = new ForceSimulator(); //NBodyForce 添加重力效果 fsim.addForce(new NBodyForce(-5f, 25f, NBodyForce.DEFAULT_THETA)); //添加弹力效果 fsim.addForce(new SpringForce(1e-5f,0f)); //添加拖拽力效果 fsim.addForce(new DragForce()); setForceSimulator(fsim); m_nodeGroup = "data"; m_edgeGroup = null; } //得到给定结点混合力作用值 protected float getMassValue(VisualItem n) { return n.isHover() ? 5f : 1f; } //重置力模拟状态对所有节点处理这个布局。 public void reset() { Iterator iter = m_vis.visibleItems(m_nodeGroup); while ( iter.hasNext() ) { VisualItem item = (VisualItem)iter.next(); ForceItem aitem = (ForceItem)item.get(ANCHORITEM); if ( aitem != null ) { aitem.location[0] = (float)item.getEndX(); aitem.location[1] = (float)item.getEndY(); } } super.reset(); } protected void initSimulator(ForceSimulator fsim) { // make sure we have force items to work with TupleSet t = (TupleSet)m_vis.getGroup(m_group); t.addColumns(ANCHORITEM_SCHEMA); t.addColumns(FORCEITEM_SCHEMA); Iterator iter = m_vis.visibleItems(m_nodeGroup); while ( iter.hasNext() ) { VisualItem item = (VisualItem)iter.next(); // get force item ForceItem fitem = (ForceItem)item.get(FORCEITEM); if ( fitem == null ) { fitem = new ForceItem(); item.set(FORCEITEM, fitem); } fitem.location[0] = (float)item.getEndX(); fitem.location[1] = (float)item.getEndY(); fitem.mass = getMassValue(item); // get spring anchor ForceItem aitem = (ForceItem)item.get(ANCHORITEM); if ( aitem == null ) { aitem = new ForceItem(); item.set(ANCHORITEM, aitem); aitem.location[0] = fitem.location[0]; aitem.location[1] = fitem.location[1]; } fsim.addItem(fitem); fsim.addSpring(fitem, aitem, 0); } } } // end of inner class DataMountainForceLayout public class MyAction implements ActionListener { public void actionPerformed(ActionEvent e) { String sql1=null; String selitem=toolbar.getSelectedItem().toString(); if(selitem.equals("All")) { sql1=sql; } else sql1=sql+" and Stars.name=\'"+selitem+"\'"; Table t=Stars.GetData(sql1); UpdateView(t); } } public void UpdateView(Table t) { m_vis.removeGroup(data); m_vis.add(data, t); m_vis.run("init"); } }
数据库设计:
唱片表:
明星表:
转载本文请标明出处。