
·您现在的位置: 云翼网络 >> 文章中心 >> 网站建设 >> 网站建设开发 >> ASP.NET网站开发 >> MyKTV项目,走起!
MyKTV项目,走起!
第一部分:这个项目对于新手来说有一点难度,但是当你理清类之间的关系和怎样去实现功能后就会感觉轻松很多。
话不多说,先上类图:

接着是数据库表间关系:

本项目要实现以下功能:
一共五大块,那么明星点歌下还有一个播放的功能。
在主页面有一个正在播放和下一首的提示功能。
这是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项目了,这个只是前台,那么大家也可以写一个后台进行管理和维护前台,通过数据库就可以
把前台和后台连在一起。