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項目了,這個只是前台,那么大家也可以寫一個后台進行管理和維護前台,通過數據庫就可以

把前台和后台連在一起。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM