7.2.2 在窗体上显示绘图
来源:互联网 发布:加湿器推荐 知乎 编辑:程序博客网 时间:2024/05/17 04:16
7.2.2 在窗体上显示绘图
绘图与第四章的示例类似。因为绘图需要一定的时间,我们将在内存中创建位图,绘制好文档,然后,在窗体上显示位图,而不是每次窗体失效时都绘制文档。我们先看一下非常有用的函数式编程模式,这一节就将使用。
“Hole in the Middle(中间有洞)”模式
[真心不知道,Hole in the Middle 是什么意思?]
写代码的一个常见情形,是首先进行初始化,然后,是函数的核心部分,最后,是一些清理工作;在程序中的多个位置,重复执行类似的操作,初始化和清理部分没有变化,而只有核心部分不同。在内存中绘制位图的示例,用 C# 写的代码可能像这样:
var bmp = new Bitmap(width, height)
using(var gr = Graphics.FromImage(bmp)) {
(...)
}
这里,代码的核心部分是第三行的占位符,我们将用值 gr 来绘图。问题是,只使用面向对象的编程概念,不能简单地把执行初始化和清理的代码,包装成一个子程序,实现在绘制不同图形的所有地方共享。C# 语言支持这种模式众所周知,通常使用各种初始化和清理的类型;using 构造就是这种情况。我们如何为自己的代码模式实现类似的功能呢?
用函数式编程,解决起来很简单;可以写一个高阶函数,把核心部分包装到 lambda 函数中,并把它作为高阶函数的参数值:
var bmp = DrawImage(width, height, gr => {
(...)
});
从函数编程的角度来看,这仅是一个使用高阶函数的无趣示例,但是,它描述了这样一种情况,先执行一些初始化,接着是核心部分,然后是清理,而且这种情况非常普遍,所以,需要有一个专门的名字。这个名字是由 Brian Hurt 在他的博客《“Hole in the Middle(中间有洞)”模式》[Hurt, 2007] 中首次使用,它很好地描述了这种情况,即,每次使用代码,只有中间的部分需要用不同的功能填充。
清单 7.7 是用 F# 实现的函数,类似于补充材料“Hole in the Middle(中间有洞)模式”中的 DrawImage,有一点不同,用两个参数指定创建位图的大小,还能够指定图像边框的边距。
清单 7.7 绘制图形的函数 (F# Interactive)
> let drawImage (width:int, height:int) space coreDrawingFunc =
let bmp = new Bitmap(width, height)
use gr = Graphics.FromImage(bmp) [1]
gr.Clear(Color.White)
gr.TranslateTransform(space, space) <-- 移动整个图像
coreDrawingFunc(gr) [2]
bmp
;;
val drawImage : int * int -> float32 -> (Graphics -> unit) –> Bitmap [3]
我们使用这个函数来绘制图像,绘图的核心部分是作为最后参数给定的函数,从类型签名[3]可以看出,这个函数的参数为 Graphics 值,不返回结果;在代码的中间[2],创建位图和 Graphics 对象之后,被调用。在初始化阶段,我们还调用 TranslateTransform,提供图像的边距。
我们创建的 Graphics 对象实现了 IDisposable,所以,需要在完成绘图后释放。在 C# 中,我们使用知名的 using 构造;在 F# 中,用 use 关键字[1],可以做类似的工作。在清单 7.7 中,在返回结果的位图之前,自动释放 Graphics 对象。use 关键字的与 using 有点不同,我们将在第九章讨论。
最后,我们需要看代码的实际效果。现在,我们将用交互方式创建并测试窗体。清单 7.8 演示了如何绘制清单 7.5 的屏幕元素,以及把文档显示在窗体上。
清单 7.8 使用 WinForms 绘制文档 (F# Interactive)
> let docImage = drawImage (450, 400) 20.0f (drawElements elements) [1]
val docImg : Bitmap
> open System.Windows.Forms
let main = new Form(Text = "Document", BackgroundImage = docImage, | 创建有文档
Width = docImage.Width, Height = docImage.Height) | 的窗体
main.Show();; |
绘制位图[1]的这一行可能要解释一下。我们调用 drawImage,它的最后一个参数是函数,指定了绘图的核心部分。因为我们曾经在 drawElements中实现了这个函数,你可能希望能够将它直接作为最后一个参数值来传递;然而,drawElements 有两个参数,而 drawImage 函数只有一个参数(需要绘制的 Graphics 对象)。我们使用散函数应用指定有 ScreenElement 值的列表;散应用的结果是函数,以 Graphics 对象,并绘制文档,这正是我们需要的 (图 7.2)。
我们以前使用的文档表示方式,虽然使创建文档的代码是有点笨拙,但是,能够轻松地实现绘制。在函数式编程中,我们经常会发现,不同的上下文需要不同数据结构:在某种程度上,期望的用法决定好的表示形式;对于函数式程序,同样的信息,在同一个程序中,有不同的表示形式,并不少见。现在,我们已经找到了适合绘制图像的表示形式,那么,还需要设计适合构造和处理的表示形式,然后,再写一个转换函数,实现两种表示形式的转换。
绘图与第四章的示例类似。因为绘图需要一定的时间,我们将在内存中创建位图,绘制好文档,然后,在窗体上显示位图,而不是每次窗体失效时都绘制文档。我们先看一下非常有用的函数式编程模式,这一节就将使用。
“Hole in the Middle(中间有洞)”模式
[真心不知道,Hole in the Middle 是什么意思?]
写代码的一个常见情形,是首先进行初始化,然后,是函数的核心部分,最后,是一些清理工作;在程序中的多个位置,重复执行类似的操作,初始化和清理部分没有变化,而只有核心部分不同。在内存中绘制位图的示例,用 C# 写的代码可能像这样:
var bmp = new Bitmap(width, height)
using(var gr = Graphics.FromImage(bmp)) {
(...)
}
这里,代码的核心部分是第三行的占位符,我们将用值 gr 来绘图。问题是,只使用面向对象的编程概念,不能简单地把执行初始化和清理的代码,包装成一个子程序,实现在绘制不同图形的所有地方共享。C# 语言支持这种模式众所周知,通常使用各种初始化和清理的类型;using 构造就是这种情况。我们如何为自己的代码模式实现类似的功能呢?
用函数式编程,解决起来很简单;可以写一个高阶函数,把核心部分包装到 lambda 函数中,并把它作为高阶函数的参数值:
var bmp = DrawImage(width, height, gr => {
(...)
});
从函数编程的角度来看,这仅是一个使用高阶函数的无趣示例,但是,它描述了这样一种情况,先执行一些初始化,接着是核心部分,然后是清理,而且这种情况非常普遍,所以,需要有一个专门的名字。这个名字是由 Brian Hurt 在他的博客《“Hole in the Middle(中间有洞)”模式》[Hurt, 2007] 中首次使用,它很好地描述了这种情况,即,每次使用代码,只有中间的部分需要用不同的功能填充。
清单 7.7 是用 F# 实现的函数,类似于补充材料“Hole in the Middle(中间有洞)模式”中的 DrawImage,有一点不同,用两个参数指定创建位图的大小,还能够指定图像边框的边距。
清单 7.7 绘制图形的函数 (F# Interactive)
> let drawImage (width:int, height:int) space coreDrawingFunc =
let bmp = new Bitmap(width, height)
use gr = Graphics.FromImage(bmp) [1]
gr.Clear(Color.White)
gr.TranslateTransform(space, space) <-- 移动整个图像
coreDrawingFunc(gr) [2]
bmp
;;
val drawImage : int * int -> float32 -> (Graphics -> unit) –> Bitmap [3]
我们使用这个函数来绘制图像,绘图的核心部分是作为最后参数给定的函数,从类型签名[3]可以看出,这个函数的参数为 Graphics 值,不返回结果;在代码的中间[2],创建位图和 Graphics 对象之后,被调用。在初始化阶段,我们还调用 TranslateTransform,提供图像的边距。
我们创建的 Graphics 对象实现了 IDisposable,所以,需要在完成绘图后释放。在 C# 中,我们使用知名的 using 构造;在 F# 中,用 use 关键字[1],可以做类似的工作。在清单 7.7 中,在返回结果的位图之前,自动释放 Graphics 对象。use 关键字的与 using 有点不同,我们将在第九章讨论。
最后,我们需要看代码的实际效果。现在,我们将用交互方式创建并测试窗体。清单 7.8 演示了如何绘制清单 7.5 的屏幕元素,以及把文档显示在窗体上。
清单 7.8 使用 WinForms 绘制文档 (F# Interactive)
> let docImage = drawImage (450, 400) 20.0f (drawElements elements) [1]
val docImg : Bitmap
> open System.Windows.Forms
let main = new Form(Text = "Document", BackgroundImage = docImage, | 创建有文档
Width = docImage.Width, Height = docImage.Height) | 的窗体
main.Show();; |
绘制位图[1]的这一行可能要解释一下。我们调用 drawImage,它的最后一个参数是函数,指定了绘图的核心部分。因为我们曾经在 drawElements中实现了这个函数,你可能希望能够将它直接作为最后一个参数值来传递;然而,drawElements 有两个参数,而 drawImage 函数只有一个参数(需要绘制的 Graphics 对象)。我们使用散函数应用指定有 ScreenElement 值的列表;散应用的结果是函数,以 Graphics 对象,并绘制文档,这正是我们需要的 (图 7.2)。
图 7.2 保存在屏幕元素列表中的示例文档,使用 drawElements 函数在窗体上绘制。
我们以前使用的文档表示方式,虽然使创建文档的代码是有点笨拙,但是,能够轻松地实现绘制。在函数式编程中,我们经常会发现,不同的上下文需要不同数据结构:在某种程度上,期望的用法决定好的表示形式;对于函数式程序,同样的信息,在同一个程序中,有不同的表示形式,并不少见。现在,我们已经找到了适合绘制图像的表示形式,那么,还需要设计适合构造和处理的表示形式,然后,再写一个转换函数,实现两种表示形式的转换。
0 0
- 7.2.2 在窗体上显示绘图
- 7.2.2 在窗体上显示绘图
- 如何使用gtk+在窗体上绘图
- C#0009--直接在窗体上绘图
- C#使用Graphics在窗体上绘图
- 子窗体显示在MDI窗体上
- C#使用Graphics在窗体上绘图(加滚动条)
- 非MainForm窗体显示在任务栏上
- 如何在Web窗体上显示XML文档
- DELPHI 让子窗体显示在任务栏上
- 窗体间传送图片并显示在水晶报表上
- 在透明窗体上显示标准Winform控件
- C# WinForm 改变控件在窗体上的显示位置
- 解析XML文件,并将信息显示在窗体上
- c++win32在窗体上动态显示时间
- 将word文档在窗体上直接显示
- OpenCV读入的图像如何显示在窗体上
- DELPHI 让子窗体显示在任务栏上
- Socket 简单实现服务器和客户端
- 他们为啥不爱谷歌眼镜了?
- MySQL索引背后的数据结构及算法原理
- 第三方支付为什么会兴起?
- nodejs中Assert是Assert.ok的别名
- 7.2.2 在窗体上显示绘图
- java中的多线程
- AVL树的插入删除查找算法实现和分析-2(树高度法)
- 第十三周 项目三 成绩处理模板
- easyui Datagrid 加入 add, cut, save工具栏
- Source Insig快键方式ht的
- Java Vector与ArrayList的区别
- Oracle 11g中Temp临时表空间、文件的新特性
- hash实现--开放寻址方式