影院售票系统
這個影院售票的項目比較的復雜,共需要九個類.
No.1首先第一個類,座位類。該項目的座位默認為黃色,被售出的狀態下默認為紅色。需要導入命名空間 Using.System.Drawing.Color
public class Seat{public Color Color { get; set; }//座位顏色public string Num { get; set; }//座位號public Seat(){}public Seat(Color color,string num){this.Color = color;this.Num = num;}}No.2電影類,沒啥說的。按照面向對象的思想封裝一堆屬性。
[Serializable]//可序列化的標識!public class Movie{public string Name { get; set; }public string DaoYan { get; set; }public string Star { get; set; }public string MovieType { get; set; }public string Url { get; set; }public int Price { get; set; }public Movie(){}public Movie(string name,string daoyan,string star,string type,string url,int price){this.Name = name;this.DaoYan = daoyan;this.Star = star;this.MovieType = type;this.Url = url;this.Price = price;}}No.3放映計劃類,保存每天放映計劃的集合,有一個解析XML文件的方法!
?
[Serializable]//可序列化標識public class Schedule{public Dictionary<string, ScheduleItems> Items { get; set; }public Schedule(){this.Items = new Dictionary<string, ScheduleItems>();}public Schedule(Dictionary<string, ScheduleItems> item){this.Items = item;}public void Show(){XmlDocument myxml = new XmlDocument();myxml.Load("ShowList.xml");XmlNode root = myxml.DocumentElement;foreach (XmlNode item in root.ChildNodes){Movie movie = new Movie();foreach (XmlNode child in item.ChildNodes){switch (child.Name){case "Name":movie.Name = child.InnerText;break;case "Poster":movie.Url = child.InnerText;break;case "Director":movie.Star = child.InnerText;break;case "Actor":movie.DaoYan = child.InnerText;break;case "Price":movie.Price = Convert.ToInt32(child.InnerText);break;case "Type":movie.MovieType = child.InnerText;break;case "Schedule":foreach (XmlNode childs in child.ChildNodes)//解析并賦值 {ScheduleItems sch = new ScheduleItems(movie, childs.InnerText);this.Items.Add(childs.InnerText, sch);}break;}}}}No.4影院每天放映計劃的場次,保存每場電影的信息,所以有一個Movie類型的movie屬性
[Serializable]public class ScheduleItems{public Movie Movie { get; set; }public string Time { get; set; }public ScheduleItems(Movie movie,string time){this.Movie = movie;this.Time = time;}public ScheduleItems(){}}No.5電影票父類,保存電影票的信息和放映場次,里面有2個虛方法,用于計算價格,打印電影票.
[Serializable]public class Tickey{public ScheduleItems Item { get; set; }public Seat Seat{ get; set; }public int Price { get; set; }public virtual int CalcPrice(){int money = this.Item.Movie.Price;return money;}public Tickey(){}public Tickey(ScheduleItems item,Seat seat){this.Item = item;this.Seat = seat;this.Price = CalcPrice();}public virtual void Print(){string path = (this.Item.Time + " " + this.Seat.Num).Replace(":","-") +".txt";//文件名 MessageBox.Show(path);FileStream fs = new FileStream(path, FileMode.Create);StreamWriter sw = new StreamWriter(fs, Encoding.Default);sw.WriteLine("*******************************");sw.WriteLine(" 青鳥影院 ");sw.WriteLine("-------------------------------");sw.WriteLine("電影名:" + Item.Movie.Name);sw.WriteLine("時間:" + this.Item.Time);sw.WriteLine("座位號:" + this.Seat.Num);sw.WriteLine("價格:" + this.Price);sw.WriteLine("*******************************");sw.Close();fs.Close();}}No.6學生票子類,繼承電影票類,保存特殊的信息(折扣),并且重寫父類的虛方法
public int DicCount { get; set; }public override int CalcPrice(){int money = this.Item.Movie.Price*DicCount/10;return money;}public StudentTickey() {}public StudentTickey(ScheduleItems Item, Seat seat, int discount): base(Item, seat){this.DicCount = discount;this.Price = CalcPrice();}public override void Print(){string path = (this.Item.Time + " " + this.Seat.Num).Replace(":", "-") + ".txt";//文件名FileStream fs = new FileStream(path, FileMode.Create);StreamWriter sw = new StreamWriter(fs, Encoding.Default);sw.WriteLine("*******************************");sw.WriteLine(" 青鳥影院 ");sw.WriteLine("-------------------------------");sw.WriteLine("電影名:" + Item.Movie.Name);sw.WriteLine("時間:" + this.Item.Time);sw.WriteLine("座位號:" + this.Seat.Num);sw.WriteLine("價格:" + this.Price);sw.WriteLine("*******************************");sw.Close();fs.Close();}}No.7免費票子類,獲取獲贈者的名字,重寫父類的虛方法,將計算價格方法的返回值改為0
public class FreeTickey:Tickey{public string FreeName { get; set; }public override int CalcPrice(){int money = 0;return money;}public FreeTickey() {}public FreeTickey(ScheduleItems Item, Seat seat,string name): base(Item, seat){this.FreeName = name;this.Price = CalcPrice();}public override void Print(){string path = (this.Item.Time + " " + this.Seat.Num).Replace(":", "-") + ".txt";//文件名FileStream fs = new FileStream(path, FileMode.Create);StreamWriter sw = new StreamWriter(fs, Encoding.Default);sw.WriteLine("*******************************");sw.WriteLine(" 青鳥影院 ");sw.WriteLine("-------------------------------");sw.WriteLine("電影名:" + Item.Movie.Name);sw.WriteLine("時間:" + this.Item.Time);sw.WriteLine("座位號:" + this.Seat.Num);sw.WriteLine("價格:" + this.Price);sw.WriteLine("*******************************");sw.Close();fs.Close();}}No.8電影院類,可以看作是以上幾個類的集合。定義座位集合Dictionary<string,Seat>;放映計劃和已售出票的集合list<Tickey>
[Serializable]public class Cinema{public Dictionary<string,Seat> Seats { get; set; }public Schedule Dule { get; set; }public List<Tickey> SoldTickeys { get; set; }public Cinema(){this.Seats = new Dictionary<string, Seat>();this.SoldTickeys = new List<Tickey>();this.Dule = new Schedule();}接下來我們要研究一下Form窗體中的代碼了!!!!
1:首先:初始化TreeView樹狀圖中的電影信息及播放場次
public void Show(){cinema.Dule.Show();TreeNode root = null;foreach (ScheduleItems item in cinema.Dule.Items.Values){if (root == null || root.Text != item.Movie.Name){root = new TreeNode(item.Movie.Name);this.TvList.Nodes.Add(root);}root.Nodes.Add(item.Time);}}通過調用在放映計劃類中的(Schedule)中寫好的解析XML文檔的方法解析。為什么要使用影院類的對象來調用這個方法呢?因為在cinema中封裝好了3個自定義類型的字段,可以直接通過cinema對象調用,避免了多次創建其他類的對象,統一調配。 樹狀圖以電影名為父節點,播放時間為子節點,首先創建出父節點對象,遍歷播放時間集合,做出一道判斷,將電影名放到父節點上,則將播放時間賦給子節點。
2.展示電影和電影票的信息,在樹狀結構被選中的事件上。
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e){TreeNode node = TvList.SelectedNode;if (node.Nodes==null || node.Nodes.Count==0){this.label1.Text = cinema.Dule.Items[node.Text].Movie.Name;this.label2.Text = cinema.Dule.Items[node.Text].Movie.DaoYan;this.label3.Text = cinema.Dule.Items[node.Text].Movie.DaoYan;this.label4.Text = cinema.Dule.Items[node.Text].Movie.MovieType;this.label5.Text = cinema.Dule.Items[node.Text].Time;this.label6.Text = cinema.Dule.Items[node.Text].Movie.Price.ToString();this.label7.Text = "";this.picMovie.Image = Image.FromFile(cinema.Dule.Items[node.Text].Movie.Url);string key = node.Parent.Text + node.Text; ColorYellow();//將控件變成黃色}public void ColorYellow(){foreach (Control itemC in this.tabCon.Controls){itemC.BackColor = Color.Yellow;}}首先記錄下被選中節點(基本上在樹狀類型被選中的事件中都要有這么的一句話)判斷如果被選中的節點下沒有子節點了,開始將界面上的label標簽賦值。首先被選中的節點是父節點電影名稱,之后被選中的節點是放映時段,根據此時段加載出該電影的信息和票價,并且將控件變為黃色。因為每一種電影的每一個播放場次均有座位(各有自己的一套座位)。
3:實現買票功能:首先動態加載出一堆的label控件,即座位。確定幾種買票的方式,通過單選按鈕的事件實現。
?
private void rb02_CheckedChanged(object sender, EventArgs e){this.textBox1.Enabled = true;this.comboBox1.Enabled = false;this.comboBox1.Text = "";this.label7.Text = "0";}private void rb03_CheckedChanged(object sender, EventArgs e){this.textBox1.Enabled = false;this.textBox1.Text = "";this.comboBox1.Enabled = true;this.comboBox1.Text = "7";if (this.label6.Text != ""){int price = Convert.ToInt32(label6.Text);int discount = Convert.ToInt32(comboBox1.Text);this.label7.Text = (price * discount / 10).ToString();}}private void rb01_CheckedChanged(object sender, EventArgs e){this.textBox1.Enabled = false;this.textBox1.Text = "";this.comboBox1.Enabled = false;this.comboBox1.Text = "";int price = Convert.ToInt32(label6.Text);this.label7.Text = price.ToString();}private void FrmMain_Load(object sender, EventArgs e){Init(5,7);}public void Init(int row, int line){for (int i = 0; i < row; i++){for (int j = 0; j < line; j++){Label lb = new Label();lb.BackColor = Color.Yellow;lb.Location = new Point(20 + j * 100, 50 + i * 70);lb.Font = new Font("宋體", 11);lb.Name = (i + 1) + "-" + (j + 1);lb.Size = new Size(80, 30);lb.TabIndex = 0;lb.Text = (i + 1) + "-" + (j + 1);lb.TextAlign = ContentAlignment.MiddleCenter;lb.Click += new System.EventHandler(lb_Click);this.tabCon.Controls.Add(lb);Seat seat = new Seat( Color.Yellow,lb.Text);cinema.Seats.Add(seat.Num, seat);}}}private void lb_Click(object sender, EventArgs e){if (this.TvList.Nodes.Count == 0 || this.TvList.SelectedNode.Level == 0){return;}lbl = sender as Label;//object基類型轉化為Label類型if (lbl.BackColor == Color.Red){MessageBox.Show("已售出");}else{if (DialogResult.OK == MessageBox.Show("是否購買", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question)){//用于判斷如何得到Cinemabool flag = true;Cinema cinema2 = null;string text = TvList.SelectedNode.Text;string txt = TvList.SelectedNode.Parent.Text;string key = txt + text;foreach (string itemKey in dic.Keys){if (key.Equals(itemKey)){cinema2 = dic[itemKey];flag = false;}}if (flag){cinema2 = new Cinema();cinema2.Seats = cinema.Seats;cinema2.Dule = cinema.Dule;}string time = this.TvList.SelectedNode.Text;ScheduleItems item = cinema2.Dule.Items[time];string type =this.rb01.Checked ? "normal" : rb02.Checked ? "free" : "student";Tickey tic = null;switch (type){case "normal":tic = new Tickey(item, cinema2.Seats[lbl.Text]);tic.Print();break;case"free":tic = new FreeTickey(item, cinema2.Seats[lbl.Text], textBox1.Text);tic.Print();break;case"student":tic = new StudentTickey(item, cinema2.Seats[lbl.Text], Convert.ToInt32(comboBox1.Text));tic.Print();break;}dic.Add(key, cinema2);lbl.BackColor = Color.Red;cinema.Seats[lbl.Text].Color = Color.Red;}}}?
?
?
?創建一個雙列集合Dictionary(string,Ciname)如果被選中的節點的文本與其父節點的文本與該集合的key值相等,cinema對象等于dic[key];因為Cinema保存的是播放時段,座位和被賣出去的票。
通過電影名稱和選中的時間段來確定這三個屬性。然后判斷被買的票的類型,將其加入到dic集合中。最后將控件的顏色變成紅色。
4:通過序列化和反序列化來實現保存和繼續銷售的功能。
private void 保存ToolStripMenuItem_Click(object sender, EventArgs e){//直接序列化 Dictionary dic 這樣 在反序列化時就啥都不用干了。BinaryFormatter bf = new BinaryFormatter();FileStream fs = new FileStream("YingPianInfo.bin", FileMode.Open);bf.Serialize(fs, dic);fs.Close();MessageBox.Show("保存成功");}private void 繼續銷售ToolStripMenuItem_Click(object sender, EventArgs e){Show();BinaryFormatter bf = new BinaryFormatter();FileStream fs = new FileStream("YingPianInfo.bin", FileMode.Open);dic = (Dictionary<string, Cinema>)bf.Deserialize(fs);fs.Close();}?直接序列化dic集合就可以了,因為dic集合中保存的就是被賣出票的所有信息。
5:最后在繼續銷售的時候,將已經賣出的座位標識為紅色(即已售出)
public void SeatColorChanage(List<Tickey> tickeys)//將已售出的票變成紅色 根據字典集合的鍵值 {if (tickeys!=null && tickeys.Count!=0){foreach (Tickey item in tickeys)//所有被賣出的票 {foreach (string cinemaSet in cinema.Seats.Keys)//已經售出座位的編號 {if (cinemaSet.Equals(item.Seat.Num))//如果匹配已經售出的座位 {foreach (Control itemLast in this.tabCon.Controls){if (itemLast.Text.Equals(cinemaSet)){itemLast.BackColor = Color.Red;}}}}}}}
?因為以上的dic集合保存的是已經售出票的信息,如果其中的座位編號與當前的座位編號相匹配的話,將其變成紅色,在treeView的事件中調用該方法。如果是該電影該時段的情況下,以dic[item].Soldtickeys.因為Soldtickey是list<tickey>類型,該字段又存在于cinema類中,所以直接以其為參數傳遞,將控件變為紅色!
轉載于:https://www.cnblogs.com/chimingyang/p/5419011.html
總結
- 上一篇: 【 D3.js 入门系列 --- 9 】
- 下一篇: Qt的MDI中多个子窗口响应一个菜单事件