当前位置: 首页>>代码示例>>Python>>正文


Python Timer.schedule方法代码示例

本文整理汇总了Python中pyjamas.Timer.Timer.schedule方法的典型用法代码示例。如果您正苦于以下问题:Python Timer.schedule方法的具体用法?Python Timer.schedule怎么用?Python Timer.schedule使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在pyjamas.Timer.Timer的用法示例。


在下文中一共展示了Timer.schedule方法的7个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Python代码示例。

示例1: delay

# 需要导入模块: from pyjamas.Timer import Timer [as 别名]
# 或者: from pyjamas.Timer.Timer import schedule [as 别名]
def delay(s):
    if STATMODE:
        return  # NO TIME FOR SLEEP IN STATMODE
    if USING_PYGAME:
        from time import sleep

        sleep(s)
    else:
        from pyjamas.Timer import Timer

        timer = Timer(notify=update)
        timer.schedule(s * 1000)
开发者ID:ThatSnail,项目名称:OthelloBot,代码行数:14,代码来源:main.py

示例2: queuereduce

# 需要导入模块: from pyjamas.Timer import Timer [as 别名]
# 或者: from pyjamas.Timer.Timer import schedule [as 别名]
def queuereduce(sender, maxlines=1000):
    showOutputMeta("Reducing...")

    outputPanel.add(HTML(" "))
    outputPanel.add(HTML(" "))
    outputPanel.add(
        HTML(
            """
    <p>Takes too long? Try the <a href="https://bitbucket.org/bgeron
    </continuation-calculus-paper/">Python evaluator.</a>.</p>
    """.strip()
        )
    )

    # Schedule reduceterm(maxlines) really soon.
    timer = Timer(notify=functools.partial(reduceterm, maxlines=maxlines))
    timer.schedule(50)  # after 50 milliseconds
开发者ID:ThreeLetterNames,项目名称:continuation-calculus-paper,代码行数:19,代码来源:cc_eval.py

示例3: itself

# 需要导入模块: from pyjamas.Timer import Timer [as 别名]
# 或者: from pyjamas.Timer.Timer import schedule [as 别名]
class RandomColor:

    __doc__ = '''This last example demonstrates what most pyjamas
    programmers currently do with timers: create a Timer instance
    specifying <code>notify</code> with an object that has an
    <code>onTimer</code> attribute that is callable.  The slider on
    the left will adjust how often the middle panel changes color; it
    is either OFF or a value of seconds from 1 to 5.  Changing the
    slider immediately cancels the current timer and starts a new
    timer to change the color in the newly specified time.  Like the
    previous example, this timer reschedules itself (if it wasn't
    turned off) at the end of the call to <code>onTimer()</code>.
    '''

    def __init__(self):

        # create the label and slider
        self.__label = Label('OFF')
        self.slider = slider = HorizontalSlider(0, 5, step=1,
                                                StyleName="slider")
        slider.setDragable(True)
        slider.addControlValueListener(self)

        # put them in a hpanel
        self.hpanel = hpanel = HorizontalPanel(Spacing=10)
        hpanel.add(slider)
        hpanel.add(self.__label)

        # create the color panel and give it color
        self.colorpanel = CaptionPanel('Color:',
                                       SimplePanel(StyleName='colorpanel'))
        self.randomcolor()

        # we're initially off
        self.value = 0
        # create our timer
        self.timer = Timer(notify=self)

    def initialize(self):

        # this method solves an apparent bug with the slider: the
        # slider doesn't draw its handle if the position is set before
        # showing, so instead of doing this in __init__ (where I
        # originally had it), this method gets called after it is
        # shown on the root panel.  See below when it gets called.
        self.slider.setValue(self.value)
        self.slider.setControlPos(self.value)

    def onTimer(self, timer):

        # when the timer fires we randomize the color and (maybe)
        # reschedule ourselves.
        self.randomcolor()
        v = self.value * 1000
        if v:
            self.timer.schedule(v)

    def onControlValueChanged(self, sender, old, new):

        # event handler for when the slider is moved.
        if new == self.value:
            return
        self.value = new

        # is it being turned off?
        if new == 0:
            self.__label.setText('OFF')
            self.timer.cancel()
        else:
            # no it's being reset
            self.__label.setText(str(new) + ' sec')
            self.onTimer(self.timer)
            
    def randomcolor(self):

        # randomize the color and set the panel accordingly
        r = random()*256
        g = random()*256
        b = random()*256
        e = self.colorpanel.getWidget().getElement()
        color = '#%02x%02x%02x' % (r, g, b)
        self.colorpanel.setCaption('Color: %s' % color)
        DOM.setStyleAttribute(e, "background", color)
开发者ID:anandology,项目名称:pyjamas,代码行数:85,代码来源:timerdemo.py

示例4: Photos

# 需要导入模块: from pyjamas.Timer import Timer [as 别名]
# 或者: from pyjamas.Timer.Timer import schedule [as 别名]
class Photos(Composite):
    def __init__(self):
        Composite.__init__(self)

        self.albums = []
        self.photos = []
        self.grid = Grid(4, 4, CellPadding=4, CellSpacing=4)
        self.grid.addTableListener(self)
        self.drill = 0
        self.pos = 0
        self.up = Button("Up", self) 
        self.next = Button("Next", self) 
        self.prev = Button("Prev", self) 
        self.timer = Timer(notify=self)
        self.userid = "jameskhedley"
        self.album_url = "http://picasaweb.google.com/data/feed/base/user/" + self.userid + "?alt=json-in-script&kind=album&hl=en_US&callback=restCb"
        self.doRESTQuery(self.album_url, self.timer)

        self.vp = VerticalPanel()
        self.disclosure = DisclosurePanel("Click for boring technical details.") 
        self.disclosure.add(HTML('''<p>OK so you want to write client JS to do a RESTful HTTP query from picasa right?
				 Well you can't because of the Same Origin Policy. Basically this means that
				 because the domain of the query and the domain of the hosted site are different,
				 then that could well be a cross-site scripting (XSS) attack. So, the workaround is to
				 do the call from a script tag so the JSON we get back is part of the document. 
				 But since we don't know what URL to hit yet, once we find out then we have to inject
				 a new script tag dynamically which the browser will run as soon as we append it.
				 To be honest I'm not 100% why Google use RESTful services and not JSON-RPC or somesuch,
				 which would be easier. Well, easier for me.'''))
        
        self.IDPanel = HorizontalPanel()
        self.IDPanel.add(Label("Enter google account:"))
        self.IDButton = Button("Go", self)
        
        self.IDBox = TextBox()
        self.IDBox.setText(self.userid)
        self.IDPanel.add(self.IDBox)
        self.IDPanel.add(self.IDButton)
        self.vp.add(self.IDPanel)
        self.vp.add(self.disclosure)
        self.vp.add(self.grid)

        self.initWidget(self.vp)

    def doRESTQuery(self, url, timer):
        """this is a totally different from an RPC call in that we have to
           dynamically add script tags to the DOM when we want to query the 
           REST API. These rely on callbacks in the DOM so we can either add 
           them dynamically or pre-define them in public/Main.html. 
           Once we've done that have to wait for the response.
           Which means we need to provide a listener for the timer"""

        JS("$wnd.receiver = 'wait'")
        new_script = DOM.createElement("script")
        DOM.setElemAttribute(new_script, "src", url)
        DOM.setElemAttribute(new_script, "type","text/javascript")
        JS("$wnd.document.body.appendChild(@{{new_script}})")
        self.timer.schedule(100)

    def onCellClicked(self, sender, row, col):
        if self.drill==0:
            self.drill += 1 
            self.vp.clear()
            self.grid.clear()
            self.vp.add(self.up)
            self.vp.add(self.grid)
            gridcols = self.grid.getColumnCount()
            album = self.albums[row+col+(row*(gridcols-1))]
            url = "http://picasaweb.google.com/data/feed/base/user/" + self.userid + "/albumid/" + album["id"] + "?alt=json-in-script&kind=photo&hl=en_US&callback=restCb"
            self.doRESTQuery(url, self.timer)
        elif self.drill==1:
            self.drill += 1
            gridcols = self.grid.getColumnCount()
            self.pos =row+col+(row*(gridcols-1))
            photo = self.photos[self.pos]
            self.vp.clear()
            self.fullsize = HTML('<img src="' + photo["full"] + '"/>')
            hp = HorizontalPanel()
            hp.add(self.up)
            hp.add(self.prev)
            hp.add(self.next)
            hp.setSpacing(8)
            self.vp.add(hp)
            self.vp.add(self.fullsize)

    def onClick(self, sender):
        if sender == self.IDButton:
            self.userid = self.IDBox.getText()
            if self.userid == "" or self.userid.isdigit():
                return
            self.drill = 0
            self.album_url = "http://picasaweb.google.com/data/feed/base/user/" + self.userid + "?alt=json-in-script&kind=album&hl=en_US&callback=restCb"
            self.grid.clear()
            self.doRESTQuery(self.album_url, self.timer)
        else:
            if self.drill == 2:
                if sender == self.up:
                    self.drill=1
                    self.vp.clear()
                    self.vp.add(self.up)
#.........这里部分代码省略.........
开发者ID:anandology,项目名称:pyjamas,代码行数:103,代码来源:Photos.py

示例5: DataRunManager

# 需要导入模块: from pyjamas.Timer import Timer [as 别名]
# 或者: from pyjamas.Timer.Timer import schedule [as 别名]
class DataRunManager(object) :
	"""
	@brief Class to take care of all the data taking runs. Starts them and
	polls the RPC service to see when it's finished.
	
	Implemented as a singleton. Call the DataRunManager.instance() static
	method to get the only running instance.
	"""
	pollingTime=1000
	idlePollingTime=4000 # Longer polling time when I don't think I'm taking data.
	_onlyInstance=None
	# The following members are used as an enum to describe what the event is
	DataTakingStartedEvent=0
	DataTakingFinishedEvent=1
	DataTakingStatusEvent=3
	
	@staticmethod
	def instance() : # static method so no "self" parameter
		if DataRunManager._onlyInstance==None :
			DataRunManager._onlyInstance=DataRunManager()
		return DataRunManager._onlyInstance
	
	def __init__(self) :
		# Since this is a singleton, throw an exception if the constructor is called
		# explicitly.
		if DataRunManager._onlyInstance!=None :
			raise Exception( "DataRunManager is a singleton class. Call 'DataRunManager.instance()' to get the only running instance" )
		self.rpcService=GlibRPCService.instance()
		self.pollingTimer=Timer( notify=self.pollRPCService )
		self.eventHandlers = []
		self.fractionComplete = 1
		self.statusString = "Not taking data"
		self.firstRun = True
		# I'll poll once immediately on startup just in case the user is connecting to an
		# already running service. The code that handles the response to this starts the
		# timer running.
		self.pollRPCService()

	def onRemoteResponse(self, response, request_info):
		"""
		The method that gets called after a successful RPC call.
		"""
		#ErrorMessage( "Response to method '"+request_info.method+"'='"+str(response)+"'" )
		if request_info.method=="getDataTakingStatus" : self._onGetDataTakingStatusResponse(response)
		elif request_info.method=="startSCurveRun" : self._startRunResponse(response,"S-curve run")
		elif request_info.method=="startOccupancyCheck" : self._startRunResponse(response,"Occupancy check")
		elif request_info.method=="startTrimCalibration" : self._startRunResponse(response,"Trim calibration")
		elif request_info.method=="stopTakingData" : pass
		else : ErrorMessage( "Received an unexpected response for method "+request_info.method )
	
	def onRemoteError(self, code, message, request_info):
		"""
		The method that gets called after an unsuccessful RPC call.
		"""
		ErrorMessage( "Unable to contact server: "+str(message) )

	def _onGetDataTakingStatusResponse( self, response ) :
		"""
		Handles the response to a getDataTakingStatus RPC call. Separate method for code layout only.
		"""
		newFraction=response["fractionComplete"]
		newStatus=response["statusString"]
		statusHasChanged=False
		if (self.fractionComplete!=newFraction) or (self.statusString!=newStatus) :
			statusHasChanged=True
			if self.firstRun :
				# If something is already running on initialisation, tell everything
				for handler in self.eventHandlers :
					handler.onDataTakingEvent( DataRunManager.DataTakingStartedEvent, None )
		self.firstRun=False
		self.fractionComplete=newFraction
		self.statusString=newStatus
		# only want to inform the listening classes if there is a change in the status
		if statusHasChanged :
			if self.fractionComplete>=1 :
				eventCode=DataRunManager.DataTakingFinishedEvent
				details=None
			else :
				eventCode=DataRunManager.DataTakingStatusEvent
				details={"fractionComplete":self.fractionComplete,"statusString":self.statusString}
			# Inform all the registered handlers what is going on
			for handler in self.eventHandlers :
				handler.onDataTakingEvent( eventCode, details )

		if self.fractionComplete<1 :
			# If data hasn't finished then set the timer to fire again.
			self.pollingTimer.schedule( DataRunManager.pollingTime )
		else :
			# I'll constantly poll to make sure it's not taking data, in case something/someone
			# else connects and tells the RPC service to do something. I'll use a longer time
			# though.
			if self.idlePollingTime>0 : self.pollingTimer.schedule( DataRunManager.idlePollingTime )

	def _startRunResponse( self, reponse, runType ) :
		"""
		Handles the response to a RPC call. Separate method for code layout only.
		"""
		self.statusString=runType+" started"
		# Start polling the RPC service to see how the run is going
		self.pollingTimer.schedule( DataRunManager.pollingTime )
#.........这里部分代码省略.........
开发者ID:BristolHEP-CBC-Testing,项目名称:cbcanalysis,代码行数:103,代码来源:DataRunManager.py

示例6: SeeMeNot

# 需要导入模块: from pyjamas.Timer import Timer [as 别名]
# 或者: from pyjamas.Timer.Timer import schedule [as 别名]
class SeeMeNot(object):
  def __init__(self, symbol_shape, message_symbol_coder, symbol_signal_coder):
    self.timer = Timer(notify=self)
    self.setTimer(self.timer)
    self.symbol_shape = symbol_shape
    self.message_symbol_coder = message_symbol_coder
    self.symbol_signal_coder = symbol_signal_coder
    self.decoded = {}

  def setTimer(self, timer):
    self.timer.schedule(2000)

  def onTimer(self, timer):
    print 'onTimer Called.'
    JS("""
var myinfoobject = new Object();
myinfoobject['populate'] = true;
chrome.windows.getCurrent(myinfoobject, mylocalfunction);
function mylocalfunction(window) {
  @{{focused_window}} = window.id;
  tabs = window.tabs;
  if (!tabs) {
    return;
  }
  tabs_len = tabs.length;
  for (var i = 0; i < tabs_len; i++) {
    if (tabs[i].active) {
      @{{focused_tab}} = tabs[i].id

      console.log("Issuing getDom request to " + tabs[i].id);
      chrome.tabs.sendRequest(tabs[i].id, {action: "getDOM"},
        function(response) {
          if (!response.process) {
            console.log('Nothing to process.');
            return;
          }
          console.log("SeeMeNot Response from python " + response.dom.substr(0,8));

          var canvas = document.createElement('canvas');
          var ctx = canvas.getContext('2d');
          var img = new Image();

          img.onload = function() {
            canvas.width = img.width;
            canvas.height = img.height;

            ctx.drawImage(img, 0, 0);

            var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
            console.log('canvas ' + canvas.width + ' ' + canvas.height);
            @{{width}} = imageData.width;
            @{{height}} = imageData.height;
            var datalength = imageData.data.length;

            @{{imageDataArray}} = new Array();
            for (var j = 0; j < datalength; j = j + 4) {
              @{{imageDataArray}}.push(imageData.data[j]);
            }
          }

          img.src = response.dom;
          @{{b64}} = response.dom;
        }
      );
    }
  }
}""")
    print 'Focused win:', focused_window
    print 'Focused tab:', focused_tab
    print "Target py'd:", str(b64)[:min(40, len(str(b64)))]

    new_b64 = str(b64)

    JS("""
@{{lookup}} = { 255: 0, 254: 0, 253: 0, 252: 0, 251: 0, 250: 0, 249: 0, 248: 0, 247: 0, 246: 0, 249: 0, 248: 0, 247: 0, 246: 0, 245: 0, 244: 0, 243: 0, 242: 0, 241: 0, 240: 0, 239: 0, 238: 0, 237: 0, 236: 0, 235: 0, 234: 0, 233: 0, 232: 0, 231: 0, 230: 0, 229: 0, 228: 0, 227: 0, 226: 0, 225: 0, 224: 0, 223: 0, 222: 0, 221: 1, 220: 1, 219: 1, 218: 1, 217: 1, 216: 1, 215: 1, 214: 1, 213: 1, 212: 1, 211: 1, 210: 1, 209: 1, 208: 1, 207: 1, 206: 1, 205: 1, 204: 1, 203: 1, 202: 1, 201: 1, 200: 1, 199: 1, 198: 1, 197: 1, 196: 1, 195: 1, 194: 1, 193: 2, 192: 2, 191: 2, 190: 2, 189: 2, 188: 2, 187: 2, 186: 2, 185: 2, 184: 2, 183: 2, 182: 2, 181: 2, 180: 2, 179: 2, 178: 2, 177: 2, 176: 2, 175: 2, 174: 2, 173: 2, 172: 2, 171: 2, 170: 2, 169: 2, 168: 2, 167: 2, 166: 2, 165: 3, 164: 3, 163: 3, 162: 3, 161: 3, 160: 3, 159: 3, 158: 3, 157: 3, 156: 3, 155: 3, 154: 3, 153: 3, 152: 3, 151: 3, 150: 3, 149: 3, 148: 3, 147: 3, 146: 3, 145: 3, 144: 3, 143: 3, 142: 3, 141: 3, 140: 3, 139: 3, 138: 3, 137: 4, 136: 4, 135: 4, 134: 4, 133: 4, 132: 4, 131: 4, 130: 4, 129: 4, 128: 4, 127: 4, 126: 4, 125: 4, 124: 4, 123: 4, 122: 4, 121: 4, 120: 4, 119: 4, 118: 4, 117: 4, 116: 4, 115: 4, 114: 4, 113: 4, 112: 4, 111: 4, 110: 4, 109: 5, 108: 5, 107: 5, 106: 5, 105: 5, 104: 5, 103: 5, 102: 5, 101: 5, 100: 5, 99: 5, 98: 5, 97: 5, 96: 5, 95: 5, 94: 5, 93: 5, 92: 5, 91: 5, 90: 5, 89: 5, 88: 5, 87: 5, 86: 5, 85: 5, 84: 5, 83: 5, 82: 5, 81: 6, 80: 6, 79: 6, 78: 6, 77: 6, 76: 6, 75: 6, 74: 6, 73: 6, 72: 6, 71: 6, 70: 6, 69: 6, 68: 6, 67: 6, 66: 6, 65: 6, 64: 6, 63: 6, 62: 6, 61: 6, 60: 6, 59: 6, 58: 6, 57: 6, 56: 6, 55: 6, 54: 6, 53: 7, 52: 7, 51: 7, 50: 7, 49: 7, 48: 7, 47: 7, 46: 7, 45: 7, 44: 7, 43: 7, 42: 7, 41: 7, 40: 7, 39: 7, 38: 7, 37: 7, 36: 7, 35: 7, 34: 7, 33: 7, 32: 7, 31: 7, 30: 7, 29: 7, 28: 7, 27: 7, 26: 7, 25: 8, 24: 8, 23: 8, 22: 8, 21: 8, 20: 8, 19: 8, 18: 8, 17: 8, 16: 8, 15: 8, 14: 8, 13: 8, 12: 8, 11: 8, 10: 8, 9: 8, 8: 8, 7: 8, 6: 8, 5: 8, 4: 8, 3: 8, 2: 8, 1: 8, 0: 8 }
""")

    symbol_signal_coder = Base64SymbolSignalCoder()
    if str(focused_tab) and str(new_b64) and str(width):
      print 'Dimensions', width, height

      _data_len = len(imageDataArray)
      imageDataArray.reverse()

      pixels = []
      for _h in range(height):
        pixels.append([])
        for _w in range(width):
          red = imageDataArray.pop()
          pixels[_h].append(red)

      print 'Pixel matrix set.'
      shape_width, shape_height = self.symbol_shape.get_shape_size()
      extracted_data = ''
      values = {}
      for y_coord in range(0, height, shape_height):
        for x_coord in range(0, width, shape_width):
          values.clear()
          _symbol = []
          for symbol_val in range(self.symbol_shape.get_num_symbol_shapes()):
#.........这里部分代码省略.........
开发者ID:davidmi,项目名称:cryptogram,代码行数:103,代码来源:SeeMeNot.py

示例7: DNDHelper

# 需要导入模块: from pyjamas.Timer import Timer [as 别名]
# 或者: from pyjamas.Timer.Timer import schedule [as 别名]

#.........这里部分代码省略.........
        self.mouseEvent = event
        button = DOM.eventGetButton(event)
        if button != Event.BUTTON_LEFT:
            return
#        x, y = eventCoordinates(event)
#        self.origMouseX = x
#        self.origMouseY = y
        self.dragging = DRAGGING_NO_MOVEMENT_YET
        self.drag_time = time.time()
        self.dragDataStore = DragDataStore()

    def onMouseUp(self, sender, x, y):
#        event = DOM.eventGetCurrentEvent()
        self.dragging = NOT_DRAGGING
        if self.draggingImage:
            GlassWidget.hide()
            if (self.currentDragOperation == 'none'
                    or not self.currentTargetElement):
                if self.currentTargetElement:
#                    leave_event = self.makeDragEvent(event, 'dragleave',
#                        self.currentTargetElement)
                    self.fireDNDEvent('dragleave', self.currentTargetElement,
                                      self.currentDropWidget)
#                    self.currentDropWidget.onDragLeave(leave_event)
#                    self.finalize(leave_event)
                else:
                    self.currentDragOperation = 'none'
                self.returnDrag()
            else:
#                self.dragDataStore.mode = READ_ONLY
#                drop_event = self.makeDragEvent(event, 'drop',
#                    self.currentTargetElement)
                drop_event = self.fireDNDEvent('drop', self.currentTargetElement,
                                  self.currentDropWidget)
                #self.dropEffect = self.currentDragOperation
#                self.currentDropWidget.onDrop(drop_event)
#                self.finalize(drop_event)
                if isCanceled(drop_event):
                    self.currentDragOperation = drop_event.dataTransfer.dropEffect
                else:
                    self.currentDragOperation = 'none'
                self.zapDragImage()

            #self.dropEffect = self.currentDragOperation
            self.fireDNDEvent('dragend', None, self.dragWidget)
#                dragEnd_event = self.makeDragEvent(event, 'dragend')

#                self.dragWidget.onDragEnd(dragEnd_event)
#                self.finalize(dragEnd_event)

    def zapDragImage(self):
        RootPanel().remove(self.draggingImage)
        self.draggingImage = None

    def returnDrag(self):
        self.moveItemTo(self.draggingImage,self.origLeft, self.origTop)

    def returnXY(self, start, destination, count):
        start_x, start_y = start
        destination_x, destination_y = destination
        diff_x = (start_x - destination_x) / count
        diff_y = (start_y - destination_y) / count
        while (abs(start_x - destination_x) > 10
               or abs(start_y - destination_y) > 10):
            start_x -= diff_x
            start_y -= diff_y
            yield start_x, start_y
        raise StopIteration

    def onReturningWidget(self, timer):
        try:
            next_loc = self.return_iterator.next()
        except StopIteration:
            self.zapDragImage()
            return
        x, y = next_loc
        self.draggingImage.setStyleAttribute('top', str(y))
        self.draggingImage.setStyleAttribute('left', str(x))
        self.returnTimer.schedule(50)

    def moveItemTo(self, widget, x, y):
        self.returnWidget = widget
        returnWidgetDestination = x, y
        widgetStart = widget.getAbsoluteLeft(), widget.getAbsoluteTop()
        self.return_iterator = self.returnXY(widgetStart,
                        returnWidgetDestination, 10)
        self.returnTimer.schedule(50)

    def onMouseEnter(self, sender):
        pass

    def onMouseLeave(self, sender):
        if self.dragging == DRAGGING_NO_MOVEMENT_YET:
            self.dragging = NOT_DRAGGING

    def onMouseGlassEnter(self, sender):
         pass

    def onMouseGlassLeave(self, sender):
         pass
开发者ID:Afey,项目名称:pyjs,代码行数:104,代码来源:DNDHelper.py


注:本文中的pyjamas.Timer.Timer.schedule方法示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。