文档章节

新手上路,各种记录: Scala Swing

aiasfina
 aiasfina
发布于 2012/12/28 09:54
字数 1136
阅读 510
收藏 1

一直都想做一下 C/S,但是没什么机会。这几天趁着有空玩了一下唯一接触过一点的 Swing,顺便总结总结。话说,绝大部分时间花在了代码着色上了,结果无功而返哈,笑:)

话说,这篇文章就在这连半成品都不算的小应用上写的呢。中间一直想换成 docat webapp 来写,担心出了神马毛病整篇文章就都完了。:P

首先给个应用截图:

在此输入图片描述

这是一个即时预览的 Markdown 编辑器,功能非常的少,开发的时间也没两天,基于 Scala Swing。

#####下面是代码结构:

在此输入图片描述

你会发现我几乎把所有的组件都拆开了,这是因为因为个人比较喜欢把组件描述放在父容器中,而组件的逻辑都独立出来。但是这样导致了一个问题,我稍后再讲。


###Swing 多线程

首先要说的是一个很不起眼的地方,那就是 Swing 多线程。

基于 Scala 如果不用多线程就没啥意思了,但很不凑巧的是 Swing 本身是单线程的。有关UI、事件派发的操作都需要由 Swing 分发。Java 的 invokeLater 在 Scala 的 Actor 上是行不通。

但是,我们可以设置 Actor 调度器来做到这点:继承 Actor 的 class 或 object 需要手动覆盖调度器。

<!-- lang: scala -->
object EventMonitorAct extends Actor {

    override val scheduler = new SchedulerAdapter {
        def execute(fun: => Unit) { Swing.onEDT(fun) }
     }
 }

另外acotr {} 方法是默认使用父调度器的,而我们在入口处就已经将初始化方法交给 Swing调度器来处理了:

<!-- lang: scala -->
object Marky {
    def main(args: Array[String]) = Swing.onEDT { startUp(args) }

    def startUp(args: Array[String]) { //... }
 }

其实我是在看到 invokeLater 才知道 Swing 单线程这回事的(典型零基础),至于 Scala 调度器?那是翻 Scala Swing 源码翻出来的,所以或许大概极有可能不是这样 = =

###Reactor/Publisher

Reactor/Publisher 是 Scala Swing 的亮点,非常简便的使用方式和扩展能力。只要在任何对象 混入(mixin) Reactor,你就可以监听组件的事件了。

但是,有一点令我很不爽,这种模型会侵入到各个组件,我需要把 Publisher 传到 Reactor 中。比如:在菜单里点击打开文件,然后将内容插入到编辑区中并改变标题。那么我需要在 Frame 和 EditorPane 中监听 MenuBar 的事件,或者将它们都写在一起。(如果你有其他方法还请告知..)

然后,就有下一个题目了。

###事件订阅/广播

在此输入图片描述

这是一个通用模块,可以用在任何对象。当发布者向事件中心发送一个消息,所有的订阅这都会得到这个消息并选择处理或丢弃。

拿上面那个例子来说:当在 MenuBar 中点击打开文件,该组件就只负责打开一个文件选择窗口并得到选中文件对象,MenuBar 只需做到这里就完成了它的职责,然后向事件中心发送一个名为 openfile 的消息并附带一个 File 对象的数组。只要任何一个订阅者响应这个 openfile 消息就能获得 File对象并且自动调用相应代码。

####菜单 MenuDef

<!-- lang: scala -->
    // 混入 Publishable 
trait MenuDef extends I18N with Publishable { this: MenuBar =>
   /*
    * File menu
    */
  val _new = new MenuItem(t("new"))
  val _open = new MenuItem(t("open"))
  val _save = new MenuItem(t("save"))
  val _quit = new MenuItem(t("quit"))

  contents += new Menu(t("file")) {
      contents += _new
      contents += _open
      contents += _save
      contents += new Separator
      contents += _quit
    }

    listenTo(_new, _open, _save, _quit)
    reactions += {
       case ButtonClicked(`_open`) =>
           val chooser = new FileChooser
           chooser.showOpenDialog(this)
           val file = chooser.selectedFile
           if (file != null)
              fire('openfile, Array(MdFile(file)))    //发布 openfile消息,附带参数数组
    }
}

####编辑器 Editor.scala:

<!-- lang: scala -->
class Editor extends EditorPane with I18N with Publishable with Listenable { self =>
    // 注册该监听器
    register()
    //订阅 openfile 消息
    on('openfile) {
        (event) =>
            {
                // 获取并读入文本
                val file = event.args.first.asInstanceOf[MdFile]
                file >> (this.text = _)
            }
     }
}

####主窗口 Frame:

<!-- lang: scala -->
val frame = new Frame with Listenable {
    title = "Marky"
    
    menuBar = new MenuBar with MenuDef {
        border = Swing.EmptyBorder(2, 3, 0, 3)
    }
    visible = true

    register()
    on('openfile, 'savefile) {
         (event) =>
              val file = event.args.first.asInstanceOf[MdFile]
              title = file.name + " - Marky"
      }
  }

最后是 MarkyEvent.scala ,大概有70行左右。 不过这 2B 编辑器要自己一行行缩进,我就不再这贴了=。 =

###Markdown2HTML

没啥好说的,一个多线程的 Actor(即非Swing调度器)做转换,一个模块负责订阅编辑区内容,发送并接受字符串,然后修改显示区内容。

###I18N 更没啥好说的了,只是为了不在代码中写中文而已。在这里个人也建议尽量不要在代码中写中文的好。


没了。不玩了。回去继续捣鼓 WEB。

© 著作权归作者所有

共有 人打赏支持
aiasfina
粉丝 33
博文 3
码字总数 1515
作品 0
深圳
程序员
加载中

评论(2)

aiasfina
aiasfina

引用来自“千叶”的评论

是我的菜

:)
千叶
千叶
是我的菜
机器学习算法 Java 库 Smile 1.5.0 发布,引入新特性

机器学习算法 Java 库 Smile 1.5.0 已发布。该版本引入了新特性和修复 bug,改进了对 Windows 的支持,具体如下: DataFrame New Shell for Mac and Linux Shell improvement for Windows Ou...

局长
2017/11/23
1K
4
在Google App Engine上创建你的Java/Scala项目

GAE(Google App Engine)是Google推出的服务器托管项目,目前支持Python、Java、Go(为什么没有传说中的G-SPOT?)三种语言。GAE的免费版本有很多限制,但是可是很稀有的可以托管Java项目的服...

戴威
2011/09/06
994
3
杨博/stateless-future

Stateless Future is a set of DSL for asynchronous programming, in the pure functional favor. Usage import scala.concurrent.duration._import scala.util.control.Exception.Catcheri......

杨博
2014/04/19
0
0
python-判断2个IP地址是否属于同一网段

python新手上路,以前主要搞网络路由交换这一块,现在用python做一下简单的关于网络的脚本,记录一下学习历程。 1个IP是否属于1个网段,需要3前提条件,2个IP,1个子网掩码。 例如192.168.1...

bang251026052
2017/07/08
0
0
Scala 2.8 发布第一个候选版

今天是ScalaDay 2010的第一天,同时期盼已久的Scala2.8的第一个候选版也已经发布。Scala 2.8 包含了大量bug修正以及增加了许多新的特性。 新特性: 集合类库重新设计 新的数组实现,允许多态...

红薯
2010/04/16
623
1

没有更多内容

加载失败,请刷新页面

加载更多

5whys分析法在美团工程师中的实践

前言 网站的质量和稳定性对于用户和公司来说至关重要,但是在网站的快速发展过程中,由于各种原因导致事故不可避免的发生,这些大大小小的事故对公司难免会造成一些负面的影响,为了避免同类...

Skqing
23分钟前
1
0
Android 接收监听开机完成,并且开机自启动

1,定义一个广播接收者的类 ,并重写抽象方法 public class BootCompleteReceiver extends BroadcastReceiver 2,在Androidmanifest 注册 <receiver android:name=".receiver.BootCompleteRece......

lanyu96
27分钟前
2
0
小程序记录

1、button的边框、角等需要在伪元素after修改去除

originDu
29分钟前
1
0
微博什么技术啊……还说支持八个明星并发出轨,结果…

是的,大家可能都知道了,女神张靓颖结婚了。。 我去,写错了,是————赵丽颖。 为什么我头脑一瞬间出现的是张靓颖,作为一个码农,技术宅,拼音缩小都是 ZLY,博主我真有点傻傻分不清楚了...

Java技术栈
29分钟前
10
0
模块化

1,什么是模块化? 模块化是指将一个复杂的系统分解为多个模块,方便编码。 2,为什么要用模块化? 降低复杂性,降低代码耦合度,部署方便,提高效率。 3,模块化的好处? a,避免命名冲突,减少...

羊皮卷
30分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部