你的位置:首页 > ASP.net教程

[ASP.net教程]MyKTV项目,走起!


MyKTV项目,走起!

第一部分:这个项目对于新手来说有一点难度,但是当你理清类之间的关系和怎样去实现功能后就会感觉轻松很多。

话不多说,先上类图:

接着是数据库表间关系:

 

本项目要实现以下功能:

  1. 明星点歌
  2. 拼音点歌
  3. 类型选择
  4. 金榜排行
  5. 字数点歌

一共五大块,那么明星点歌下还有一个播放的功能。

在主页面有一个正在播放和下一首的提示功能。

这是ktv主页面:

在下边还有重唱,切歌,已点,服务和退出功能

相信大家都去过KTV,所以这些功能就不说了,比我都清楚!

这里我把播放控件放在了主页面,位置随意,放在哪都行,也可以单独开一个窗体进行播放。

点击明星点歌进入到明星点歌页面:

 

组合,女歌手和男歌手都放在listView中,这里要注意的是在这一个窗体中一共有三个listView,先在窗体中隐藏后两个,

那么点击第一个进入到第二个时要把第一个listView隐藏。

隐藏listView只需把它的Visible属性设置成false就ok了:

1       lvCountry.Visible = false;2       lvSinger.Visible = false;

第二个listView就是供用户一个更精确的选择歌曲或歌手了:

第三个listView就是显示歌手对应的图片:

这个图片要从数据库中取,不能写死,还有很多功能,像金榜排行,都不能写死。

再次点击就进入播放列表:

刷新歌曲列表代码:

 1     /// <summary> 2     /// 刷新歌曲列表 3     /// </summary> 4     private void RefreshSongList() 5     { 6       lvSongList.Items.Clear(); // 清空原列表 7       int i = 0; 8       while (PlayList.SongList[i] != null) 9       {10         ListViewItem item = new ListViewItem();11         item.Text = PlayList.SongList[i].SongName;        12         item.Tag = i;13         string playState = PlayList.SongList[i].PlayState== SongPlayState.unplayed?"未播放":"已播放";14         item.SubItems.Add(playState);15         lvSongList.Items.Add(item);16         i++;17       }18     }

 

明星点歌代码:

 1      string singertype = "组合"; 2     int singertypid = 0; 3  4      /// <summary> 5     /// 第一层listView 6     /// </summary> 7     public void LoadSingerArea()  8     { 9       if (lvType.SelectedItems[0]!=null) 10       { 11         lvType.Visible = false; 12         lvCountry.Visible = true; 13         lvCountry.Location = lvType.Location; 14         lvCountry.Dock = DockStyle.Fill; 15         this.singertype = Convert.ToString(lvType.SelectedItems[0].Text); 16       }           17       string sql = "select singertype_id,singertype_name from singer_type"; 18       SqlCommand cmd = new SqlCommand(sql,db.Connection ); 19       try 20       { 21         db.OpenConnection(); 22         SqlDataReader dr = cmd.ExecuteReader(); 23         lvCountry.Items.Clear(); 24         if (dr.HasRows) 25         { 26           int index = 0; 27           while (dr.Read()) 28           { 29             ListViewItem lvitem = new ListViewItem(); 30             int typeid = Convert.ToInt32(dr["singertype_id"]); 31             string typename = Convert.ToString(dr["singertype_name"]); 32             lvitem.Text = typename; 33             lvitem.Tag = typeid; 34             lvitem.ImageIndex = index; 35             lvCountry.Items.Add(lvitem); 36             index++; 37           } 38         } 39         dr.Close(); 40       } 41       catch (Exception ex) 42       { 43  44         MessageBox.Show(ex.Message); 45       } 46       finally 47       { 48         db.CloseConnection(); 49       } 50     } 51     /// <summary> 52     /// 第二层listView 53     /// </summary> 54     public void LoadSingerName()  55     { 56       if (lvCountry.SelectedItems[0]!=null) 57       { 58         //隐藏歌手地区,显示歌手的姓名 59         lvCountry.Visible = false; 60         lvSinger.Visible = true; 61         lvSinger.Location = lvCountry.Location;                 62         singertypid = Convert.ToInt32(lvCountry.SelectedItems[0].Tag); 63         StringBuilder sql = new StringBuilder(); 64         string result = singertype; 65         if (result!="组合") 66         { 67           result = singertype == "女歌手" ? "女" : "男"; 68         } 69         sql.AppendFormat("select singe_id,singer_name,singer_photo_url from Singer_info where singertype_id={0}and singer_gemder='{1}'",singertypid,result); 70         SqlCommand cmd = new SqlCommand(sql.ToString(), db.Connection); 71         try 72         {           73           db.OpenConnection(); 74           SqlDataReader dr = cmd.ExecuteReader(); 75           int imageIndex = 0; //代表歌手头像的索引 76           imageList1.Images.Clear(); 77           lvSinger.Items.Clear(); 78           if (dr.HasRows) 79           { 80             while (dr.Read()) 81             { 82               string photoURL = KTVUtil.singerPhotoPath + "\\" + Convert.ToString(dr["singer_photo_url"]); 83               imageList1.Images.Add(Image.FromFile(photoURL)); 84               ListViewItem item = new ListViewItem(); 85               item.Text = Convert.ToString(dr["singer_name"]); 86               item.Tag = Convert.ToString(dr["singer_id"]); 87               item.ImageIndex = imageIndex; 88               lvSinger.Items.Add(item); 89               imageIndex++; 90             } 91           } 92           dr.Close(); 93         } 94         catch (Exception ex) 95         { 96           MessageBox.Show(ex.Message); 97         } 98         finally  99         {100           db.CloseConnection();101         }102       }103     }104 105     private void tsplMenu_Click(object sender, EventArgs e)106     {107       MainForm mf = new MainForm();108       mf.Show();109       this.Close();110 111     }112     /// <summary>113     /// 第三层listView114     /// </summary>115     public void SongList()116     {117       StringBuilder sb = new StringBuilder();118       sb.AppendFormat("select song_id,song_name, singer_name='{0}',song_url from SongInfo,Singer_Info where singer_id={1}",119         lvSinger.SelectedItems[0].Text, Convert.ToInt32(lvSinger.SelectedItems[0].Tag));120 121       SongListForm songList = new SongListForm();122       songList.Sql = sb.ToString();123       songList.Show();124       this.Close();125     }

之后一定要在listView的Click事件中调用方法:

 1      private void lvType_Click(object sender, EventArgs e) 2     { 3       LoadSingerArea(); 4     } 5  6     private void lvSinger_Click(object sender, EventArgs e) 7     { 8       SongList(); 9     }10 11     private void lvCountry_Click(object sender, EventArgs e)12     {13       LoadSingerName();14     }

播放过程:

当选中某首歌曲后,点击一下,那么就会将各个列的值拼接成一个Song对象,

1 Song song=new Song();2 song.songName="值";3 song.songUrl="地址";

歌曲列表中数据来源于数据库!所以我们要将喜欢的歌曲添加到数据库中!

当我们点击已点的时候就会循环遍历数组,然后每遍历一项,就会创建一个 ListViewItem对象。

刚才忘了说了,每个页面下面的菜单我用的是ToolStrip控件。

接下来是拼音点歌

拼音点歌相对来说就简单多了,就是一个模糊查询,页面如下:

拼音点歌部分代码:

 1     // 查询歌曲显示在窗体中 2     private void btnSearch_Click(object sender, EventArgs e) 3     {             4       DBHelper dbHelper = new DBHelper(); 5       DataSet dataSet = new DataSet(); 6       StringBuilder sb = new StringBuilder(); 7       sb.Append("select song_id,song_name,singer_name,song_url from song_info inner join singer_info on singer_info.singer_id=song_info.singer_id "); 8       sb.AppendFormat("where song_name like '%{0}%' or song_ab like '{0}'",this.txtSongName.Text); 9 10       Console.WriteLine(sb.ToString());11 12       SqlDataAdapter adapter = new SqlDataAdapter(sb.ToString(), dbHelper.Connection);13 14       // 清空当前列表15       if (dataSet.Tables["songList"] != null)16       {17         dataSet.Tables["songList"].Clear();18       }19 20       adapter.Fill(dataSet, "songList");21       this.dgvSong.DataSource = dataSet.Tables["songList"];      22     }

类型点歌:

这个和酷狗里的如下页面功能类似:

 

点击某一个项进入到相应的歌曲页面,部分代码如下:

 1 // 窗体加载时,显示歌曲类别 2     private void OrderBySongTypeForm_Load(object sender, EventArgs e) 3     { 4       // 读取歌曲类别 5       DBHelper dbHelper = new DBHelper(); 6       string sql = "select * from song_type"; 7       try 8       { 9         // 查询数据库10         SqlCommand command = new SqlCommand(sql, dbHelper.Connection);11         dbHelper.OpenConnection();12         SqlDataReader reader = command.ExecuteReader();13 14         // 循环将类别读取出来添加到ListView中15         this.lvSongType.Items.Clear();16         int i = 0;17         while (reader.Read())18         {19           ListViewItem item = new ListViewItem();20           item.Text = Convert.ToString(reader["songtype_name"]);21           item.Tag = Convert.ToInt32(reader["songtype_id"]);22           item.ImageIndex = i;23           this.lvSongType.Items.Add(item);24           i++;25         }26         reader.Close();27       }28       catch (Exception ex)29       {30         Console.WriteLine(ex.Message);31         MessageBox.Show("系统错误,请联系服务人员!");32 33       }34       finally35       {36         dbHelper.CloseConnection();37       }38     }

金榜排行和字数点歌大家可以尝试着写一下,都不难!字数点歌这里要注意一下:

上边的那12个Label不是拖12个Label控件,而是利用二重数组进行控制Label的:

 1         for (int i = 1; i <= 5; i++)//行数 2        { 3         for (int j = 1; j <= 5; j++) 4         { 5           Label label = new Label(); 6           label.Text = i+"-"+j; 7           //自身大小(重点) 8           label.Size = new Size(80, 50); 9           //背景颜色10           label.BackColor = Color.Yellow;11           //相对于窗体0,0点的位置12           label.Location = new Point(20+100*j, 20+80*i);13           //文本居中14           label.TextAlign = ContentAlignment.MiddleCenter;15           //字体大小16           label.Font=new Font("Bradley Hand ITC",20);17           //触发Click事件18           label.Click += label_Click;19          20           //让Label对象归属于当前窗体21           this.Controls.Add(label);22         }23       }24 25     }26 27     void label_MouseMove(object sender, MouseEventArgs e)28     {29       this.Text = e.X + "," + e.Y;30     }31 32     void label_Click(object sender, EventArgs e)33     {34      35       Label label = (Label)sender;36       MessageBox.Show(label.Text);37       38 39     }40 41     private void Form1_MouseMove(object sender, MouseEventArgs e)42     {43       this.Text = e.X + "," + e.Y;44     }

要记住:每一个控件都是一个类。

 

第二部分:

部分关键代码如下:

1.重唱:

1 // 重新播放当前歌曲2     private void tsbtnAgain_Click(object sender, EventArgs e)3     {4       PlayList.PlayAgain();5     }

就是调用PlayList中的PlayAgain()方法。PlayList类我会在下面给出。

2.切歌:

 1     // 切歌 2     private void tsbtnCut_Click(object sender, EventArgs e) 3     { 4       if (MessageBox.Show("确定要切歌吗?", "操作提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK) 5       { 6         int songId = -1; // 切歌的编号 7         if (this.lvSongList.SelectedItems.Count > 0) 8         { 9           songId = Convert.ToInt32(this.lvSongList.SelectedItems[0].Tag);10         }11         PlayList.CutSong(songId);12         this.RefreshSongList();13       }14     }

3.播放:

 1     private Song song;//当前播放的歌曲 2     //播放歌曲 3     private void PlaySong() 4     { 5       this.song = PlayList.GetPlaySong();//获取当前播放的歌曲 6       if (song != null) 7       { 8         this.song.SetSongPlayed();//已播放 9         //D:\song\恋爱新手.mp310         Player1.URL = KTVUtil.songPath + "\\" + this.song.SongURL;//得到当前播放歌曲的路径11         txtNext.Text = this.song.SongName;12       }13     }

 

4.PlayList类:

 1 /// <summary> 2   /// 播放列表管理 3   /// </summary> 4   class PlayList 5   { 6     private static Song[] songList = new Song[50]; // 歌曲播放列表数组 7     private static int songIndex = 0; // 当前播放的歌曲在数组中的索引    8  9     /// <summary> 10     /// 播放列表数组 11     /// </summary> 12     public static Song[] SongList 13     { 14      get { return PlayList.songList; }      15     } 16  17     /// <summary> 18     /// 当前播放歌曲的索引 19     /// </summary> 20     public static int SongIndex 21     { 22       get { return PlayList.songIndex; } 23     } 24  25     /// <summary> 26     /// 当前播放的歌曲名称 27     /// </summary> 28     /// <returns>歌曲名称</returns> 29     public static string PlayingSongName() 30     {  31       string songName = ""; // 歌曲名称 32       if (SongList[SongIndex] != null) 33       { 34         songName = SongList[SongIndex].SongName; 35       } 36  37       return songName; 38     } 39  40     /// <summary> 41     /// 获取当前播放的歌曲 42     /// </summary> 43     /// <returns>当前要播放的歌曲</returns> 44     public static Song GetPlayingSong() 45     { 46       if (SongList[songIndex] != null) 47       { 48         return SongList[songIndex]; 49       } 50       else 51       { 52         return null; 53       } 54     } 55  56     /// <summary> 57     /// 下一首要播放的歌曲名称 58     /// </summary> 59     /// <returns>歌曲名称</returns> 60     public static string NextSongName() 61     { 62       string songName = ""; // 歌曲名称 63       if (SongList[SongIndex+1] != null) 64       { 65         songName = SongList[SongIndex+1].SongName; 66       } 67  68       return songName; 69     } 70      71     /// <summary> 72     /// 点播一首歌曲 73     /// </summary> 74     /// <param name="song">新点播的歌曲</param> 75     public static bool AddSong(Song song) 76     { 77       bool success = false; 78       for (int i = 0; i < SongList.Length; i++) 79       { 80         if (SongList[i] == null) 81         { 82           SongList[i] = song; 83           Console.WriteLine(song.SongName); 84           success = true; 85           break; 86         } 87       } 88  89       return success; 90     } 91  92     /// <summary> 93     /// 切歌 94     /// </summary> 95     /// <param name="index">要切歌曲的编号,如果是切当前播放的歌曲传入-1</param> 96     public static void CutSong(int index) 97     { 98       int i; // 循环变量,代表切歌的位置 99       if (index == -1)100       {101         i = SongIndex;        102       }103       else104       { 105         i = index; // 从切歌的位置开始,将歌曲逐个向前移一个位置106       }107 108       SongList[i].SetSongCut();109       while (SongList[i] != null)110       {111         SongList[i] = SongList[i + 1];  112         i++;113 114         // 如果到达数组最后一个元素,就将最后一个元素指向空115         if (i == SongList.Length)116         {117           SongList[i] = null;118         }119       }120     }121 122     /// <summary>123     /// 重放当前歌曲124     /// </summary>125     public static void PlayAgain()126     {127       if (SongList[songIndex] != null)128       {129         SongList[songIndex].SetPlayAgain();130       }131     }132 133     /// <summary>134     /// 播放下一首135     /// </summary>136     public static void MoveOn()137     {138       if (SongList[songIndex] != null && SongList[songIndex].PlayState == SongPlayState.again)139       {140         SongList[songIndex].SetSongPlayed();141       }142       else143       {144         songIndex++;145       }      146     }    147   }

 

5.Song类:

 1   enum SongPlayState 2   {  3     unplayed,played,again,cut  4   } 5    6    7   /// <summary> 8   /// 歌曲类 9   /// </summary>10   class Song11   {    12     /// <summary>13     /// 歌曲名称14     /// </summary>15     public string SongName16     {17       get { return songName; }18       set { songName = value; }19     }20 21     /// <summary>22     /// 歌曲存放路径23     /// </summary>24     public string SongURL25     {26       get { return songURL; }27       set { songURL = value; }28     }29 30     /// <summary>31     /// 歌曲播放状态32     /// </summary>33     internal SongPlayState PlayState34     {35       get { return playState; }36       set { playState = value; }37     }38     39     private string songName;40     private string songURL;41     private SongPlayState playState = SongPlayState.unplayed; // 歌曲播放状态42 43     44     /// <summary>45     /// 将歌曲状态改为已播放46     /// </summary>47     public void SetSongPlayed()48     {49       this.playState = SongPlayState.played;50     }51 52     /// <summary>53     /// 将歌曲状态改为再拨放一次54     /// </summary>55     public void SetPlayAgain()56     {57       this.playState = SongPlayState.again;58     }59 60     /// <summary>61     /// 将歌曲状态改为切歌62     /// </summary>63     public void SetSongCut()64     {65       this.playState = SongPlayState.cut;66     }67   }

6.KTVUtil类:

这里主要存的就是路径

1     public static string singerPhotoPath = ""; // 歌手照片路径2     public static string songPath = "";     // 歌曲路径

7.SongList类:

 1 public enum PalySongState  2   { 3    //未播放 , 播放, 重播,切歌 4     unplayed,played,again,cut 5   } 6   /// <summary> 7   /// 歌曲播放类 8   /// </summary> 9   public class SongList10   {11     //歌曲名称12     private string SongName;13     //歌曲路径14     private string SongUl;15     //歌曲状态16     private string SongState;17 18     public string SongState119     {20       get { return SongState; }21       set { SongState = value; }22     }23 24     public string SongUl125     {26       get { return SongUl; }27       set { SongUl = value; }28     }29 30     public string SongName131     {32       get { return SongName; }33       set { SongName = value; }34     }35 36     //把当前的播放状态设置为未播放状态37    private PalySongState playSong = PalySongState.unplayed;38 39     public PalySongState PlaySong40     {41       get { return playSong; }42       set { playSong = value; }43     }44     /// <summary>45     /// 将未播放状态改为播放状态46     /// </summary>47     public void PalyState() 48     {49       this.PlaySong = PalySongState.played;50     }51     /// <summary>52     /// 将歌曲重新播放53     /// </summary>54     public void AgainState() 55     {56       this.PlaySong = PalySongState.again;57     }58     /// <summary>59     /// 切歌状态60     /// </summary>61     public void CutState() 62     {63       this.PlaySong = PalySongState.cut;64     }65   }

那么以上就是本次的KTV项目了,这个只是前台,那么大家也可以写一个后台进行管理和维护前台,通过数据库就可以

把前台和后台连在一起。