詳解 Qt QWidget對象的Eventable接口 (Scala實現(xiàn))
Qt QWidget對象的Eventable接口(Scala實現(xiàn))是本文將要介紹的內(nèi)容,Scala編程語言近來抓住了很多開發(fā)者的眼球。如果你粗略瀏覽Scala的網(wǎng)站,你會覺得Scala是一種純粹的面向?qū)ο缶幊陶Z言,而又無縫地結(jié)合了命令式和函數(shù)式的編程風格。
這個Eventable接口是我項目中常用的一個東西,scala強調(diào)FP,但是Qt Jambi本身是基于OOP的,事件重載需要在類里面進行。
在這個例子中,( http://my.oschina.net/janpoem/blog/7017 )大家可以看到經(jīng)常會這樣展開一個類去重載:
- new QLabel {
- override def xxxxEvent
- }
這種聲明的方法多了其實很容易讓人覺得不規(guī)范,而且閱讀也是不易。所以我萌生了讓將js那種聲明事件風格的代碼加入至此,js是一個可以很fp的語言,而scala也是,這不是一個很好的決定嗎?獻上具體的代碼:
- package yourporject.package
- import scala.collection.mutable.{ ArrayBuffer, HashMap }
- import com.trolltech.qt.gui._
- import com.trolltech.qt.core._
- import com.trolltech.qt.core.QEvent
- import com.trolltech.qt.QSignalEmitter._
- import com.agiers.mvc.Base
- /*
- * Base類里面封裝了的是對于Java和Scala既有類的方法擴展,使用的是隱式混入的方式,不會改變對象本身。
- * 如
- * "onClick".toEventName => click
- * "中文字".encode => url encode
- * "繁體字".encodeSys => 這個是根據(jù)客戶端操作系統(tǒng)默認的字符編碼進行urlencode
- * "繁體字".toSimplified => 繁體轉(zhuǎn)簡體
- * "簡體字".toTraditional => 簡體轉(zhuǎn)繁體
- * "hello_world".toCamelCase => HelloWorld
- * "good guys".dump("temp.txt") => 將字符串內(nèi)容輸入到一個io文件中
- * "hello world".md5 => 將字符串md5加密
- */
- trait Eventable[T <: QWidget] extends QWidget with Base {
- // 定義閉包的格式聲明
- // 凡是在Eventable里使用閉包的類型,應(yīng)該首先使用Fn類型
- // 修改閉包類型,應(yīng)該在此修改,而不在具體聲明的地方修改
- type Fn = EventHandle => Unit
- // 定義一個event的類型組合
- // 這個代表的實際上是String -> Fn或者(String, Fn)
- type Ev = (String, Fn)
- /**
- * 事件接管對象
- * 用于接管聲明事件時的閉包處理,并臨時寄存該閉包中的各種狀態(tài)和變量
- * @TODO 要逐漸增加他的寄存和讀取的接口
- * @author Janpoem
- */
- sealed case class EventHandle(val widget : T, val event : QEvent) {
- // 這個是用來獲取該widget執(zhí)行event時的狀態(tài)的
- private var _break = false
- // 以下
- def isBreak = _break
- def isBreak_=(is : Boolean) = _break = is
- def break(fn : EventHandle => Boolean) = isBreak = fn(this)
- }
- /**
- * 閉包的存放容器
- * 允許將閉包作為一個隊列存放,并在fire的時,按照隊列先后順序執(zhí)行。
- * @author Janpoem
- */
- sealed case class FnContainer(fn : Fn) {
- private var fns = ArrayBuffer[Fn](fn)
- def +(fn : Fn) : this.type = {
- fns += fn
- this
- }
- def fire(widget : T, event : QEvent) : EventHandle = {
- val handle = EventHandle(widget, event)
- fns.foreach(_(handle))
- handle
- }
- }
- // 定義Qt標準時間類型轉(zhuǎn)換到當前類的助記名
- // name統(tǒng)一使用小寫
- // @TODO 要不斷增加QEvent.Type的內(nèi)容
- private val _eventsMap = HashMap[QEvent.Type, String](
- QEvent.Type.Show -> "show",
- QEvent.Type.MouseButtonPress -> "click",
- QEvent.Type.MouseButtonDblClick -> "doubleclick",
- QEvent.Type.FocusIn -> "focus",
- QEvent.Type.FocusOut -> "blur",
- QEvent.Type.Enter -> "enter",
- QEvent.Type.Leave -> "leave"
- )
- // 事件
- private val _events = HashMap[String, FnContainer]()
- // 傳入Qt的QEvent.Type,獲取其在Eventable內(nèi)部的快捷助記名
- def eventType2Name(_type : QEvent.Type) : Option[String] = _eventsMap.get(_type)
- // 裝載事件
- // w.addEvent("show", handle => { /* */ })
- def addEvent(s : String, fn : Fn) : this.type = {
- val name = s.toEventName
- if (!this.hasEvent(name))
- _events(name) = FnContainer(fn)
- else
- _events(name) + fn
- this
- }
- // w.addEvent("click" -> { handle => println(handle.event) })
- def addEvent(event : Ev) : thisthis.type = this.addEvent(event._1, event._2)
- def addEvents(events : Ev*) : this.type = {
- events.foreach(this.addEvent(_))
- this
- }
- // 判斷是否存在事件
- def hasEvent(name : String) : Boolean = _events.contains(name.toEventName)
- // Qt事件覆蓋
- override def event(event : QEvent) : Boolean = {
- eventType2Name(event.`type`()) match {
- case Some(name) =>
- if (this.hasEvent(name)) {
- val handle = _events(name).fire(this.asInstanceOf[T], event)
- }
- case _ =>
- }
- super.event(event)
- }
- }
這個Eventable只是一個很初步的封裝,只是針對所有的QWidget適用,我還有好些想法,比如延時事件激活,定時事件循環(huán)。并且希望能對QObject進行全部的適用,而對于Qt的信號槽,自然也要兼容。唉,想法太多,可惜時間太有限。先用著吧,能好像寫js一樣寫事件聲明,該知足了。
下面奉上使用的代碼:
- class Widget extends QWidget with Eventable[QWidget]
- val w = new Widget()
- w.addEvent("onClick", handle => {
- println("單擊了!")
- })
- w.addEvents(
- "show" -> { handle =>
- println("窗口顯示了")
- },
- "doubleClick" -> { handle =>
- println("雙擊了!")
- }
- )
小結(jié):詳解 Qt QWidget對象的Eventable接口(Scala實現(xiàn))的內(nèi)容介紹完了,希望本文對你有幫助,更毒內(nèi)容請參考編輯推薦!
【編輯推薦】