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         /// 第三层listView
114         /// </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             finally
35             {
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恋爱新手.mp3
10                 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             else
104             { 
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             else
143             {
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 Song
11     {        
12         /// <summary>
13         /// 歌曲名称
14         /// </summary>
15         public string SongName
16         {
17             get { return songName; }
18             set { songName = value; }
19         }
20 
21         /// <summary>
22         /// 歌曲存放路径
23         /// </summary>
24         public string SongURL
25         {
26             get { return songURL; }
27             set { songURL = value; }
28         }
29 
30         /// <summary>
31         /// 歌曲播放状态
32         /// </summary>
33         internal SongPlayState PlayState
34         {
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 SongList
10     {
11          //歌曲名称
12         private string SongName;
13          //歌曲路径
14         private string SongUl;
15          //歌曲状态
16         private string SongState;
17 
18         public string SongState1
19         {
20             get { return SongState; }
21             set { SongState = value; }
22         }
23 
24         public string SongUl1
25         {
26             get { return SongUl; }
27             set { SongUl = value; }
28         }
29 
30         public string SongName1
31         {
32             get { return SongName; }
33             set { SongName = value; }
34         }
35 
36          //把当前的播放状态设置为未播放状态
37        private  PalySongState playSong = PalySongState.unplayed;
38 
39         public  PalySongState PlaySong
40         {
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项目了,这个只是前台,那么大家也可以写一个后台进行管理和维护前台,通过数据库就可以

把前台和后台连在一起。

原文地址:https://www.cnblogs.com/wcf6676/p/4690722.html