Sending canvas data between applications

main.py

from kivy.base import EventLoop
from kivy.config import Config
from kivy.graphics import Color, Line
from kivy.uix.behaviors import ToggleButtonBehavior
from kivy.uix.togglebutton import ToggleButton
from kivy.uix.widget import Widget
from kivy.utils import get_color_from_hex
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.popup import Popup
from kivy.clock import Clock
CURSOR = (
    '       @@@@             ',
    '       @--@             ',
    '       @--@             ',
    '       @--@             ',
    '       @--@             ',
    '       @@@@             ',
    '                        ',
    '@@@@@@ @@@@ @@@@@@      ',
    '@----@ @--@ @----@      ',
    '@----@ @--@ @----@      ',
    '@@@@@@ @@@@ @@@@@@      ',
    '                        ',
    '       @@@@             ',
    '       @--@             ',
    '       @--@             ',
    '       @--@             ',
    '       @--@             ',
    '       @@@@             ',
    '                        ',
    '                        ',
    '                        ',
    '                        ',
    '                        ',
    '                        ',
)
class Update_Location(Widget):
    pass

class CanvasWidget(Widget):
    line_width = 2

    def on_touch_down(self, touch):
        if Widget.on_touch_down(self, touch):
           return

        with self.canvas:
            touch.ud['current_line'] = Line(
                points=(touch.x, touch.y),
                width=self.line_width)

    def on_touch_move(self, touch):
        if 'current_line' in touch.ud:
            touch.ud['current_line'].points += (touch.x, touch.y)

    def set_color(self, new_color):
        self.last_color = new_color
        self.canvas.add(Color(*new_color))

    def set_line_width(self, line_width='Normal'):
        self.line_width = {
            'Thin': 1, 'Normal': 2, 'Thick': 4
        }[line_width]

    def clear_canvas(self):
        saved = self.children[:]
        self.clear_widgets()
        self.canvas.clear()
        for widget in saved:
            self.add_widget(widget)
        self.set_color(self.last_color)
    def start_server(self):
        host = '127.0.0.1'
        port = 5000
        notification_text="Server started on host: "+host+" and port: "+str(port)
        server_start=Popup(title='Notification',content=Label(text=notification_text),size_hint=(.75,.75),auto_dismiss=True)
        server_start.open()
        Clock.schedule_interval(server_start.dismiss, 3)


class PaintApp(App):
    def build(self):
        EventLoop.ensure_window()
        if EventLoop.window.__class__.__name__.endswith('Pygame'):
            try:
                from pygame import mouse

                a, b = pygame_compile_cursor()
                mouse.set_cursor((24, 24), (9, 9), a, b)
            except:
                pass
        #boxlayout
        self.layout = BoxLayout(orientation='vertical')

        self.canvas_widget = CanvasWidget()
        self.canvas_widget.set_color(
            get_color_from_hex('#2980b9'))
        self.layout.add_widget(self.canvas_widget)
        #self.layout.add_widget(Label(text="Started Server : False , Connected to Server : False",color=(1,1,1),size_hint=(1, .1)))
        return self.layout

        #return self.canvas_widget


class RadioButton(ToggleButton):
    def _do_press(self):
        if self.state == 'normal':
            ToggleButtonBehavior._do_press(self)


def pygame_compile_cursor(black='@', white='-'):
    aa, bb = [], []
    a = b = 0
    i = 8
    for s in CURSOR:
        for c in s:
            a <<= 1
            b <<= 1
            i -= 1
            if c == black:
                a |= 1
                b |= 1
            elif c == white:
                b |= 1

            if not i:
                aa.append(a)
                bb.append(b)
                a = b = 0
                i = 8

    return tuple(aa), tuple(bb)

if __name__ == '__main__':
    Config.set('graphics', 'width', '960')
    Config.set('graphics', 'height', '540')  # 16:9
    # Config.set('graphics', 'resizable', '0')
    # Config.set('input', 'mouse', 'mouse,disable_multitouch')

    from kivy.core.window import Window
    Window.clearcolor = get_color_from_hex('#ffffff')

    PaintApp().run()

server.py

import socket

def start_server(host,port):
    s = socket.socket()
    s.bind((host,port))

    s.listen(1)
    c, addr = s.accept()
    print "Connection from: " + str(addr)
    while True:
        data = c.recv(1024)
        if not data:
            break
        print "from connected user: " + str(data)
        data = str(data).upper()
        print "sending: " + str(data)
        c.send(data)
    c.close()

if __name__ == '__main__':
    start_server()

Above is the code for my simple drawing application (adopted from kiwi blue prints).

My goal is to start the server in one application on the local host, and then connect to it with others. Those who can connect to it should update their canvas with one of the servers to which they are connected. How can I send data and update the canvas. I created the server in the above code using the python socket library.

I do not want to use HTTP requests / streams, instead I establish connections with sockets and use async.io.

+4
source share
1 answer

REST /canvas, . CanvasWidget, . , , , , - .

  • server.py
  • main.py
  • -
  • 's',
  • main.py
  • main.py
  • "r", .

main.py

from kivy.app import App
from kivy.base import EventLoop
from kivy.config import Config
from kivy.graphics import Color, Line
from kivy.uix.behaviors import ToggleButtonBehavior
from kivy.uix.togglebutton import ToggleButton
from kivy.uix.widget import Widget
from kivy.utils import get_color_from_hex
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.popup import Popup
from kivy.clock import Clock
from kivy.network.urlrequest import UrlRequest
import flask

CURSOR = (
    '       @@@@             ',
    '       @--@             ',
    '       @--@             ',
    '       @--@             ',
    '       @--@             ',
    '       @@@@             ',
    '                        ',
    '@@@@@@ @@@@ @@@@@@      ',
    '@----@ @--@ @----@      ',
    '@----@ @--@ @----@      ',
    '@@@@@@ @@@@ @@@@@@      ',
    '                        ',
    '       @@@@             ',
    '       @--@             ',
    '       @--@             ',
    '       @--@             ',
    '       @--@             ',
    '       @@@@             ',
    '                        ',
    '                        ',
    '                        ',
    '                        ',
    '                        ',
    '                        ',
)
class Update_Location(Widget):
    pass

class CanvasWidget(Widget):
    line_width = 2
    lines = []

    def __init__(self, **kwargs):
        super(CanvasWidget, self).__init__(**kwargs)
        self._keyboard = Window.request_keyboard(self._keyboard_closed, self)
        self._keyboard.bind(on_key_down=self._on_keyboard_down)

    def _keyboard_closed(self):
        self._keyboard.unbind(on_key_down=self._on_keyboard_down)
        self._keyboard = None

    def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
        if keycode[1] == 's':
            print 'send'
            json = flask.json.dumps(self.lines)
            req = UrlRequest('http://127.0.0.1:5000/canvas', req_body=json)
        elif keycode[1] == 'r':
            print 'receive'
            req = UrlRequest('http://127.0.0.1:5000/canvas', self.load_state)

    def on_touch_down(self, touch):
        if Widget.on_touch_down(self, touch):
           return

        with self.canvas:
            touch.ud['current_line'] = Line(
                points=(touch.x, touch.y),
                width=self.line_width)
            self.lines.append({'points':[touch.x,touch.y], 'width':self.line_width})

    def on_touch_move(self, touch):
        if 'current_line' in touch.ud:
            touch.ud['current_line'].points += (touch.x, touch.y)
            self.lines[-1]['points'].append(touch.x)
            self.lines[-1]['points'].append(touch.y)

    def set_color(self, new_color):
        self.last_color = new_color
        self.canvas.add(Color(*new_color))

    def set_line_width(self, line_width='Normal'):
        self.line_width = {
            'Thin': 1, 'Normal': 2, 'Thick': 4
        }[line_width]

    def clear_canvas(self):
        saved = self.children[:]
        self.clear_widgets()
        self.canvas.clear()
        for widget in saved:
            self.add_widget(widget)
        self.set_color(self.last_color)

    def load_state(self, req, results):
        print 'load_state req', repr(req)
        print 'load_state results', repr(results)
        #needs some validation here
        self.clear_canvas()
        with self.canvas:
            for line in results:
                Line(points=line['points'], width=line['width'])
        self.line = results 

    def start_server(self):
        host = '127.0.0.1'
        port = 5000
        notification_text="Server started on host: "+host+" and port: "+str(port)
        server_start=Popup(title='Notification',content=Label(text=notification_text),size_hint=(.75,.75),auto_dismiss=True)
        server_start.open()
        Clock.schedule_interval(server_start.dismiss, 3)


class PaintApp(App):
    def build(self):
        EventLoop.ensure_window()
        if EventLoop.window.__class__.__name__.endswith('Pygame'):
            try:
                from pygame import mouse

                a, b = pygame_compile_cursor()
                mouse.set_cursor((24, 24), (9, 9), a, b)
            except:
                pass
        #boxlayout
        self.layout = BoxLayout(orientation='vertical')

        self.canvas_widget = CanvasWidget()
        self.canvas_widget.set_color(
            get_color_from_hex('#2980b9'))
        self.layout.add_widget(self.canvas_widget)
        #self.layout.add_widget(Label(text="Started Server : False , Connected to Server : False",color=(1,1,1),size_hint=(1, .1)))
        return self.layout
        #return self.canvas_widget


class RadioButton(ToggleButton):
    def _do_press(self):
        if self.state == 'normal':
            ToggleButtonBehavior._do_press(self)


def pygame_compile_cursor(black='@', white='-'):
    aa, bb = [], []
    a = b = 0
    i = 8
    for s in CURSOR:
        for c in s:
            a <<= 1
            b <<= 1
            i -= 1
            if c == black:
                a |= 1
                b |= 1
            elif c == white:
                b |= 1

            if not i:
                aa.append(a)
                bb.append(b)
                a = b = 0
                i = 8

    return tuple(aa), tuple(bb)

if __name__ == '__main__':
    Config.set('graphics', 'width', '960')
    Config.set('graphics', 'height', '540')  # 16:9
    # Config.set('graphics', 'resizable', '0')
    # Config.set('input', 'mouse', 'mouse,disable_multitouch')

    from kivy.core.window import Window
    Window.clearcolor = get_color_from_hex('#ffffff')

    PaintApp().run()

server.py

from flask import Flask, jsonify, request, json
app = Flask(__name__)

data = []

@app.route('/canvas', methods = ['GET', 'POST'])
def canvas():
    global data
    if request.method == 'GET':
        tmp = jsonify({})
        tmp.set_data(json.dumps(data))
        return tmp

    if request.method == 'POST':
        data = json.loads(request.data)
        tmp = jsonify({})
        tmp.set_data(json.dumps(data))
        return tmp


if __name__ == '__main__':
    app.run(debug=True)
+4

Source: https://habr.com/ru/post/1618692/


All Articles