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


Python QVector.at方法代码示例

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


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

示例1: ObjectTypesModel

# 需要导入模块: from pyqtcore import QVector [as 别名]
# 或者: from pyqtcore.QVector import at [as 别名]
class ObjectTypesModel(QAbstractTableModel):
    ColorRole = Qt.UserRole

    def __init__(self, parent):
        super().__init__(parent)
        
        self.mObjectTypes = QVector()
        
    def setObjectTypes(self, objectTypes):
        self.beginResetModel()
        self.mObjectTypes = objectTypes
        self.endResetModel()

    def objectTypes(self):
        return self.mObjectTypes
        
    def rowCount(self, parent):
        if parent.isValid():
            _x = 0
        else:
            _x = self.mObjectTypes.size()
        return _x

    def columnCount(self, parent):
        if parent.isValid():
            _x = 0
        else:
            _x = 2
        return _x

    def headerData(self, section, orientation, role):
        if (orientation == Qt.Horizontal):
            if (role == Qt.DisplayRole):
                x = section
                if x==0:
                    return self.tr("Type")
                elif x==1:
                    return self.tr("Color")
            elif (role == Qt.TextAlignmentRole):
                return Qt.AlignLeft

        return QVariant()

    def data(self, index, role):
        # QComboBox requests data for an invalid index when the model is empty
        if (not index.isValid()):
            return QVariant()
        objectType = self.mObjectTypes.at(index.row())
        if (role == Qt.DisplayRole or role == Qt.EditRole):
            if (index.column() == 0):
                return objectType.name
        if (role == ObjectTypesModel.ColorRole and index.column() == 1):
            return objectType.color
        return QVariant()

    def setData(self, index, value, role):
        if (role == Qt.EditRole and index.column() == 0):
            self.mObjectTypes[index.row()].name = value.strip()
            self.dataChanged.emit(index, index)
            return True

        return False

    def flags(self, index):
        f = super().flags(index)
        if (index.column() == 0):
            f |= Qt.ItemIsEditable
        return f

    def setObjectTypeColor(self, objectIndex, color):
        self.mObjectTypes[objectIndex].color = color
        mi = self.index(objectIndex, 1)
        self.dataChanged.emit(mi, mi)

    def removeObjectTypes(self, indexes):
        rows = QVector()
        for index in indexes:
            rows.append(index.row())
        rows = sorted(rows)
        for i in range(len(rows) - 1, -1, -1):
            row = rows[i]
            self.beginRemoveRows(QModelIndex(), row, row)
            self.mObjectTypes.remove(row)
            self.endRemoveRows()

    def appendNewObjectType(self):
        self.beginInsertRows(QModelIndex(), self.mObjectTypes.size(), self.mObjectTypes.size())
        self.mObjectTypes.append(ObjectType())
        self.endInsertRows()
开发者ID:theall,项目名称:Python-Tiled,代码行数:91,代码来源:objecttypesmodel.py

示例2: AutoMapperWrapper

# 需要导入模块: from pyqtcore import QVector [as 别名]
# 或者: from pyqtcore.QVector import at [as 别名]
class AutoMapperWrapper(QUndoCommand):
    def __init__(self, mapDocument, autoMapper, where):
        super().__init__()
        
        self.mLayersAfter = QVector()
        self.mLayersBefore = QVector()
        self.mMapDocument = mapDocument
        map = self.mMapDocument.Map()
        touchedLayers = QSet()
        index = 0
        while (index < autoMapper.size()):
            a = autoMapper.at(index)
            if (a.prepareAutoMap()):
                touchedLayers|= a.getTouchedTileLayers()
                index += 1
            else:
                autoMapper.remove(index)

        for layerName in touchedLayers:
            layerindex = map.indexOfLayer(layerName)
            self.mLayersBefore (map.layerAt(layerindex).clone())

        for a in autoMapper:
            a.autoMap(where)
        for layerName in touchedLayers:
            layerindex = map.indexOfLayer(layerName)
            # layerindex exists, because AutoMapper is still alive, dont check
            self.mLayersAfter (map.layerAt(layerindex).clone())

        # reduce memory usage by saving only diffs
        for i in range(self.mLayersAfter.size()):
            before = self.mLayersBefore.at(i)
            after = self.mLayersAfter.at(i)
            diffRegion = before.computeDiffRegion(after).boundingRect()
            before1 = before.copy(diffRegion)
            after1 = after.copy(diffRegion)
            before1.setPosition(diffRegion.topLeft())
            after1.setPosition(diffRegion.topLeft())
            before1.setName(before.name())
            after1.setName(after.name())
            self.mLayersBefore.replace(i, before1)
            self.mLayersAfter.replace(i, after1)
            del before
            del after

        for a in autoMapper:
            a.cleanAll()

    def __del__(self):
        for i in self.mLayersAfter:
            del i
        for i in self.mLayersBefore:
            del i

    def undo(self):
        map = self.mMapDocument.Map()
        for layer in self.mLayersBefore:
            layerindex = map.indexOfLayer(layer.name())
            if (layerindex != -1):
                self.patchLayer(layerindex, layer)

    def redo(self):
        map = self.mMapDocument.Map()
        for layer in self.mLayersAfter:
            layerindex = (map.indexOfLayer(layer.name()))
            if (layerindex != -1):
                self.patchLayer(layerindex, layer)

    def patchLayer(self, layerIndex, layer):
        map = self.mMapDocument.Map()
        b = layer.bounds()
        t = map.layerAt(layerIndex)
        t.setCells(b.left() - t.x(), b.top() - t.y(), layer,
                    b.translated(-t.position()))
        self.mMapDocument.emitRegionChanged(b, t)
开发者ID:theall,项目名称:Python-Tiled,代码行数:77,代码来源:automapperwrapper.py

示例3: Tile

# 需要导入模块: from pyqtcore import QVector [as 别名]
# 或者: from pyqtcore.QVector import at [as 别名]
class Tile(Object):
    def __init__(self, *args):
        super().__init__(Object.TileType)
        
        l = len(args)
        if l==3:
            image, id, tileset = args
            self.mImageSource = QString()
        elif l==4:
            image, imageSource, id, tileset = args
            self.mImageSource = imageSource

        self.mId = id
        self.mTileset = tileset
        self.mImage = image
        self.mTerrain = 0xffffffff
        self.mProbability = 1.0
        self.mObjectGroup = None
        self.mFrames = QVector()
        self.mCurrentFrameIndex = 0
        self.mUnusedTime = 0

    def __del__(self):
        del self.mObjectGroup

    ##
    # Returns the tileset that this tile is part of as a shared pointer.
    ##
    def sharedTileset(self):
        return self.mTileset.sharedPointer()

    ##
    # Returns ID of this tile within its tileset.
    ##
    def id(self):
        return self.mId

    ##
    # Returns the tileset that this tile is part of.
    ##
    def tileset(self):
        return self.mTileset

    ##
    # Returns the image of this tile.
    ##
    def image(self):
        return QPixmap(self.mImage)

    ##
    # Returns the image for rendering this tile, taking into account tile
    # animations.
    ##
    def currentFrameImage(self):
        if (self.isAnimated()):
            frame = self.mFrames.at(self.mCurrentFrameIndex)
            return self.mTileset.tileAt(frame.tileId).image()
        else:
            return QPixmap(self.mImage)

    ##
    # Returns the drawing offset of the tile (in pixels).
    ##
    def offset(self):
        return self.mTileset.tileOffset()

    ##
    # Sets the image of this tile.
    ##
    def setImage(self, image):
        self.mImage = image

    ##
    # Returns the file name of the external image that represents this tile.
    # When this tile doesn't refer to an external image, an empty string is
    # returned.
    ##
    def imageSource(self):
        return self.mImageSource

    ##
    # Returns the file name of the external image that represents this tile.
    # When this tile doesn't refer to an external image, an empty string is
    # returned.
    ##
    def setImageSource(self, imageSource):
        self.mImageSource = imageSource

    ##
    # Returns the width of this tile.
    ##
    def width(self):
        return self.mImage.width()

    ##
    # Returns the height of this tile.
    ##
    def height(self):
        return self.mImage.height()

#.........这里部分代码省略.........
开发者ID:theall,项目名称:Python-Tiled,代码行数:103,代码来源:tile.py

示例4: TileLayer

# 需要导入模块: from pyqtcore import QVector [as 别名]
# 或者: from pyqtcore.QVector import at [as 别名]
class TileLayer(Layer):
    ##
    # Constructor.
    ##
    def __init__(self, name, x, y, width, height):
        super().__init__(Layer.TileLayerType, name, x, y, width, height)
        self.mMaxTileSize = QSize(0, 0)
        self.mGrid = QVector()
        for i in range(width * height):
            self.mGrid.append(Cell())
        self.mOffsetMargins = QMargins()

    def __iter__(self):
        return self.mGrid.__iter__()
        
    ##
    # Returns the maximum tile size of this layer.
    ##
    def maxTileSize(self):
        return self.mMaxTileSize

    ##
    # Returns the margins that have to be taken into account while drawing
    # this tile layer. The margins depend on the maximum tile size and the
    # offset applied to the tiles.
    ##
    def drawMargins(self):
        return QMargins(self.mOffsetMargins.left(),
                        self.mOffsetMargins.top() + self.mMaxTileSize.height(),
                        self.mOffsetMargins.right() + self.mMaxTileSize.width(),
                        self.mOffsetMargins.bottom())

    ##
    # Recomputes the draw margins. Needed after the tile offset of a tileset
    # has changed for example.
    #
    # Generally you want to call Map.recomputeDrawMargins instead.
    ##
    def recomputeDrawMargins(self):
        maxTileSize = QSize(0, 0)
        offsetMargins = QMargins()
        i = 0
        while(i<self.mGrid.size()):
            cell = self.mGrid.at(i)
            tile = cell.tile
            if tile:
                size = tile.size()
                if (cell.flippedAntiDiagonally):
                    size.transpose()
                offset = tile.offset()
                maxTileSize = maxSize(size, maxTileSize)
                offsetMargins = maxMargins(QMargins(-offset.x(),
                                                     -offset.y(),
                                                     offset.x(),
                                                     offset.y()),
                                            offsetMargins)
            i += 1

        self.mMaxTileSize = maxTileSize
        self.mOffsetMargins = offsetMargins
        if (self.mMap):
            self.mMap.adjustDrawMargins(self.drawMargins())

    ##
    # Returns whether (x, y) is inside this map layer.
    ##
    def contains(self, *args):
        l = len(args)
        if l==2:
            x, y = args
            return x >= 0 and y >= 0 and x < self.mWidth and y < self.mHeight
        elif l==1:
            point = args[0]
            return self.contains(point.x(), point.y())

    ##
    # Calculates the region of cells in this tile layer for which the given
    # \a condition returns True.
    ##
    def region(self, *args):
        l = len(args)
        if l==1:
            condition = args[0]
            region = QRegion()
            for y in range(self.mHeight):
                for x in range(self.mWidth):
                    if (condition(self.cellAt(x, y))):
                        rangeStart = x
                        x += 1
                        while(x<=self.mWidth):
                            if (x == self.mWidth or not condition(self.cellAt(x, y))):
                                rangeEnd = x
                                region += QRect(rangeStart + self.mX, y + self.mY,
                                                rangeEnd - rangeStart, 1)
                                break
                            x += 1

            return region
        elif l==0:
            ##
#.........这里部分代码省略.........
开发者ID:theall,项目名称:Python-Tiled,代码行数:103,代码来源:tilelayer.py

示例5: TileStampManager

# 需要导入模块: from pyqtcore import QVector [as 别名]
# 或者: from pyqtcore.QVector import at [as 别名]
class TileStampManager(QObject):
    setStamp = pyqtSignal(TileStamp)

    def __init__(self, toolManager, parent = None):
        super().__init__(parent)
        
        self.mStampsByName = QMap()
        self.mQuickStamps = QVector()
        for i in range(TileStampManager.quickStampKeys().__len__()):
            self.mQuickStamps.append(0)
        
        self.mTileStampModel = TileStampModel(self)
        self.mToolManager = toolManager

        prefs = preferences.Preferences.instance()
        prefs.stampsDirectoryChanged.connect(self.stampsDirectoryChanged)
        self.mTileStampModel.stampAdded.connect(self.stampAdded)
        self.mTileStampModel.stampRenamed.connect(self.stampRenamed)
        self.mTileStampModel.stampChanged.connect(self.saveStamp)
        self.mTileStampModel.stampRemoved.connect(self.deleteStamp)
        self.loadStamps()

    def __del__(self):
        # needs to be over here where the TileStamp type is complete
        pass
        
    ##
    # Returns the keys used for quickly accessible tile stamps.
    # Note: To store a tile layer <Ctrl> is added. The given keys will work
    # for recalling the stored values.
    ##
    def quickStampKeys():
        keys=[Qt.Key_1, Qt.Key_2, Qt.Key_3, Qt.Key_4, Qt.Key_5, Qt.Key_6, Qt.Key_7, Qt.Key_8, Qt.Key_9]
        return keys
        
    def tileStampModel(self):
        return self.mTileStampModel
        
    def createStamp(self):
        stamp = self.tampFromContext(self.mToolManager.selectedTool())
        if (not stamp.isEmpty()):
            self.mTileStampModel.addStamp(stamp)
        return stamp
    
    def addVariation(self, targetStamp):
        stamp = stampFromContext(self.mToolManager.selectedTool())
        if (stamp.isEmpty()):
            return
        if (stamp == targetStamp): # avoid easy mistake of adding duplicates
            return
        for variation in stamp.variations():
            self.mTileStampModel.addVariation(targetStamp, variation)

    def selectQuickStamp(self, index):
        stamp = self.mQuickStamps.at(index)
        if (not stamp.isEmpty()):
            self.setStamp.emit(stamp)
    
    def createQuickStamp(self, index):
        stamp = stampFromContext(self.mToolManager.selectedTool())
        if (stamp.isEmpty()):
            return
        self.setQuickStamp(index, stamp)
    
    def extendQuickStamp(self, index):
        quickStamp = self.mQuickStamps[index]
        if (quickStamp.isEmpty()):
            self.createQuickStamp(index)
        else:
            self.addVariation(quickStamp)
    
    def stampsDirectoryChanged(self):
        # erase current stamps
        self.mQuickStamps.fill(TileStamp())
        self.mStampsByName.clear()
        self.mTileStampModel.clear()
        self.loadStamps()

    def eraseQuickStamp(self, index):
        stamp = self.mQuickStamps.at(index)
        if (not stamp.isEmpty()):
            self.mQuickStamps[index] = TileStamp()
            if (not self.mQuickStamps.contains(stamp)):
                self.mTileStampModel.removeStamp(stamp)

    def setQuickStamp(self, index, stamp):
        stamp.setQuickStampIndex(index)
        # make sure existing quickstamp is removed from stamp model
        self.eraseQuickStamp(index)
        self.mTileStampModel.addStamp(stamp)
        self.mQuickStamps[index] = stamp
    
    def loadStamps(self):
        prefs = preferences.Preferences.instance()
        stampsDirectory = prefs.stampsDirectory()
        stampsDir = QDir(stampsDirectory)
        iterator = QDirIterator(stampsDirectory,
                              ["*.stamp"],
                              QDir.Files | QDir.Readable)
        while (iterator.hasNext()):
#.........这里部分代码省略.........
开发者ID:theall,项目名称:Python-Tiled,代码行数:103,代码来源:tilestampmanager.py

示例6: MapScene

# 需要导入模块: from pyqtcore import QVector [as 别名]
# 或者: from pyqtcore.QVector import at [as 别名]
class MapScene(QGraphicsScene):
    selectedObjectItemsChanged = pyqtSignal()

    ##
    # Constructor.
    ##
    def __init__(self, parent):
        super().__init__(parent)
        self.mMapDocument = None
        self.mSelectedTool = None
        self.mActiveTool = None
        self.mObjectSelectionItem = None
        self.mUnderMouse = False
        self.mCurrentModifiers = Qt.NoModifier,
        self.mDarkRectangle = QGraphicsRectItem()
        self.mDefaultBackgroundColor = Qt.darkGray

        self.mLayerItems = QVector()
        self.mObjectItems = QMap()
        self.mObjectLineWidth = 0.0
        self.mSelectedObjectItems = QSet()
        self.mLastMousePos = QPointF()
        self.mShowTileObjectOutlines = False
        self.mHighlightCurrentLayer = False
        self.mGridVisible = False

        self.setBackgroundBrush(self.mDefaultBackgroundColor)
        tilesetManager = TilesetManager.instance()
        tilesetManager.tilesetChanged.connect(self.tilesetChanged)
        tilesetManager.repaintTileset.connect(self.tilesetChanged)
        prefs = preferences.Preferences.instance()
        prefs.showGridChanged.connect(self.setGridVisible)
        prefs.showTileObjectOutlinesChanged.connect(self.setShowTileObjectOutlines)
        prefs.objectTypesChanged.connect(self.syncAllObjectItems)
        prefs.highlightCurrentLayerChanged.connect(self.setHighlightCurrentLayer)
        prefs.gridColorChanged.connect(self.update)
        prefs.objectLineWidthChanged.connect(self.setObjectLineWidth)
        self.mDarkRectangle.setPen(QPen(Qt.NoPen))
        self.mDarkRectangle.setBrush(Qt.black)
        self.mDarkRectangle.setOpacity(darkeningFactor)
        self.addItem(self.mDarkRectangle)
        self.mGridVisible = prefs.showGrid()
        self.mObjectLineWidth = prefs.objectLineWidth()
        self.mShowTileObjectOutlines = prefs.showTileObjectOutlines()
        self.mHighlightCurrentLayer = prefs.highlightCurrentLayer()
        # Install an event filter so that we can get key events on behalf of the
        # active tool without having to have the current focus.
        QCoreApplication.instance().installEventFilter(self)

    ##
    # Destructor.
    ##
    def __del__(self):
        if QCoreApplication.instance():
            QCoreApplication.instance().removeEventFilter(self)

    ##
    # Returns the map document this scene is displaying.
    ##
    def mapDocument(self):
        return self.mMapDocument

    ##
    # Sets the map this scene displays.
    ##
    def setMapDocument(self, mapDocument):
        if (self.mMapDocument):
            self.mMapDocument.disconnect()
            if (not self.mSelectedObjectItems.isEmpty()):
                self.mSelectedObjectItems.clear()
                self.selectedObjectItemsChanged.emit()

        self.mMapDocument = mapDocument
        if (self.mMapDocument):
            renderer = self.mMapDocument.renderer()
            renderer.setObjectLineWidth(self.mObjectLineWidth)
            renderer.setFlag(RenderFlag.ShowTileObjectOutlines, self.mShowTileObjectOutlines)
            self.mMapDocument.mapChanged.connect(self.mapChanged)
            self.mMapDocument.regionChanged.connect(self.repaintRegion)
            self.mMapDocument.tileLayerDrawMarginsChanged.connect(self.tileLayerDrawMarginsChanged)
            self.mMapDocument.layerAdded.connect(self.layerAdded)
            self.mMapDocument.layerRemoved.connect(self.layerRemoved)
            self.mMapDocument.layerChanged.connect(self.layerChanged)
            self.mMapDocument.objectGroupChanged.connect(self.objectGroupChanged)
            self.mMapDocument.imageLayerChanged.connect(self.imageLayerChanged)
            self.mMapDocument.currentLayerIndexChanged.connect(self.currentLayerIndexChanged)
            self.mMapDocument.tilesetTileOffsetChanged.connect(self.tilesetTileOffsetChanged)
            self.mMapDocument.objectsInserted.connect(self.objectsInserted)
            self.mMapDocument.objectsRemoved.connect(self.objectsRemoved)
            self.mMapDocument.objectsChanged.connect(self.objectsChanged)
            self.mMapDocument.objectsIndexChanged.connect(self.objectsIndexChanged)
            self.mMapDocument.selectedObjectsChanged.connect(self.updateSelectedObjectItems)

        self.refreshScene()

    ##
    # Returns whether the tile grid is visible.
    ##
    def isGridVisible(self):
        return self.mGridVisible
#.........这里部分代码省略.........
开发者ID:theall,项目名称:Python-Tiled,代码行数:103,代码来源:mapscene.py

示例7: EditPolygonTool

# 需要导入模块: from pyqtcore import QVector [as 别名]
# 或者: from pyqtcore.QVector import at [as 别名]
class EditPolygonTool(AbstractObjectTool):
    NoMode, Selecting, Moving = range(3)

    def __init__(self, parent = None):
        super().__init__(self.tr("Edit Polygons"),
              QIcon(":images/24x24/tool-edit-polygons.png"),
              QKeySequence(self.tr("E")),
              parent)

        self.mSelectedHandles = QSet()
        self.mModifiers = Qt.KeyboardModifiers()
        self.mScreenStart = QPoint()
        self.mOldHandlePositions = QVector()
        self.mAlignPosition = QPointF()
        ## The list of handles associated with each selected map object
        self.mHandles = QMapList()
        self.mOldPolygons = QMap()
        self.mStart = QPointF()

        self.mSelectionRectangle = SelectionRectangle()
        self.mMousePressed = False
        self.mClickedHandle = None
        self.mClickedObjectItem = None
        self.mMode = EditPolygonTool.NoMode

    def __del__(self):
        del self.mSelectionRectangle

    def tr(self, sourceText, disambiguation = '', n = -1):
        return QCoreApplication.translate('EditPolygonTool', sourceText, disambiguation, n)

    def activate(self, scene):
        super().activate(scene)
        self.updateHandles()
        # TODO: Could be more optimal by separating the updating of handles from
        # the creation and removal of handles depending on changes in the
        # selection, and by only updating the handles of the objects that changed.
        self.mapDocument().objectsChanged.connect(self.updateHandles)
        scene.selectedObjectItemsChanged.connect(self.updateHandles)
        self.mapDocument().objectsRemoved.connect(self.objectsRemoved)

    def deactivate(self, scene):
        try:
            self.mapDocument().objectsChanged.disconnect(self.updateHandles)
            scene.selectedObjectItemsChanged.disconnect(self.updateHandles)
        except:
            pass
        # Delete all handles
        self.mHandles.clear()
        self.mSelectedHandles.clear()
        self.mClickedHandle = None
        super().deactivate(scene)

    def mouseEntered(self):
        pass
    def mouseMoved(self, pos, modifiers):
        super().mouseMoved(pos, modifiers)
        if (self.mMode == EditPolygonTool.NoMode and self.mMousePressed):
            screenPos = QCursor.pos()
            dragDistance = (self.mScreenStart - screenPos).manhattanLength()
            if (dragDistance >= QApplication.startDragDistance()):
                if (self.mClickedHandle):
                    self.startMoving()
                else:
                    self.startSelecting()

        x = self.mMode
        if x==EditPolygonTool.Selecting:
            self.mSelectionRectangle.setRectangle(QRectF(self.mStart, pos).normalized())
        elif x==EditPolygonTool.Moving:
            self.updateMovingItems(pos, modifiers)
        elif x==EditPolygonTool.NoMode:
            pass

    def mousePressed(self, event):
        if (self.mMode != EditPolygonTool.NoMode): # Ignore additional presses during select/move
            return
        x = event.button()
        if x==Qt.LeftButton:
            self.mMousePressed = True
            self.mStart = event.scenePos()
            self.mScreenStart = event.screenPos()
            items = self.mapScene().items(self.mStart,
                                                                   Qt.IntersectsItemShape,
                                                                   Qt.DescendingOrder,
                                                                   viewTransform(event))
            self.mClickedObjectItem = first(items, MapObjectItem)
            self.mClickedHandle = first(items, PointHandle)
        elif x==Qt.RightButton:
            items = self.mapScene().items(event.scenePos(),
                                                                   Qt.IntersectsItemShape,
                                                                   Qt.DescendingOrder,
                                                                   viewTransform(event))
            clickedHandle = first(items)
            if (clickedHandle or not self.mSelectedHandles.isEmpty()):
                self.showHandleContextMenu(clickedHandle,
                                      event.screenPos())
            else:
                super().mousePressed(event)
        else:
#.........这里部分代码省略.........
开发者ID:theall,项目名称:Python-Tiled,代码行数:103,代码来源:editpolygontool.py


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