包含标签 windows 的文章

[藏]运用 BoxLayout 进行 Swing 控件布局

写的非常非常好的一个教程,感谢陈 怡平 引言 在用户使用 Java Swing 进行用户界面开发过程中,会碰到如何对 Java Swing 的控件进行布局的问题。Swing 的控件放置在容器 (Container) 中,容器就是能够容纳控件或者其它容器的类,容器的具体例子有 Frame、Panel 等等。容器需要定义一个布局管理器来对控件进行布局管理,Swing 当中提供的主要的布局管理器有 FlowLayout、BorderLayout、BoxLayout、GridLayout 和 GridBaglayout, 它们的主要特点如表 1 所示: 表 1. Swing 中的一些主要布局管理器的比较 BoxLayout 介绍 如前所述,BoxLayout 可以把控件依次进行水平或者垂直排列布局,这是通过参数 X_AXIS、Y_AXIS 来决定的。X_AXIS 表示水平排列,而 Y_AXIS 表示垂直排列。BoxLayout 的构造函数有两个参数,一个参数定义使用该 BoxLayout 的容器,另一个参数是指定 BoxLayout 是采用水平还是垂直排列。下面是一个创建 BoxLayout 实例的例子: 当 BoxLayout 进行布局时,它将所有控件依次按照控件的优先尺寸按照顺序的进行水平或者垂直放置,假如布局的整个水平或者垂直空间的尺寸不能放下所有控件,那么 BoxLayout 会试图调整各个控件的大小来填充整个布局的水平或者垂直空间。 BoxLayout 往往和 Box 这个容器结合在一起使用,这么做的理由是,BoxLayout 是把控件以水平或者垂直的方向一个接一个的放置,如果要调整这些控件之间的空间,就会需要使用 Box 容器提供的透明的组件作为填充来填充控件之间的空间,从而达到调整控件之间的间隔空间的目的。Box 容器提供了 4 种透明的组件,分别是 rigid area、strut、glue、filler。Box 容器分别提供了不同的方法来创建这些组件。这四个组件的特点如下: Rigid area 是一种用户可以定义水平和垂直尺寸的透明组件; strut 与 rigid area 类似,但是用户只能定义一个方向的尺寸,即水平方向或者垂直方向,不能同时定义水平和垂直尺寸; 当用户将 glue 放在两个控件之间时,它会尽可能的占据两个控件之间的多余空间,从而将两个控件挤到两边; Filler 是 Box 的内部类,它与 rigid area 相似,都可以指定水平或者垂直的尺寸,但是它可以设置最小,最大和优先尺寸。 用 BoxLayout 进行布局 在了解了 BoxLayout 和 Box 容器的基本特点后,我们来看一下 BoxLayout 的优点,首先 BoxLayout 可以进行对控件进行垂直或者水平布局,同时 BoxLayout 使用起来较为简单,然而把它和 Box 容器相结合,就可以进行较为复杂的布局,达到同使用 GridBagLayout 的一样的效果,但是使用起来要简单方便多了。我们用按钮的布局作为例子来看怎样运用 BoxLayout 和 Box 容器进行布局: 图 1. 应用 BoxLayout 进行按钮布局例子 1 我们在布局中经常会碰到如图 1 所示要把按钮放在容器的两端,那么我们就可以给容器定义一个 BoxLayout 来布局按钮,我们在按钮 1 和按钮 2 之间放置一个不可见的 glue,如前面所提到的那样,glue 就会尽量挤占掉两个按钮之间的空间,从而将两个按钮放在两端。 图 2. 应用 BoxLayout 进行按钮布局例子 2 再来看图 2 的例子,我们经常会遇到要将两个按钮放在容器的右边,我们就可以给容器定义一个 BoxLayout, 先放一个不可见的 glue,这个 glue 会挤占左边的空间,从而将两个按钮推到右边, 在两个按钮之间再放一个 strut,它也是不可见的,它会把两个按钮分隔开。 BoxLayout 布局实例 在基于前面讨论的基础上,我们现在来看一个具体的运用例子,假设图 3 是我们需要完成的用户界面:……

阅读全文

邻接表实现无向图(C++)

很早以前写的代码了,贴出来做个备份吧。用向量来存储一条邻接链表,存储可连通值。实现了判断是否连通,添加边,添加顶点的功能。 UnDirectGraph.h UnDirectGraph.cpp 代码还算清晰,就不解释了,有问题留言反馈。谢谢。……

阅读全文

求整数1-N范围和为N的所有组合

看到的一道题,给出答案 问题:找出整数1~N范围和为N的所有集合,集合里的数不允许重复。 解答:递归吧 代码如下: 要是允许重复,也简单,将递归中的这句话改为: 同理,还可以解决类似给定一个数组,让求和为N的元素组合,只需要现将元素排个序,然后思路相同。  ……

阅读全文

并查集(C++实现)

并查集这个很有意思,并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。昨天看书看到了,然后用C++简单实现了下。在Dijkstra算法中,用来判断两个顶点是否在同一个集合里。 里面定义了两个类,都是并查集,一个是QuickFind,查找很快,一个是QuickUnion,合并较快。写了一些注释,有一些优化的提示.看代码吧,有什么问题指出来吧。 QuickFind的实现 QuickUnion的实现 参考文档(英文):UnionFind.pdf 工程代码下载:并查集Demo……

阅读全文

和 浅析

这两个转义字符最初学习C++的时候看到了,当时没多想,后来某一天突然想起来,回车不就是换行吗?这不是多此一举吗?今天又看到,索性查了下相关资料,整理一下,留作记录. 关于“回车”(carriage return)和“换行”(line feed)这两个概念的来历和区别。 在计算机还没有出现之前,有一种叫做电传打字机(Teletype Model 33)的玩意,每秒钟可以打10个字符。但是它有一个问题,就是打完一行换行的时候,要用去0.2秒,正好可以打两个字符。要是在这0.2秒里面,又有新的字符传过来,那么这个字符将丢失。 于是,研制人员想了个办法解决这个问题,就是在每行后面加两个表示结束的字符。一个叫做“回车”,告诉打字机把打印头定位在左边界;另一个叫做“换行”,告诉打字机把纸向下移一行(这句的意思是把纸向上拉,然后打印头就定位到了下一行),可以想象一下,这个打印头只能在一个固定的水平线上左右移动,而不能上下移动,我们通过移动纸来完成打印下一行。 不明白的我在youtube上找到一个这种打字机的演示视频,为了方便读者观看,我提供一个下载地址。 后来,计算机发明了,这两个概念也就被般到了计算机上。那时,存储器很贵,一些科学家认为在每行结尾加两个字符太浪费了,加一个就可以。于是,就出现了分歧。 Unix系统里,每行结尾只有”<换行>",即”\n”; Windows系统里面,每行结尾是”<换行><回车>",即”\n\r”; Mac系统里,每行结尾是”<回车>",不过mac基于unix,所以换行也应该是可以的。 一个直接后果是,Unix/Mac系统下的文件在Windows里打开的话,所有文字会变成一行;而Windows里的文件在Unix/Mac下打开的话,在每行的结尾可能会多出一个^M符号。这个如果你在windows下使用vim也会发现这个情况 用C++来说明 如:  最后只显示 bystander 而 leaver.me 背覆盖了 \n 是换行,系统会将其替换成回车+换行 把光标 先移到 行首 然后换到下一行 也就是 下一行的行首拉 则 显示 leaver.me bystander 一句话,这看起来是一个历史遗留问题…………

阅读全文

[E].Net 多线程指南

这是codeproject上的一个系列。我看完了。收获匪浅。可惜作者之后未能更新预想中的总结贴,多少有些可惜,不过。此系列非常非常不错。建议想学习.net多线程的看看。 1.net 多线程介绍 Introduction into threading in .NET 2.线程周期/线程优势/陷阱 Lifecycle of threads/Threading opportunities/Traps  3.线程同步 Synchronization 4.线程池 Thread Pools 5.UI中的线程应用 Threading in UIs (WinForms / WPF / Silverlight)……

阅读全文

C#中的Debug类

位于命名空间System.Diagnostics中 1.Debug.Print方法 2.Debug.WriteLine方法 3.TraceListener类 DelimitedListTraceListener创建的时候指定一个文件名,当Flush调用的时候,就被覆写到文件里。 第一个参数一个bool值,为真则输出。 5.Debug.Assert方法 如果表达式为false,则输出。……

阅读全文

C#多线程揭秘

文章略长。。。 Demo下载:Demo.Threading.zip 介绍 本文将通过一些例子来展示.net 中如何实现多线程,涉及到以下四部分。 1 .线程概念 2 .如何实现多线程 3 .如何确保线程安全 4 .死锁 什么是进程 一个进程就是一个可执行文件运行的操作系统上下文环境。它被用来分隔虚拟地址空间,线程,对象句柄(指向类似文件这样的资源的指针),以及环境变量,进程还有一些类似优先级类和最大内存分配的属性。 也就是说: 1 .一个进程就是一个包含资源的内存块。 2 .操作系统执行的一个单独的任务。 3 .一个正在运行的软件 4 .一个进程拥有一个/多个操作系统线程 一般的。一个进程最大可以是4GB的内存空间,这块内存是安全,私有,其他进程是无法访问的。 什么是线程 一个线程就是在一个进程里执行的一条指令流,所有的线程都在一个进程里执行,也就是一个进程可以包含多个线程。线程公用进程的虚拟地址空间。线程是操作系统的调度单元。一个线程的上下文由操作系统进行保存/恢复。 也就是说: 1 .一个线程是进程里的一条指令流。 2 .所有的线程在进程里。一个进程可以有多个线程 3 .一个进程的所有线程使用进程的虚拟地址空间。 什么是多线程 多线程指的是进程同时有多个线程活动。这可以通过时间片的线程模拟或是多cpu上的超线程来实现。可以提高性能。 多线程-为什么或是为什么不? 为什么多线程 1 .保持UI响应。 2 .提高性能(对于cpu密集型和I/O密集型的进程) 为什么不多线程 1 .过度使用降低性能 2 .代码复杂,增加设计时间,潜在的bug 线程池 线程池为你的程序提供了一个由操作系统管理的机制。在线程池里的都是后台线程。一个线程池线程在程序的前台线程都退出后,也会推出。每个进程一个线程池。默认情况下。每个处理器会为进程分配25个线程。但是可以通过SetMaxThreads 方法来改变。 .net 中的线程 在.net 中,线程可以通过下面6个方法来实现。 1 .Thread线程类 2 .Delegates委托 3 .Background Worker 4 .ThreadPool 线程池 5 .Task任务类 6 .Parallel并行类 下面的几部分里。我将逐一展示实现方法。 简而言之,多线程就是通过使程序同时运行多个任务来最大化计算机能力,同时能够保持UI响应。下图是一个例子的图示。 代码 提供的源码是一个简单的WinForm程序。模拟了.net中委托,线程类和Background Worker三种方法。 程序异步执行一个繁重的操作,这样UI就不会无响应。三个方法都是模拟的。 这个“繁重”的操作 真实的开发中,这个繁重的操作从轮询数据库到流媒体操作都可以。基本上可以是任何事情。源码里面是向一个字符串追加值。String是不能变的。追加的时候,新的字符串变量会被创建,旧的会被丢弃,这是由CLR处理的。如果做很多次这个操作,是很耗资源的。这也是为什么我们使用Stringbuilder.Append 来代替这个操作。通过调整界面中的次数。可以通知追加的次数。 后面我们有一个Utility泪,有一个LoadData() 方法。类里面也有一个和LoadData() 有着同样签名的委托 同步调用 当点击Get Data Sync按钮的时候。操作和UI在同一个线程里,因此阻塞了UI线程。因此。UI线程会未响应 异步调用 使用委托(异步编程模型) 如果你选择了“Delegates”单选按钮,那么LoadData()方法就会通过使用委托来异步调用。首先通过utility.LoadData(). 的地址初始化delLoadData 类型,然后调用委托的BeginInvoke()方法。在.net的世界里。任何一个有着BeginXXX和EndXXX名字的方法都是异步的。比如delegate.Invoke()将会在同一个线程里调用方法。而delegate.BeginInvoke()则会另开一个线程调用。 BeginInvoke()有三个参数 1 .传递给Utility.LoadData()方法的参数 2 .回调方法的地址 3 .对象的状态 回调 一旦我们开了一个线程执行一些操作,我们就想知道操作正在发生些什么,换句话说。我们需要当操作完成的时候我们能够收到通知。有三种方法可以知道一个操作是否完成。 1 .回调 2 .轮询 3 .等待直到完成 在我的源码里,我们使用回调方法来捕获线程的完成。回调只需要在调用BeginInvoke的时候把回到函数的名字传递进去。这会告诉线程当你做完工作以后调用这个回调方法就好了。 一旦一个独立线程里的一个方法启动。你也许关心也许不关心方法的返回值,如果一个方法没有返回值,那么可以叫做“触发然后忘记的调用”,这种情况下就不需要回调函数了。这里callback直接传入null就可以了。 在我们的例子中,我们需要一个回调方法,因此,哦们需要传递回调方法的名字到参数里。这里我们的回调方法的名字就叫做CallBack(),纯属巧合。 回调方法的签名都是void MethodName(IAsyncResult asyncResult). IAsyncResult包含了关于线程的一些必要的信息,返回的数据可以像下面这样提取。 而轮询的方法(本例没有使用)则是像这样 等待直到完成,如名所示,就是等待直到完成。 更新UI 既然我们已经捕获了操作结束,并且取回了LoadData()的结果。我们需要用结果来更新UI,但是有个问题。文本框需要在UI线程里更新,结果在回调里取到了。回调和他启动的时候是一个线程(他是由新开的线程启动的)。因为UI线程和回调不是同一个线程。换句话说。文本框不能像下面这样更新。 回调里执行这一行将会导致一个跨线程的系统异常。我们需要在后台线程和Ui线程之前构建一个桥。来更新文本框的值。可以通过使用Invoke()或是BeginInvoke()方法。 我定义了一个方法来更新UI 对上面的方法定义一个委托 如下调用BeginInvoke()方法。 需要注意的是一旦一个线程通过委托启动。它就不能取消,暂停,或是终止,我们无法控制那个线程。 使用Thread线程类 同样的操作可以是哟哦那个Thread类来完成。这个类的优点是你可以对操作有更多的控制,比如暂停/取消操作,类在System.Threading命名空间里。 我们有一个私有的方法LoadData(),他是Utility.LoadData()方法的一个包装。 这样做是因为 Utility.LoadData() 需要一个参数。而我们需要一个ThreadStart委托,这个委托没有参数。 这个委托没有参数,为了防止我们需要传递参数,我们可以使用有参的ThreadStart委托,不幸的是,这个委托只能把object作为参数,而我们需要一个字符串所以需要类型转换。 是的。Thread泪可以对线程有更多的控制。中断。终止,获取线程状态。 使用BackgroundWorker 这个类是一个组件,可以使得线程使用更简单,这个BackgroundWorker类的主要特点就是可以异步的报告进度,这就可以用来更新状态栏,保持UI可视化的更新进度 为了完成操作,我们需要把下面两个属性设置为true,缺省时false • WorkerReportsProgress • WorkerSupportsCancel 这个类有三个主要的事件DoCount, ProgressChanged, RunWorkerCompleted 初始化的时候需要注册这三个事件……

阅读全文

操作系统的死锁和内存管理

这部分是最后一部分笔记。《现代操作系统》第三版的笔记就这样了。 死锁; 把需要排他性使用的对象称为资源,资源分为可抢占的和不可抢占的。可抢占资源可以从拥有它的进程中抢占而不会具有任何副作用。存储器就是可抢占的。不可抢占资源是指在不引起相关的计算失败的情况下,无法把它从占有她的进程处抢占过来。比如CD刻录机,如果一个进程开始刻盘,突然分配给CD刻录机到另一进程,就会划坏CD盘。死锁会发生在不可抢占资源中 死锁的规范定义:如果一个进程集合中的每个进程都在等待只能由该进程集合中的其他进程才能引发的事件,那么,该进程集合就是死锁的。 死锁的四个必要条件 1.互斥条件。每个资源要么已经分配给一个进程,要么就是可用的。 2.占有和等待条件,已经得到了某个资源的进程可以再请求新的资源。 3.不可抢占条件,已经分配给一个进程的资源不可强制性的被抢占,他只能由占有她的进程显式的释放。 4.环路等待条件。死锁发生时,系统中一定有友两个/多个进程组成的一条回路,该环路中的每个进程都在等待着下一个进程所占有的资源。 死锁处理的四种策略 1.忽略该问题,如果可以忽略。则忽略 2.检测死锁并恢复,让死锁发生,检测他们是否发生,一旦发生。采取行动。 3.仔细对资源进行分配。动态的避免死锁。 4.通过破坏引起的四个必要条件之一。防止死锁发生。 银行家算法就是对每个请求进行检查。检查如果满足这一请求是否会达到安全状态,或是,那么满足这请求,若否。就推迟这一请求的满足。为了看状态是否安全。类似于银行家投资。看自己是否有足够的资源满足客户。如果可以。就认为投资是可以收回的。接着检查最接近最大限额的一个客户。如果所有投资最终都被收回。则该状态安全。 通信死锁:两个/以上的进程发送消息通信。A向B发送请求信息,然后阻塞直到B回复。假设请求信息丢失,A将阻塞等待回复。B则阻塞等待一个向其发送命令的请求。则发生死锁。他不能通过对资源排序/安排调度来避免,因此。采用了超时来中断通信死锁。 活锁:两个进程A和B,A获得1.B获得2.轮询请求对方的。没有进程被阻塞。看起来像是死锁发生了。就叫做活锁。 内存管理 每个linux进程都有一个地址空间,逻辑上有三段组成:代码。数据和堆栈段。代码段包含了形成程序可执行代码的机器指令。通常是只读的。是由编译器把源码转换成机器码形成的。 数据段包含了所有程序变量。字符串。数字和其他数据的存储。由两部分,初始化数据和未初始化数据。后者即为BSS,符号起始块。加载后被初始化为0.数据段可以修改。可以增加数据段的大小。 第三段是栈段。大多数机器里。从虚拟地址空间的顶部/附近开始。并且向下生长。 linux内存由三部分组成。前两部分是内核和内存映射,被钉在内存中。页面从不换粗。内存的其他部分,被划分为页框。每个页框都可以包含一个代码。数据或栈页面。 window如何知道系统配置的细节呢。答案就是windows会挂载一种特殊的文件系统,其为小文件做了优化,到名字空间,也就是注册表。注册表被阻止成了不同的卷,称作储巢。hive。一个叫做system的储巢会在系统启动时。装入内存。这里面包含了驱动什么设备工作。什么软件要初始化。那些变量等等。……

阅读全文

操作系统中的输入输出

输入输出 I/O硬件: I/O设备分为两类:块设备和字符设备,块设备吧信息存储在固定大小的块中,每个块有自己的地址,传输以块为单位,每个块都能独立于其他块读写,硬盘,CD-ROM和USB盘都是常见的块设备。字符设备是以字符为单位发送和接收一个字符流,而不考虑任何块结构,字符设备不可寻址,也不寻道,打印机,网络几口,鼠标,以及大多数与磁盘不同的设备都可看作是字符设备。 I/O设备一般由机械部件和电子部件两部分组成,通常分开处理,实现模块化和通用设计,电子部件称作设备控制器/适配器,在个人计算机上,通常以主板上的芯片的形式出现,或者以插入PCI的印刷电路板的形式出现。控制器卡上通常有一个连接器,通向设备本身的电缆可以插入到这个连接器中, 控制器的任务是吧串行的位流转换成字节块,并进行必要的错误校正工作,字节块通常首先在控制器内部的一个缓冲区中按位进行组装,然后再对校验和进行校验并证明字节块没有错误后再将它复制到主存中。 每个控制器都有几个寄存器用来和cpu通信,通过写入这些寄存器,操作系统可以命令设备发送数据等等操作。 1.内存映射io 将所有控制寄存器映射到内存空间中,每个寄存器被分配一个唯一的内存地址,并且不会有内存被分配这一地址,这样的系统称为内存映射I/O,通常位于地址空间的顶端。使用内存映射io,设备控制器只是内存中的变量,c语言可以和其他变量一样寻址,这样,I/O设备驱动程序就可以采用c语言编写。 2.DMA 无论CPU是否具有内存映射I/O,他都需要寻址设备控制器以便和他们交换数据,但浪费eficpu时间,所以经常使用直接存储器存储。可独立于cpu访问地址总线。 没有DMA的时候,首先控制器从磁盘驱动器串行的一位一位的读一个块,直到将整块信息放入控制器的内存缓冲区中,接着,他计算校验和,以保证没有读错误发生,然后控制器产生一个中断,当操作系统开始运行时,它重复地从控制器的缓冲区中一次一个字节/一个字的读取该块的信息,并将其放入内存中。 当有DMA的时候,首先CPU通过设置DMA控制器的寄存器对它进行编程,所以DMA控制器知道将什么数据传送到什么地方,(第1步)DMA控制器还要向磁盘控制器发送一个命令,通知他从磁盘读数据到其内部的缓冲区中,并且对校验和进行检验,如果磁盘控制器中的缓冲区中的数据是有效的的。那么DMA开始 DMA控制器通过在总线上发出一个读请求到磁盘控制器而发起DMA传送(第2步),这一读请求和其他一样,并且磁盘控制器并不关心是来自DMA还是CPU,一般情况下,要写的内存地址在总线的地址线上,所以磁盘控制器从内部缓冲区中读取下一个字的时候,她知道要写的什么地方,写到内存是另一个标准总线周期,(第3步) 当写操作完成时,磁盘控制器在总线上发起一个应答信号到DMA(第4步),于是DMA控制器部增要使用的内存地址,并且步减字节计数,如果字节计数仍然大于0,则从父2-4步。完成后产生中断告诉cpu,操作系统开始工作时,数据已经在内存中了。 中断: 将机器留在一个明确状态的中断称为精确中断,四个特征,1.PC保存在一个已知的地方。2.PC所指向的指令之前的所有指令都已经完全执行。3.PC所指向的指令之后的所有指令都没有执行。4.PC所指向的指令的执行状态是已知的。注意,对于PC所指向的指令以后的指令,并没有禁止他们开始执行,而只是要求在中断发生之前必须撤销他们对寄存器或内存所做的任何修改。 I/O软件: 设计I/O软件时一个关键的点就是设备独立性,意思是我们可以访问任意I/O设备而无需事先指定设备。也就是对于不同的I/O硬件。同一段程序是可以的。 具有标准接口的驱动程序的工作方式如下:对于每一种设备类型,例如磁盘和打印机。操作系统定义一组驱动程序必须支持的函数,对于磁盘而言,这些函数自然的包含读和写,除此之外还包含开启和关闭电源,格式化以及其他与磁盘有关的事情。驱动程序通常包含一张表格,这张表格具有针对这些函数指向驱动程序自身的指针。当驱动程序装载时,操作系统记录下这张函数指针表的地址。所以当操作系统需要调用一个函数时,可以通过表格发出间接调用。这张函数指针表定义了驱动程序与操作系统其他部分之间的接口。 **双缓冲:**当第二个缓冲区正在复制用户空间的时候,第一个缓冲区用来接收新的字符。以这样的方法。两个缓冲区轮流使用。称为双缓冲。 磁盘臂调度算法: 读/写一个磁盘块需要时间:1.寻道时间(将磁盘臂移动到适当的柱面上所需的时间)2.旋转延迟(等待适当扇区旋转到磁头下所需的时间)。3.实际数据传输时间。 一个磁盘子系统具有如下特性:当一个写命令发给它时,磁盘要么正确地写数据,要么什么也不做,让现有的数据完整无缺的留下,这样的系统称为稳定存储器,并且是在软件中实现的。目标是不惜一切代价保持磁盘的一致性。 **时钟:**两种。1种是直接接到电源线上。就可以每个电压周期产生一个终端。现在比较少。另一种是由晶体振荡器,计数器和存储寄存器三个构成。当把一块石英晶体适当的切割并且安装到一定的压力之下时就可以产生非常精确的周期性信号。时钟启动时,存储寄存器的值被复制到计数器中,每一个脉冲使计数器-1,直到为0,产生中断。……

阅读全文