MyKTV项目,走起!
MyKTV项目,走起!
第一部分:这个项目对于新手来说有一点难度,但是当你理清类之间的关系和怎样去实现功能后就会感觉轻松很多。
话不多说,先上类图:
接着是数据库表间关系:
本项目要实现以下功能:
- 明星点歌
- 拼音点歌
- 类型选择
- 金榜排行
- 字数点歌
一共五大块,那么明星点歌下还有一个播放的功能。
在主页面有一个正在播放和下一首的提示功能。
这是ktv主页面:
在下边还有重唱,切歌,已点,服务和退出功能
相信大家都去过KTV,所以这些功能就不说了,比我都清楚!
这里我把播放控件放在了主页面,位置随意,放在哪都行,也可以单独开一个窗体进行播放。
点击明星点歌进入到明星点歌页面:
组合,女歌手和男歌手都放在listView中,这里要注意的是在这一个窗体中一共有三个listView,先在窗体中隐藏后两个,
那么点击第一个进入到第二个时要把第一个listView隐藏。
隐藏listView只需把它的Visible属性设置成false就ok了:
lvCountry.Visible = false;
lvSinger.Visible = false;
第二个listView就是供用户一个更精确的选择歌曲或歌手了:
第三个listView就是显示歌手对应的图片:
这个图片要从数据库中取,不能写死,还有很多功能,像金榜排行,都不能写死。
再次点击就进入播放列表:
刷新歌曲列表代码:
/// <summary>
/// 刷新歌曲列表
/// </summary>
private void RefreshSongList()
{
lvSongList.Items.Clear(); // 清空原列表
int i = ;
while (PlayList.SongList[i] != null)
{
ListViewItem item = new ListViewItem();
item.Text = PlayList.SongList[i].SongName;
item.Tag = i;
string playState = PlayList.SongList[i].PlayState== SongPlayState.unplayed?"未播放":"已播放";
item.SubItems.Add(playState);
lvSongList.Items.Add(item);
i++;
}
}
明星点歌代码:
string singertype = "组合";
int singertypid = ; /// <summary>
/// 第一层listView
/// </summary>
public void LoadSingerArea()
{
if (lvType.SelectedItems[]!=null)
{
lvType.Visible = false;
lvCountry.Visible = true;
lvCountry.Location = lvType.Location;
lvCountry.Dock = DockStyle.Fill;
this.singertype = Convert.ToString(lvType.SelectedItems[].Text);
}
string sql = "select singertype_id,singertype_name from singer_type";
SqlCommand cmd = new SqlCommand(sql,db.Connection );
try
{
db.OpenConnection();
SqlDataReader dr = cmd.ExecuteReader();
lvCountry.Items.Clear();
if (dr.HasRows)
{
int index = ;
while (dr.Read())
{
ListViewItem lvitem = new ListViewItem();
int typeid = Convert.ToInt32(dr["singertype_id"]);
string typename = Convert.ToString(dr["singertype_name"]);
lvitem.Text = typename;
lvitem.Tag = typeid;
lvitem.ImageIndex = index;
lvCountry.Items.Add(lvitem);
index++;
}
}
dr.Close();
}
catch (Exception ex)
{ MessageBox.Show(ex.Message);
}
finally
{
db.CloseConnection();
}
}
/// <summary>
/// 第二层listView
/// </summary>
public void LoadSingerName()
{
if (lvCountry.SelectedItems[]!=null)
{
//隐藏歌手地区,显示歌手的姓名
lvCountry.Visible = false;
lvSinger.Visible = true;
lvSinger.Location = lvCountry.Location;
singertypid = Convert.ToInt32(lvCountry.SelectedItems[].Tag);
StringBuilder sql = new StringBuilder();
string result = singertype;
if (result!="组合")
{
result = singertype == "女歌手" ? "女" : "男";
}
sql.AppendFormat("select singe_id,singer_name,singer_photo_url from Singer_info where singertype_id={0}and singer_gemder='{1}'",singertypid,result);
SqlCommand cmd = new SqlCommand(sql.ToString(), db.Connection);
try
{
db.OpenConnection();
SqlDataReader dr = cmd.ExecuteReader();
int imageIndex = ; //代表歌手头像的索引
imageList1.Images.Clear();
lvSinger.Items.Clear();
if (dr.HasRows)
{
while (dr.Read())
{
string photoURL = KTVUtil.singerPhotoPath + "\\" + Convert.ToString(dr["singer_photo_url"]);
imageList1.Images.Add(Image.FromFile(photoURL));
ListViewItem item = new ListViewItem();
item.Text = Convert.ToString(dr["singer_name"]);
item.Tag = Convert.ToString(dr["singer_id"]);
item.ImageIndex = imageIndex;
lvSinger.Items.Add(item);
imageIndex++;
}
}
dr.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
db.CloseConnection();
}
}
} private void tsplMenu_Click(object sender, EventArgs e)
{
MainForm mf = new MainForm();
mf.Show();
this.Close(); }
/// <summary>
/// 第三层listView
/// </summary>
public void SongList()
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("select song_id,song_name, singer_name='{0}',song_url from SongInfo,Singer_Info where singer_id={1}",
lvSinger.SelectedItems[].Text, Convert.ToInt32(lvSinger.SelectedItems[].Tag)); SongListForm songList = new SongListForm();
songList.Sql = sb.ToString();
songList.Show();
this.Close();
}
之后一定要在listView的Click事件中调用方法:
private void lvType_Click(object sender, EventArgs e)
{
LoadSingerArea();
} private void lvSinger_Click(object sender, EventArgs e)
{
SongList();
} private void lvCountry_Click(object sender, EventArgs e)
{
LoadSingerName();
}
播放过程:
当选中某首歌曲后,点击一下,那么就会将各个列的值拼接成一个Song对象,
Song song=new Song();
song.songName="值";
song.songUrl="地址";
歌曲列表中数据来源于数据库!所以我们要将喜欢的歌曲添加到数据库中!
当我们点击已点的时候就会循环遍历数组,然后每遍历一项,就会创建一个 ListViewItem对象。
刚才忘了说了,每个页面下面的菜单我用的是ToolStrip控件。
接下来是拼音点歌。
拼音点歌相对来说就简单多了,就是一个模糊查询,页面如下:
拼音点歌部分代码:
// 查询歌曲显示在窗体中
private void btnSearch_Click(object sender, EventArgs e)
{
DBHelper dbHelper = new DBHelper();
DataSet dataSet = new DataSet();
StringBuilder sb = new StringBuilder();
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 ");
sb.AppendFormat("where song_name like '%{0}%' or song_ab like '{0}'",this.txtSongName.Text); Console.WriteLine(sb.ToString()); SqlDataAdapter adapter = new SqlDataAdapter(sb.ToString(), dbHelper.Connection); // 清空当前列表
if (dataSet.Tables["songList"] != null)
{
dataSet.Tables["songList"].Clear();
} adapter.Fill(dataSet, "songList");
this.dgvSong.DataSource = dataSet.Tables["songList"];
}
类型点歌:
这个和酷狗里的如下页面功能类似:
点击某一个项进入到相应的歌曲页面,部分代码如下:
// 窗体加载时,显示歌曲类别
private void OrderBySongTypeForm_Load(object sender, EventArgs e)
{
// 读取歌曲类别
DBHelper dbHelper = new DBHelper();
string sql = "select * from song_type";
try
{
// 查询数据库
SqlCommand command = new SqlCommand(sql, dbHelper.Connection);
dbHelper.OpenConnection();
SqlDataReader reader = command.ExecuteReader(); // 循环将类别读取出来添加到ListView中
this.lvSongType.Items.Clear();
int i = ;
while (reader.Read())
{
ListViewItem item = new ListViewItem();
item.Text = Convert.ToString(reader["songtype_name"]);
item.Tag = Convert.ToInt32(reader["songtype_id"]);
item.ImageIndex = i;
this.lvSongType.Items.Add(item);
i++;
}
reader.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
MessageBox.Show("系统错误,请联系服务人员!"); }
finally
{
dbHelper.CloseConnection();
}
}
金榜排行和字数点歌大家可以尝试着写一下,都不难!字数点歌这里要注意一下:
上边的那12个Label不是拖12个Label控件,而是利用二重数组进行控制Label的:
for (int i = ; i <= ; i++)//行数
{
for (int j = ; j <= ; j++)
{
Label label = new Label();
label.Text = i+"-"+j;
//自身大小(重点)
label.Size = new Size(, );
//背景颜色
label.BackColor = Color.Yellow;
//相对于窗体0,0点的位置
label.Location = new Point(+*j, +*i);
//文本居中
label.TextAlign = ContentAlignment.MiddleCenter;
//字体大小
label.Font=new Font("Bradley Hand ITC",20); //触发Click事件
label.Click += label_Click;
//让Label对象归属于当前窗体
this.Controls.Add(label);
}
} } void label_MouseMove(object sender, MouseEventArgs e)
{
this.Text = e.X + "," + e.Y;
} void label_Click(object sender, EventArgs e)
{
Label label = (Label)sender; MessageBox.Show(label.Text); } private void Form1_MouseMove(object sender, MouseEventArgs e)
{
this.Text = e.X + "," + e.Y;
}
要记住:每一个控件都是一个类。
第二部分:
部分关键代码如下:
1.重唱:
// 重新播放当前歌曲
private void tsbtnAgain_Click(object sender, EventArgs e)
{
PlayList.PlayAgain();
}
就是调用PlayList中的PlayAgain()方法。PlayList类我会在下面给出。
2.切歌:
// 切歌
private void tsbtnCut_Click(object sender, EventArgs e)
{
if (MessageBox.Show("确定要切歌吗?", "操作提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK)
{
int songId = -; // 切歌的编号
if (this.lvSongList.SelectedItems.Count > )
{
songId = Convert.ToInt32(this.lvSongList.SelectedItems[].Tag);
}
PlayList.CutSong(songId);
this.RefreshSongList();
}
}
3.播放:
private Song song;//当前播放的歌曲
//播放歌曲
private void PlaySong()
{
this.song = PlayList.GetPlaySong();//获取当前播放的歌曲
if (song != null)
{
this.song.SetSongPlayed();//已播放
//D:\song\恋爱新手.mp3
Player1.URL = KTVUtil.songPath + "\\" + this.song.SongURL;//得到当前播放歌曲的路径
txtNext.Text = this.song.SongName;
}
}
4.PlayList类:
/// <summary>
/// 播放列表管理
/// </summary>
class PlayList
{
private static Song[] songList = new Song[]; // 歌曲播放列表数组
private static int songIndex = ; // 当前播放的歌曲在数组中的索引 /// <summary>
/// 播放列表数组
/// </summary>
public static Song[] SongList
{
get { return PlayList.songList; }
} /// <summary>
/// 当前播放歌曲的索引
/// </summary>
public static int SongIndex
{
get { return PlayList.songIndex; }
} /// <summary>
/// 当前播放的歌曲名称
/// </summary>
/// <returns>歌曲名称</returns>
public static string PlayingSongName()
{
string songName = ""; // 歌曲名称
if (SongList[SongIndex] != null)
{
songName = SongList[SongIndex].SongName;
} return songName;
} /// <summary>
/// 获取当前播放的歌曲
/// </summary>
/// <returns>当前要播放的歌曲</returns>
public static Song GetPlayingSong()
{
if (SongList[songIndex] != null)
{
return SongList[songIndex];
}
else
{
return null;
}
} /// <summary>
/// 下一首要播放的歌曲名称
/// </summary>
/// <returns>歌曲名称</returns>
public static string NextSongName()
{
string songName = ""; // 歌曲名称
if (SongList[SongIndex+] != null)
{
songName = SongList[SongIndex+].SongName;
} return songName;
} /// <summary>
/// 点播一首歌曲
/// </summary>
/// <param name="song">新点播的歌曲</param>
public static bool AddSong(Song song)
{
bool success = false;
for (int i = ; i < SongList.Length; i++)
{
if (SongList[i] == null)
{
SongList[i] = song;
Console.WriteLine(song.SongName);
success = true;
break;
}
} return success;
} /// <summary>
/// 切歌
/// </summary>
/// <param name="index">要切歌曲的编号,如果是切当前播放的歌曲传入-1</param>
public static void CutSong(int index)
{
int i; // 循环变量,代表切歌的位置
if (index == -)
{
i = SongIndex;
}
else
{
i = index; // 从切歌的位置开始,将歌曲逐个向前移一个位置
} SongList[i].SetSongCut();
while (SongList[i] != null)
{
SongList[i] = SongList[i + ];
i++; // 如果到达数组最后一个元素,就将最后一个元素指向空
if (i == SongList.Length)
{
SongList[i] = null;
}
}
} /// <summary>
/// 重放当前歌曲
/// </summary>
public static void PlayAgain()
{
if (SongList[songIndex] != null)
{
SongList[songIndex].SetPlayAgain();
}
} /// <summary>
/// 播放下一首
/// </summary>
public static void MoveOn()
{
if (SongList[songIndex] != null && SongList[songIndex].PlayState == SongPlayState.again)
{
SongList[songIndex].SetSongPlayed();
}
else
{
songIndex++;
}
}
}
5.Song类:
enum SongPlayState
{
unplayed,played,again,cut
} /// <summary>
/// 歌曲类
/// </summary>
class Song
{
/// <summary>
/// 歌曲名称
/// </summary>
public string SongName
{
get { return songName; }
set { songName = value; }
} /// <summary>
/// 歌曲存放路径
/// </summary>
public string SongURL
{
get { return songURL; }
set { songURL = value; }
} /// <summary>
/// 歌曲播放状态
/// </summary>
internal SongPlayState PlayState
{
get { return playState; }
set { playState = value; }
} private string songName;
private string songURL;
private SongPlayState playState = SongPlayState.unplayed; // 歌曲播放状态 /// <summary>
/// 将歌曲状态改为已播放
/// </summary>
public void SetSongPlayed()
{
this.playState = SongPlayState.played;
} /// <summary>
/// 将歌曲状态改为再拨放一次
/// </summary>
public void SetPlayAgain()
{
this.playState = SongPlayState.again;
} /// <summary>
/// 将歌曲状态改为切歌
/// </summary>
public void SetSongCut()
{
this.playState = SongPlayState.cut;
}
}
6.KTVUtil类:
这里主要存的就是路径
public static string singerPhotoPath = ""; // 歌手照片路径
public static string songPath = ""; // 歌曲路径
7.SongList类:
public enum PalySongState
{
//未播放 , 播放, 重播,切歌
unplayed,played,again,cut
}
/// <summary>
/// 歌曲播放类
/// </summary>
public class SongList
{
//歌曲名称
private string SongName;
//歌曲路径
private string SongUl;
//歌曲状态
private string SongState; public string SongState1
{
get { return SongState; }
set { SongState = value; }
} public string SongUl1
{
get { return SongUl; }
set { SongUl = value; }
} public string SongName1
{
get { return SongName; }
set { SongName = value; }
} //把当前的播放状态设置为未播放状态
private PalySongState playSong = PalySongState.unplayed; public PalySongState PlaySong
{
get { return playSong; }
set { playSong = value; }
}
/// <summary>
/// 将未播放状态改为播放状态
/// </summary>
public void PalyState()
{
this.PlaySong = PalySongState.played;
}
/// <summary>
/// 将歌曲重新播放
/// </summary>
public void AgainState()
{
this.PlaySong = PalySongState.again;
}
/// <summary>
/// 切歌状态
/// </summary>
public void CutState()
{
this.PlaySong = PalySongState.cut;
}
}
那么以上就是本次的KTV项目了,这个只是前台,那么大家也可以写一个后台进行管理和维护前台,通过数据库就可以
把前台和后台连在一起。
MyKTV项目,走起!的更多相关文章
- MyKTV项目总结
今天和大伙分享一下我的KTV系统,我想大家都有自己独特的魅力,都有自己的风采,都有自己骄傲的一部分. 在这里我就抛砖引玉,聊聊我的KTV项目,希望大家能给出自己的建议.. 首先,我们先了解一下:当我们 ...
- C#Windows窗体应用程序MyKTV项目
后台管理其中有一个添加歌手信息和歌曲信息的窗体要点击按钮并上传文件,因为对那些文件流什么的不懂,所以用了老师教的最简单的判断方法,但此方法只是按后缀名判断文件的样式,如果后缀名乱改就不行了! 此时需要 ...
- 一个P2P点播直播开源项目:P2PCenter
最近跟着公司的项目走,我也研究了不少东西,尤其是在P2P方面,广泛涉猎各种开源项目,尤其是国外的开源项目,意外的发现了一个国内的项目,做的还不错,推荐一下.---------------------使 ...
- VS2013 MVC Web项目使用内置的IISExpress支持局域网内部机器(手机、PC)访问、调试
VS2013内置了IISExpress.做asp.net MVC的web项目开发时,Ctrl+F5和F5启动项目运行(后者是调试模式)的同时都会打开IISExpress,事实上本机对该web项目走的就 ...
- 【转并修改】VS2013 MVC Web项目使用内置的IISExpress支持局域网内部机器(手机、PC)访问、调试
转:http://www.cnblogs.com/ShaYeBlog/p/4072074.html VS2013内置了IISExpress.做asp.net MVC的web项目开发时,Ctrl+F5和 ...
- 迈向angularjs2系列(8):angular cli和angular2种子项目
文章目录 1.angular cli快速搭建项目 2.angular2-seed 3.手动配置 题外话:如何更好的阅读本篇文章 一: angular cli的安装 Angular-cli(命令行界面, ...
- 手把手教你从零开始搭建SpringBoot后端项目框架
原料 新鲜的IntelliJ IDEA.一双手.以及电脑一台. 搭建框架 新建项目 打开IDE,点击File -> New Project.在左侧的列表中的选择Maven项目,点击Next. 填 ...
- 转一篇做BI项目的好文
首先,我们有一个大的假设前提,集团报表平台是服务于大型公司,比如有很多分公司,子公司,多部门等,并且有BI需求的访问人群超过1000以上的公司. 这样,我们的关键词是:集团 平台 运营 集团:意味着, ...
- maven 项目加载本地JAR
将jar安装到本地的maven仓库 1.首先确定本地有maven环境. 2.安装本地jar 模板: mvn install:install-file -Dfile=<path-to-file& ...
随机推荐
- Android学习----五大布局
1.LinearLayout 线性布局 android:orientation="horizontal" 制定线性布局的排列方式 水平 horizontal 垂直 vertical ...
- ueditor 1.4.3.2 独立/单独 上传图片框原理
其实简单的说就是编辑框很多按钮,所有按钮的功能都是以command形式提供,所以execCommand就是执行这些功能的命令.有些按钮是能弹出显示一个对话框,他的基类就是dialog,而所有被弹出的d ...
- 如何在C#添加鼠标右键菜单
C#添加鼠标右键方法步骤: 1 选中要添加右键功能的Form或者控件,打开控件的设计页面. 2 从工具箱中找到ContextMenuStrip控件,将这个控件拖曳到Form或者控件的设计页面上.这时系 ...
- Linux下Openfire相关安装和配置
记录下来,方便下次再用时从头查找资料 小京东ecshop中的通讯有用到openfire,Window下配置安装很简单,直接下载exe文件安装就行,而linux下要麻烦一点.安装后的配置下面会细说: 一 ...
- A记录、CNAME记录、MX记录
A 记录(Address) (一句话:用来指定域名和服务器IP的对应关系) 是用来指定主机名(或域名)对应的IP地址记录.用户可以将该域名下的网站服务器指向到自己的web server上.同时也可以 ...
- C:\WINDOWS\system32\config\systemprofile\Desktop引用了一个不可用的位置
使用迅雷下载压缩文件到桌面时,下载完毕后,如果直接点击"打开文件",则迅雷会报错: C:\WINDOWS\system32\config\systemprofile\Desktop ...
- ARC下的内存泄露
iOS提供了ARC功能,很大程度上简化了内存管理的代码. 但使用ARC并不代表了不会发生内存泄露,使用不当照样会发生内存泄露. 下面列举两种ARC导致内存泄露的情况. 1,循环参照 A有个属性参照B, ...
- 减少JAVA GC
减少GC开销的措施:程序的运行会直接影响系统环境的变化,从而影响GC的触发.若不针对GC的特点进行设计和编码,就会出现内存驻留等一系列负面影响.为了避免这些影响,基本的原则就是尽可能地减少垃圾和减少G ...
- linux kernel
first step. http://www.cyberciti.biz/faq/howto-install-kernel-headers-package/ http://uliweb.clkg.or ...
- redgate
http://www.cnblogs.com/VAllen/archive/2012/09/08/SQLPrompt.html http://www.cnblogs.com/dotLive/archi ...