文档章节

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

aiasfina
 aiasfina
发布于 2012/12/28 09:54
字数 1136
阅读 501
收藏 1
点赞 0
评论 2

一直都想做一下 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
博文 2
码字总数 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 ⋅ 4

在Google App Engine上创建你的Java/Scala项目

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

戴威 ⋅ 2011/09/06 ⋅ 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

Scala swing和FX

Swing是老了。虽然Scala也提供了swing的支持,但是没有设计器,纯粹使用代码,灵活性比较差,当然也是可以使用的。我个人还是比较倾向使用javaFX。javaFX什么都可以自己绘制,提供了形状的抽...

崔钢 ⋅ 2011/01/12 ⋅ 1

python-判断2个IP地址是否属于同一网段

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

bang251026052 ⋅ 2017/07/08 ⋅ 0

Scala 2.8 发布第一个候选版

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

红薯 ⋅ 2010/04/16 ⋅ 1

red5无法用ip地址打开

新手学习这个red5,解压后修改了red5.properties的ip,但是只能用localhost:5080访问到主页,不能用ip:5080访问,端口显示是打开的,就是访问不到?求解??新手上路用oflaDemo测试也一样,l...

漠水情 ⋅ 2017/12/15 ⋅ 1

Scala 2.8.0 Final 释出

经历了7个RC版本,Scala终于迎来了2.8.0的Final版本,这是修正了大量Bug和增强了若干特性的最终版本。 注意,相关的编辑器和IDE也要做相应的更新,如Scala IDE for Eclipse,目前已更新至2.8...

曾建凯 ⋅ 2010/07/15 ⋅ 0

老猪/ScalaConsole

ScalaConsole Reloaded (V2.0) ScalaConsole 是什么 ScalaConsole是Scala语言REPL的图形界面替代者。 为什么需要 ScalaConsole 命令行REPL的编辑功能有限,只能基于行来进行编辑,如果输入错...

老猪 ⋅ 2015/02/11 ⋅ 0

记录python列表内存释放

今天用python写了个小程序,从一堆文件中读取字段,生成xml,由于新手上路,折腾吐了,最恶心的是电脑被搞死机了两次,起初以为电脑系统有点问题,知道后来运行那段py程序的时候发现python的...

浪子_仗剑走天涯 ⋅ 2014/05/08 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

开启Swarm集群以及可视化管理

在搭建的两台coreos服务器上开启swarm集群 前置条件: docker均开启2375端口 同一个局域网内 主服务器上安装Portainer容器 安装Portainer容器执行: docker run -d -p 9000:9000 --restart=a...

ykbj ⋅ 18分钟前 ⋅ 0

单例设计模式

1、单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例 2、饿汉式单例类 在这个类被加载时,静态变量instance会被初始化,此时类的私有构造子会被调用 饿汉式是典型...

职业搬砖20年 ⋅ 23分钟前 ⋅ 0

前端基础(四):前端国际规范收集

字数:1142 阅读时间:5分钟 前言 由于前端技术的灵活性和杂乱性,导致网上的许多解决方案不够全面甚至是完全错误,容易起到误导作用。所以,我对搜索到的解决方案往往是存疑态度。那么,如何...

老司机带你撸代码 ⋅ 25分钟前 ⋅ 0

Failed to open/create Network-VirtualBox Host-Only

虚拟机版本 : Oracle Vm VirtualBox 5.2.12 报错时机:开网卡二,重启虚拟机报错 "Failed to open/create the internal network 'HostInterfaceNetworking-VirtualBox Host-Only Ethernet Ada......

p至尊宝 ⋅ 28分钟前 ⋅ 0

三分钟学会如何在函数计算中使用 puppeteer

摘要: 使用 puppeteer 结合函数计算,可以快速的构建弹性的服务完成各种功能,包括:生成网页截图或者 PDF、高级爬虫,可以爬取大量异步渲染内容的网页、模拟键盘输入、表单自动提交、登录网...

阿里云云栖社区 ⋅ 31分钟前 ⋅ 0

springMVC接收表单时 Bean对象有Double Int Char类型的处理

前台ajax提交表单price为double类型 后台controller就介绍不到 400错误 前台 实体类: public class ReleaseMapIconConfig{ private String id; private long maxValue; private long minVal......

废柴 ⋅ 34分钟前 ⋅ 0

ZOOKEEPER安装

工作需要在ubuntu上配置了一个zookeeper集群,有些问题记录下来。 1. zookeeper以来java,所以首先要安装java。但是ubuntu系统有自带的jdk,需要通过命令切换java版本: $ sudo update-alter...

恰东 ⋅ 37分钟前 ⋅ 0

linux 进程地址空间的一步步探究

我们知道,在32位机器上linux操作系统中的进程的地址空间大小是4G,其中0-3G是用户空间,3G-4G是内核空间。其实,这个4G的地址空间是不存在的,也就是我们所说的虚拟内存空间。 那虚拟内存空间...

HelloRookie ⋅ 37分钟前 ⋅ 0

myatis #{}与${}区别及原理

https://blog.csdn.net/wo541075754/article/details/54292751

李道福 ⋅ 40分钟前 ⋅ 0

三分钟学会如何在函数计算中使用 puppeteer

摘要: 使用 puppeteer 结合函数计算,可以快速的构建弹性的服务完成各种功能,包括:生成网页截图或者 PDF、高级爬虫,可以爬取大量异步渲染内容的网页、模拟键盘输入、表单自动提交、登录网...

猫耳m ⋅ 41分钟前 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部