x01.drawPie

随心而动,改变世界!在此,沉痛悼念 乔布斯!

多核时代,并行时代!而函数式编程的不变性,具有很大的优势。F# 更能轻松集成 C# 的大部分功能,很有学习的必要。

学习的方法,与其空谈理论,不如来个实际的例子更带劲。刚学了个画饼图,推荐给大家。

运行 VS2010 SP1,新建项目选择 F#应用程序 ,在 program.fs 中输入以下代码,按 F5 即可。勿忘添加相关引用!

View Code
  1 open System
2 open System.IO
3 open System.Drawing
4 open System.Windows.Forms
5
6 let main = new Form(Width=620, Height=450, Text="Pie Chart")
7
8 let menu = new ToolStrip()
9 let btnOpen = new ToolStripButton("Open")
10 let btnSave = new ToolStripButton("Save", Enabled=false)
11 ignore(menu.Items.Add(btnOpen))
12 ignore(menu.Items.Add(btnSave))
13 main.Controls.Add(menu)
14
15 let boxChart =
16 new PictureBox(BackColor=Color.White, Dock=DockStyle.Fill,SizeMode=PictureBoxSizeMode.CenterImage)
17 main.Controls.Add(boxChart)
18
19 let rand = new Random()
20 let randBrush() =
21 let r, g, b = rand.Next(256), rand.Next(256), rand.Next(256)
22 new SolidBrush(Color.FromArgb(r,g,b))
23
24 let drawPie(g:Graphics, title, startAngle, occupieAngle) =
25 let br = randBrush()
26 g.FillPie(br,170,70,260,260,startAngle,occupieAngle)
27 br.Dispose()
28
29 let font = new Font("Times new roman", 10.0f)
30
31 let centerX, centerY = 300.0, 200.0
32 let distance = 150.0
33
34 let drawTitle(g:Graphics, title, startAngle, occupieAngle) =
35 let ra = Math.PI * 2.0 * float(startAngle + occupieAngle/2) / 360.0
36 let x = centerX + distance * cos(ra)
37 let y = centerY + distance * sin(ra)
38 let size = g.MeasureString(title, font)
39 let rc = new PointF(float32(x) - size.Width / 2.0f, float32(y) - size.Height / 2.0f)
40 g.DrawString(title, font, Brushes.Black, new RectangleF(rc,size))
41
42 let drawStep(drawFunc, g:Graphics, sum, data) =
43 let rec drawStepUtil(data, angleSoFar) =
44 match data with
45 | [] -> () //empty
46 | [title, value] -> // have one then draw
47 let angle = 360 - angleSoFar
48 drawFunc(g, title, angleSoFar, angle)
49 | (title, value)::tail -> // not only one then recursive draw
50 let angle = int(float(value) / sum * 360.0)
51 drawFunc(g, title, angleSoFar, angle)
52 drawStepUtil(tail, angleSoFar+angle)
53 drawStepUtil(data,0)
54
55 let convertDataRow(line:string) =
56 let cells = List.ofSeq(line.Split(','))
57 match cells with
58 | title::number::_ ->
59 let num = Int32.Parse(number)
60 (title, num)
61 | _ -> failwith "Incorret data format!"
62
63
64 let rec processLines(lines) =
65 match lines with
66 | [] -> []
67 | currentLine::remaining ->
68 let line = convertDataRow(currentLine)
69 let rest = processLines(remaining)
70 line::rest
71
72 let rec calculateSum(rows) =
73 match rows with
74 | [] -> 0
75 | (_, value)::tail ->
76 let sum = calculateSum(tail)
77 value + sum
78
79 let drawChart(file) = //real main draw chart
80 let lines = List.ofSeq(File.ReadAllLines(file))
81 let data = processLines(lines)
82 let sum = float(calculateSum(data))
83
84 let pieChart = new Bitmap(600,400)
85 let g = Graphics.FromImage(pieChart)
86
87 g.Clear(Color.White)
88 drawStep(drawPie, g, sum, data)
89 drawStep(drawTitle, g, sum, data)
90
91 g.Dispose()
92 pieChart
93
94 let openClick(e) =
95 let dlg = new OpenFileDialog()
96 if (dlg.ShowDialog() = DialogResult.OK) then
97 let pieChart = drawChart(dlg.FileName)
98 boxChart.Image <- pieChart
99 btnSave.Enabled <- true
100
101 let saveClick(e) =
102 let dlg = new SaveFileDialog()
103 if (dlg.ShowDialog() = DialogResult.OK) then
104 boxChart.Image.Save(dlg.FileName)
105
106 [<STAThread>]
107 do
108 btnOpen.Click.Add(openClick)
109 btnSave.Click.Add(saveClick)
110 Application.EnableVisualStyles()
111 Application.Run(main)

其中,打开文件对话框,选择的文本文件内容应是分行名值对,如下所示:

   hello, 299

   world, 399

   china, 3993

   yes, 333

C# 学习 Java 多多,也改进多多。

F# 借鉴 OCaml,走了另一条路。但其高明之处,却在于不忘 C#,将函数式与命令式作了一个无缝的融合。

你可能感兴趣的:(raw)