四、编程向导(4.10集成其他框架)

编程向导4.10集成其他框架

在Kivy内部使用Twisted框架

gthank:Twisted是用Python实现的基于事件驱动的网络引擎框架。Twisted诞生于2000年初,在当时的网络游戏开发者看来,无论他们使用哪种语言,手中都鲜有可兼顾扩展性及跨平台的网络库。Twisted的作者试图在当时现有的环境下开发游戏,这一步走的非常艰难,他们迫切地需要一个可扩展性高、基于事件驱动、跨平台的网络开发框架,为此他们决定自己实现一个,并从那些之前的游戏和网络应用程序的开发者中学习,汲取他们的经验教训。Twisted支持许多常见的传输及应用层协议,包括TCP、UDP、SSL/TLS、HTTP、IMAP、SSH、IRC以及FTP。Twisted对于其支持的所有协议都带有客户端和服务器实现,同时附带有基于命令行的工具,使得配置和部署产品级的Twisted应用变得非常方便。

你可以使用kivy.support.install_twisted_reactor函数来安装一个运行在kivy事件循环里面的twisted反应器。任何传递到该函数的参数和关键字都会被传递给threadedselect反应器交错函数。通常有一个参数传递twisted的reactor.startRunning.

警告:不像默认的Twisted反应器,安装的反应器不会处理任何的信号,除非你设置了installSignalHandlers关键字参数为1.这将使kivy来和平时一样来处理信号,除非你明确地想twisted反应器来处理信号。

kivy的样例中含一个关于twisted服务端和客户端的小例子。服务端程序有一个简单的twisted服务运行并在日志上记录所有的信息。客户端程序能发送消息到服务端,并打印它发送及响应它的信息。例子基于twisted文档的的简单的Echo 例子,你可以在下面的链接找到它们:

为了测试这个例子,首先运行echo_server_app.py,接着运行echo_client_app.py。服务端将会使用简单的echo消息来回应任何来自客户端发送的消息。

服务端:

#在导入和使用反应器之前,install_twisted_rector必须首先被调用
from kivy.support import install_twisted_reactor
install_twisted_reactor()


from twisted.internet import reactor
from twisted.internet import protocol


class EchoProtocol(protocol.Protocol):
    def dataReceived(self, data):
        response = self.factory.app.handle_message(data)
        if response:
            self.transport.write(response)


class EchoFactory(protocol.Factory):
    protocol = EchoProtocol

    def __init__(self, app):
        self.app = app


from kivy.app import App
from kivy.uix.label import Label


class TwistedServerApp(App):
    def build(self):
        self.label = Label(text="server started\n")
        reactor.listenTCP(8000, EchoFactory(self))
        return self.label

    def handle_message(self, msg):
        self.label.text = "received:  %s\n" % msg

        if msg == "ping":
            msg = "pong"
        if msg == "plop":
            msg = "kivy rocks"
        self.label.text += "responded: %s\n" % msg
        return msg


if __name__ == '__main__':
    TwistedServerApp().run()

客户端:

#在导入和使用反应器之前,install_twisted_rector必须首先被调用
from kivy.support import install_twisted_reactor
install_twisted_reactor()

#一个简单的客户端,它能发送消息到echo服务端
from twisted.internet import reactor, protocol


class EchoClient(protocol.Protocol):
    def connectionMade(self):
        self.factory.app.on_connection(self.transport)

    def dataReceived(self, data):
        self.factory.app.print_message(data)


class EchoFactory(protocol.ClientFactory):
    protocol = EchoClient

    def __init__(self, app):
        self.app = app

    def clientConnectionLost(self, conn, reason):
        self.app.print_message("connection lost")

    def clientConnectionFailed(self, conn, reason):
        self.app.print_message("connection failed")


from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.boxlayout import BoxLayout

#一个简单的kivy应用程序,带有一个文本框来输入消息,
#并有一个文本标签来显示所有的从服务端返回的消息
class TwistedClientApp(App):
    connection = None

    def build(self):
        root = self.setup_gui()
        self.connect_to_server()
        return root

    def setup_gui(self):
        self.textbox = TextInput(size_hint_y=.1, multiline=False)
        self.textbox.bind(on_text_validate=self.send_message)
        self.label = Label(text='connecting...\n')
        self.layout = BoxLayout(orientation='vertical')
        self.layout.add_widget(self.label)
        self.layout.add_widget(self.textbox)
        return self.layout

    def connect_to_server(self):
        reactor.connectTCP('localhost', 8000, EchoFactory(self))

    def on_connection(self, connection):
        self.print_message("connected succesfully!")
        self.connection = connection

    def send_message(self, *args):
        msg = self.textbox.text
        if msg and self.connection:
            self.connection.write(str(self.textbox.text))
            self.textbox.text = ""

    def print_message(self, msg):
        self.label.text += msg + "\n"

if __name__ == '__main__':
    TwistedClientApp().run()

下节预告:编程向导4.11最佳实践&4.12高级图形技术

推荐阅读更多精彩内容