熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

用Scala實現Qt QWidget對象的Eventable接口

2013-11-23 18:49:26  來源: Java核心技術 
    今天我們來講講用Scala實現Qt QWidget對象的Eventable接口這個Eventable接口是我項目中常用的一個東西Scala強調FP但是Qt Jambi本身是基於OOP的事件重載需要在類裡面進行在前面展示的例子中大家可以看到經常會這樣展開一個類去重載
    new QLabel {
    override def xxxxEvent  }  這種聲明的方法多了其實很容易讓人覺得不規范而且閱讀也是不易所以我萌生了讓將js那種聲明事件風格的代碼加入至此js是一個可以很fp的語言而scala也是這不是一個很好的決定嗎?獻上具體的代碼
    package yourporjectpackage
    import llectionmutable{ ArrayBuffer HashMap }  import comtrolltechqtgui_  import re_  import reQEvent  import comtrolltechqtQSignalEmitter_  import comagiersmvcBase  /*
    * Base類裡面封裝了的是對於Java和Scala既有類的方法擴展使用的是隱式混入的方式不會改變對象本身
    * 如
    * onClicktoEventName => click
    * 中文字encode => url encode
    * 繁體字encodeSys => 這個是根據客戶端操作系統默認的字符編碼進行urlencode
    * 繁體字toSimplified => 繁體轉簡體
    * 簡體字toTraditional => 簡體轉繁體
    * hello_worldtoCamelCase => HelloWorld
    * good guysdump(temptxt) => 將字符串內容輸入到一個io文件中
    * hello worldmd => 將字符串md加密
    */
    trait Eventable[T < QWidget] extends QWidget with Base {
    // 定義閉包的格式聲明
    // 凡是在Eventable裡使用閉包的類型應該首先使用Fn類型
    // 修改閉包類型應該在此修改而不在具體聲明的地方修改
    type Fn = EventHandle => Unit
    // 定義一個event的類型組合
    // 這個代表的實際上是String > Fn或者(String Fn)
    type Ev = (String Fn)
    /**
    * 事件接管對象
    * 用於接管聲明事件時的閉包處理並臨時寄存該閉包中的各種狀態和變量
    * @TODO 要逐漸增加他的寄存和讀取的接口
    * @author Janpoem
    */
    sealed case class EventHandle(val widget T val event QEvent) {
    // 這個是用來獲取該widget執行event時的狀態的
    private var _break = false
    // 以下
    def isBreak = _break
    def isBreak_=(is Boolean) = _break = is
    def break(fn EventHandle => Boolean) = isBreak = fn(this)
    }


    /**
    * 閉包的存放容器
    * 允許將閉包作為一個隊列存放並在fire的時按照隊列先後順序執行
    * @author Janpoem
    */
    sealed case class FnContainer(fn Fn) {
    private var fns = ArrayBuffer[Fn](fn)
    def +(fn Fn) thistype = {
    fns += fn
    this
    }
    def fire(widget T event QEvent) EventHandle = {
    val handle = EventHandle(widget event)
    fnsforeach(_(handle))
    handle
    }
    }
    // 定義Qt標准時間類型轉換到當前類的助記名
    // name統一使用小寫
    // @TODO 要不斷增加QEventType的內容
    private val _eventsMap = HashMap[QEventType String](
    QEventTypeShow
    > show
    QEventTypeMouseButtonPress
    > click
    QEventTypeMouseButtonDblClick > doubleclick
    QEventTypeFocusIn
    > focus
    QEventTypeFocusOut
    > blur
    QEventTypeEnter
    > enter
    QEventTypeLeave
    > leave
    )
    // 事件
    private val _events = HashMap[String FnContainer]()
    // 傳入Qt的QEventType獲取其在Eventable內部的快捷助記名
    def eventTypeName(_type QEventType) Option[String] = _eventsMapget(_type)
    // 裝載事件
    // waddEvent(show handle => { /*  */ })
    def addEvent(s String fn Fn) thistype = {
    val name = stoEventName
    if (!thishasEvent(name))
    _events(name) = FnContainer(fn)
    else
    _events(name) + fn
    this
    }
    // waddEvent(click > { handle => println(handleevent) })
    def addEvent(event Ev) thisthistype = thisaddEvent(event_ event_
    def addEvents(events Ev*) thistype = {
    eventsforeach(thisaddEvent(_))
    this
    }


    // 判斷是否存在事件
    def hasEvent(name String) Boolean = ntains(nametoEventName)
    // Qt事件覆蓋
    override def event(event QEvent) Boolean = {
    eventTypeName(event`type`()) match {
    case Some(name) =>
    if (thishasEvent(name)) {
    val handle = _events(name)fire(thisasInstanceOf[T] event)
    }
    case _ =>
    }
    superevent(event)
    }
    }  
    這個Eventable只是一個很初步的封裝只是針對所有的QWidget適用我還有好些想法比如延時事件激活定時事件循環並且希望能對QObject進行全部的適用而對於Qt的信號槽自然也要兼容想法太多可惜時間太有限先用著吧能好像寫js一樣寫事件聲明該知足了
    下面奉上使用的代碼
    class Widget extends QWidget with Eventable[QWidget]
    val w = new Widget()  waddEvent(onClick handle => {
    println(單擊了!)  })  waddEvents(
    show > { handle =>
    println(窗口顯示了
    }
    doubleClick > { handle =>
    println(雙擊了!
    }  )


From:http://tw.wingwit.com/Article/program/Java/hx/201311/25803.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.