最近我在csdn上看见了 __小小的程序员__ 博主的文章,发现python可以开发minecraft启动器?

好牛皮!我试了一下!果真可以,所有版本(包括最新1.19和最新快照)都可以。别忘了pip install pyqt5和minecraft-launcher-lib哦

效果:

选择路径,颜色界面

选择版本和启动游戏界面

版本安装界面

下载地址:

github链接

gitee链接

希望此文对你有帮助。

这一个程序可以自己下载minecraft java edition(包括beta版本,远古版!),如果可以自己改动代码的话首先要下载qt designer,这是python里pyqt里面的一个图形化界面设计应用。

关键的是,下载这些东西都可以不用钱了!动了小心思。

提醒:大家不要沉迷哦

程序的一部分:

1.主程序 launcher.py

import subprocess
import sys
from threading import Thread
from time import sleep
import time
import traceback
# PyQt5中使用的基本控件都在PyQt5.QtWidgets模块中
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import QCursor
from PyQt5.QtWidgets import *
from PyQt5 import QtCore
from json import dumps, load, dump, loads
# 导入designer工具生成的login模块
from ui import Ui_MainWindow
import minecraft_launcher_lib
import ctypes
import inspect
from rich.console import Console
from qt_material import apply_stylesheet, list_themes
console = Console()FLAG = True
LOCK = False
ILOCK = False
verlistpub = []try:# def setTip(obj):# myWin.status.setText(obj)def startfile(filename):try:os.startfile(filename)except:subprocess.Popen(['open', filename])def _async_raise(tid, exctype):"""raises the exception, performs cleanup if needed"""try:tid = ctypes.c_long(tid)if not inspect.isclass(exctype):exctype = type(exctype)res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))if res == 0:# passraise ValueError("invalid thread id")elif res != 1:# """if it returns a number greater than one, you're in trouble,# and you should call it again with exc=NULL to revert the effect"""ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)raise SystemError("PyThreadState_SetAsyncExc failed")except Exception as err:print(err)def info(*obj):localtime = time.localtime(time.time())stackinfo = traceback.extract_stack()who = stackinfo[1][2]line = stackinfo[1][1]# console.print("[black on green] I ", *obj)print(f"[{localtime[3]:0>2}:{localtime[4]:0>2}:{localtime[5]:0>2}] [{who:>20} |{line:>5} ] [INFO]", *obj)def warn(*obj):# console.log("[black on yellow] W ", *obj)localtime = time.localtime(time.time())stackinfo = traceback.extract_stack()who = stackinfo[1][2]line = stackinfo[1][1]# console.print("[black on green] I ", *obj)print(f"[{localtime[3]:0>2}:{localtime[4]:0>2}:{localtime[5]:0>2}] [{who:>20} |{line:>5} ] [WARN]", *obj)def error(*obj):# console.log("[black on red] E ", *obj)localtime = time.localtime(time.time())stackinfo = traceback.extract_stack()who = stackinfo[1][2]line = stackinfo[1][1]# console.print("[black on green] I ", *obj)print(f"[{localtime[3]:0>2}:{localtime[4]:0>2}:{localtime[5]:0>2}] [{who:>20} |{line:>5} ] [ERROR]", *obj)def readData():try:with open(".hj.json") as j:data = load(j)# data["mclist"] = minecraft_launcher_lib.utils.get_installed_versions(# data["mcdirs"])info("Read File Succ")except:warn("File Not Found ignore it")temp = {}temp["mcdirs"] = minecraft_launcher_lib.utils.get_minecraft_directory()temp["user"] = "Launcher"temp["theme"] = list_themes()[0]# temp["mclist"] = minecraft_launcher_lib.utils.get_installed_versions(# temp["mcdirs"])with open(".hj.json", 'w') as j:dump(temp, j)data = tempreturn datadef reloadver():alllist = minecraft_launcher_lib.utils.get_version_list()ver = []for i in alllist:if(i["type"] == "snapshot"):ver.append(i["id"])elif(i["type"] == "release"):ver.append(i["id"])else:ver.append(i["id"])return verinfo("Launcher is Launching")def stop_thread(thread):"""终止线程"""_async_raise(thread.ident, SystemExit)class IoThread(Thread):def __init__(self):Thread.__init__(self)self.data = ""self.counter = 0def run(self):info("Start IoThread")while(FLAG):if(self.counter == 1):# print("Counter!")self.data = readData()# self.reloadver()MyMainForm.apiSetConf(self, self.data)if(self.counter >= 6000):self.counter = 0# print("s")self.counter += 1sleep(0.1)# print(self.counter)class MyMainForm(QMainWindow, Ui_MainWindow):def __init__(self, Parent=None):global myWinglobal verlistpubglobal appsuper(MyMainForm, self).__init__(Parent)self.setupUi(self)self.mclist = []# self.setWindowFlags(Qt.FramelessWindowHint)  # Hide Boardself.tabWidget.currentChanged.connect(self.tabchange)self.launchGameBtn.clicked.connect(self.launchGameFunc)self.conf = readData()if(not os.path.exists(self.conf["mcdirs"])):error("Folder Is NOT FOUND")warn("Not Found Ignore it")self.conf["mcdirs"] = minecraft_launcher_lib.utils.get_minecraft_directory()with open('./.hj.json', 'w') as f:dump(self.conf, f)self.conf = readData()self.userName.setText(self.conf["user"])self.userName.editingFinished.connect(self.setUserText)self.label_4.setWordWrap(True)self.stauts.setWordWrap(True)self.stauts.setAlignment(QtCore.Qt.AlignTop)self.mcDirText.setText(self.conf["mcdirs"])self.setMcDirButton.clicked.connect(self.setMcDir)self.label_4.setAlignment(QtCore.Qt.AlignTop)# self.closeButton.clicked.connect(self.closeFunc)try:self.choiceVer = self.mclist[0]["id"]except:passself.ttemp = reloadver()for i in self.ttemp:self.selectInstallVersionBox.addItem(i)self.installGameButton.clicked.connect(self.installGameFunc)self.selectVersionBox.activated[str].connect(self.setMcVersion)self.styleBox.activated[str].connect(self.changeThemes)self.selectInstallVersionBox.activated[str].connect(self.setinstallMcVersion)self.version = "1.1.1"self.choiceTheme = self.conf["theme"]for i in list_themes():self.styleBox.addItem(i)self.threadpool = []try:self.mclist = minecraft_launcher_lib.utils.get_installed_versions(self.conf["mcdirs"])except:passself.lock = Falseself.desc = ""self.progress = 0# self.ttemp = reloadver()self.current_max = 0for i in self.mclist:self.selectVersionBox.addItem(i["id"])# self.setsText("asdfasdflkahsdfkjahsdf")self.threadpool.append(IoThread())for index in range(len(self.threadpool)):self.threadpool[index].start()self.installchoiceVer = self.ttemp[0]# .stauts.setText("sadfasdf")# def mousePressEvent(self, event):#     if event.button() == Qt.LeftButton:#         self.m_flag = True#         self.m_Position = event.globalPos()-self.pos()  # 获取鼠标相对窗口的位置#         event.accept()#         self.setCursor(QCursor(Qt.OpenHandCursor))  # 更改鼠标图标# def mouseMoveEvent(self, QMouseEvent):#     if Qt.LeftButton and self.m_flag:#         self.move(QMouseEvent.globalPos()-self.m_Position)  # 更改窗口位置#         QMouseEvent.accept()# def mouseReleaseEvent(self, QMouseEvent):#     self.m_flag = False#     self.setCursor(QCursor(Qt.ArrowCursor))try:apply_stylesheet(app, theme=self.conf["theme"])info("Succ Load Theme!")except:error(f"The Launcher is Not Supported This Theme:{self.conf['theme']}")self.conf["theme"] = list_themes()[0]info(f"Change Theme:{self.conf['theme']}")apply_stylesheet(app, theme=self.conf["theme"])with open("./.hj.json", 'w') as f:dump(self.conf, f)def setMcDir(self):result = QFileDialog.getExistingDirectory(None, "选取我的世界目录", self.conf["mcdirs"])info("Dir:", result)if(result is None or result == ""):warn("The Folder is Not Found")else:self.conf["mcdirs"] = resultwith open("./.hj.json", 'w') as f:dump(self.conf, f)self.conf = readData()self.mcDirText.setText(self.conf["mcdirs"])def tabchange(self):index = self.tabWidget.currentIndex()info(f"Tab is Changed! Tabindex:{index}")# if self.tabWidget.currentIndex()==0if index == 1:pass# self.ttemp = reloadver()# for i in self.ttemp:#     self.selectInstallVersionBox.addItem(i)elif index == 0:try:self.mclist = minecraft_launcher_lib.utils.get_installed_versions(self.conf["mcdirs"])except:self.mclist = []try:self.choiceVer = self.mclist[0]["id"]except:passself.selectVersionBox.clear()for i in self.mclist:self.selectVersionBox.addItem(i["id"])def installGameFunc(self):global ILOCKif(not ILOCK):ILOCK = Trueself.setTipText("准备安装版本:{}".format(self.installchoiceVer))info("Start install Version:{}".format(self.installchoiceVer))installmc = InstallMc(self.installchoiceVer, self.conf["mcdirs"])installmc.start()self.setTipText("安装中...")else:self.setTipText("安装正在运行,请等待安装结束")warn("It's installing!")def changeThemes(self, text):global appself.conf["theme"] = textinfo(f"Change Theme:{text}")apply_stylesheet(app, theme=self.conf["theme"])with open("./.hj.json", 'w') as f:dump(self.conf, f)def setTipText(self, text):self.stauts.setText(text)def setUserText(self):self.conf["user"] = "".join(self.userName.text().split(" "))with open(".hj.json", 'w') as j:dump(self.conf, j)def setinstallMcVersion(self, text):self.installchoiceVer = text# print(text)def setMcVersion(self, text):self.choiceVer = text# print(text)def launchGameFunc(self):global LOCKif(not LOCK):LOCK = Trueinfo("Run Mc")self.setTipText("游戏启动中...")mc = RunMc(self.choiceVer, self.conf["mcdirs"], self.userName.text(), "8888-8888-8888")mc.start()self.setTipText("游戏已启动等待游戏窗口出现...")info(self.userName.text())else:self.setTipText("游戏正在运行,请等待游戏结束")warn("The Game is running but User want to Creat NEW game thread!")warn("New Thread is kill by USER")def closeEvent(self, event):global FLAGFLAG = Falsefor index in range(len(self.threadpool)):stop_thread(self.threadpool[index])def apiSetConf(self, conf: dict):self.config = confclass InstallMc(Thread):def __init__(self, version, mcdir):Thread.__init__(self)self.version = versionself.mcdir = mcdirself.desc = ""self.current_max = 0self.progress = 0def set_max(self, new_max: int):self.current_max = new_maxinfo(f"{self.desc} Finish")info("Start New Task!")def set_status(self, status: str):self.desc = statusinfo(f"Change Task To:{status}")def set_progress(self, progress: int):global myWinif self.current_max != 0:self.progress = progressmyWin.stauts.setText(f"下载中: 已下载:{progress} 未下载:{self.current_max-progress}")info(f"{self.desc}: Progress:{progress} Total:{self.current_max}")# MyMainForm.setTipText(MyMainForm, "s")def run(self):global ILOCK, myWincallback = {"setStatus": self.set_status,"setProgress": self.set_progress,"setMax": self.set_max}try:minecraft_launcher_lib.install.install_minecraft_version(self.version, self.mcdir, callback)info(f"Succ Install Version:{self.version}")ILOCK = FalsemyWin.stauts.setText(f"成功安装版本:{self.version}")except:myWin.stauts.setText("安装异常,未知版本!")class RunMc(Thread):def __init__(self, version, mcdir, username, uuuid):Thread.__init__(self)self.version = versionself.mcdir = mcdirself.username = usernameself.uuid = uuuidself.desc = ""self.current_max = 0self.progress = 0def set_max(self, new_max: int):self.current_max = new_maxinfo("Download Finish")info("Start New Task!")def set_status(self, status: str):self.desc = statusinfo(f"Change Task To:{status}")def set_progress(self, progress: int):if self.current_max != 0:self.progress = progressmyWin.stauts.setText(f"启动中: 已准备:{progress} 未准备:{self.current_max-progress}")info(f"{self.desc}: Progress:{progress} Total:{self.current_max}")def run(self):global LOCKcallback = {"setStatus": self.set_status,"setProgress": self.set_progress,"setMax": self.set_max}try:minecraft_launcher_lib.install.install_minecraft_version(self.version, self.mcdir, callback)options = {"username": self.username,"uuid": self.uuid,"token": self.uuid,"-Dminecraft.launcher.brand": "Huaji Launcher","-Dminecraft.launcher.version": "1.1.1"# "launcherName": "PMCL",  # The name of your launcher# "launcherVersion": "1.1",  # The version of your launcher}minecraft_command = minecraft_launcher_lib.command.get_minecraft_command(self.version, self.mcdir, options)myWin.stauts.setText("成功生成启动命令")# 最终,你可以直接启动Minecraft了subprocess.call(minecraft_command)info("Run Minecraft Command with:{}".format(minecraft_command))info("Mc is Run!")info("----------Log With Mc-----------")myWin.stauts.setText("等待游戏窗口出现...")subprocess.call(minecraft_command)LOCK = FalsemyWin.stauts.setText("游戏已退出")except:myWin.stauts.setText("安装异常,未知版本!")if __name__ == "__main__":# 固定的,PyQt5程序都需要QApplication对象。sys.argv是命令行参数列表,确保程序可以双击运行app = QApplication(sys.argv)# 初始化myWin = MyMainForm()# 将窗口控件显示在屏幕上myWin.show()# 程序运行,sys.exit方法确保程序完整退出。sys.exit(app.exec_())
except SystemExit:pass
except:error("Launcher Error:")error("Looking For Trace Back:")console.print_exception(show_locals=True)

2.ui界面设计 main.py

# Form implementation generated from reading ui file '/Users/dcboy/Desktop/pml/main.ui'
#
# Created by: PyQt6 UI code generator 6.1.0
#
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
# run again.  Do not edit this file unless you know what you are doing.from PyQt6 import QtCore, QtGui, QtWidgetsclass Ui_MainWindow(object):def setupUi(self, MainWindow):MainWindow.setObjectName("MainWindow")MainWindow.resize(389, 345)MainWindow.setMinimumSize(QtCore.QSize(389, 345))MainWindow.setMaximumSize(QtCore.QSize(389, 345))MainWindow.setFocusPolicy(QtCore.Qt.FocusPolicy.TabFocus)self.centralwidget = QtWidgets.QWidget(MainWindow)self.centralwidget.setObjectName("centralwidget")self.tabWidget = QtWidgets.QTabWidget(self.centralwidget)self.tabWidget.setGeometry(QtCore.QRect(10, 8, 371, 301))self.tabWidget.setObjectName("tabWidget")self.tab = QtWidgets.QWidget()self.tab.setObjectName("tab")self.groupBox = QtWidgets.QGroupBox(self.tab)self.groupBox.setGeometry(QtCore.QRect(10, 10, 341, 211))self.groupBox.setObjectName("groupBox")self.selectVersionBox = QtWidgets.QComboBox(self.groupBox)self.selectVersionBox.setGeometry(QtCore.QRect(80, 31, 191, 41))self.selectVersionBox.setObjectName("selectVersionBox")self.label = QtWidgets.QLabel(self.groupBox)self.label.setGeometry(QtCore.QRect(20, 40, 60, 21))self.label.setObjectName("label")self.launchGameBtn = QtWidgets.QPushButton(self.groupBox)self.launchGameBtn.setGeometry(QtCore.QRect(190, 150, 141, 51))self.launchGameBtn.setObjectName("launchGameBtn")self.tabWidget.addTab(self.tab, "")self.tab_2 = QtWidgets.QWidget()self.tab_2.setObjectName("tab_2")self.groupBox_2 = QtWidgets.QGroupBox(self.tab_2)self.groupBox_2.setGeometry(QtCore.QRect(10, 10, 341, 131))self.groupBox_2.setObjectName("groupBox_2")self.selectInstallVersionBox = QtWidgets.QComboBox(self.groupBox_2)self.selectInstallVersionBox.setGeometry(QtCore.QRect(10, 40, 321, 41))self.selectInstallVersionBox.setObjectName("selectInstallVersionBox")self.installGameButton = QtWidgets.QPushButton(self.groupBox_2)self.installGameButton.setGeometry(QtCore.QRect(12, 90, 131, 32))self.installGameButton.setObjectName("installGameButton")self.tabWidget.addTab(self.tab_2, "")self.tab_3 = QtWidgets.QWidget()self.tab_3.setObjectName("tab_3")self.groupBox_3 = QtWidgets.QGroupBox(self.tab_3)self.groupBox_3.setGeometry(QtCore.QRect(10, 10, 341, 71))self.groupBox_3.setObjectName("groupBox_3")self.userName = QtWidgets.QLineEdit(self.groupBox_3)self.userName.setGeometry(QtCore.QRect(90, 30, 241, 31))self.userName.setObjectName("userName")self.label_2 = QtWidgets.QLabel(self.groupBox_3)self.label_2.setGeometry(QtCore.QRect(20, 30, 61, 31))self.label_2.setObjectName("label_2")self.groupBox_4 = QtWidgets.QGroupBox(self.tab_3)self.groupBox_4.setGeometry(QtCore.QRect(10, 90, 341, 91))self.groupBox_4.setObjectName("groupBox_4")self.label_3 = QtWidgets.QLabel(self.groupBox_4)self.label_3.setGeometry(QtCore.QRect(10, 30, 60, 16))self.label_3.setObjectName("label_3")self.mcDirText = QtWidgets.QLabel(self.groupBox_4)self.mcDirText.setGeometry(QtCore.QRect(50, 30, 281, 16))self.mcDirText.setObjectName("mcDirText")self.setMcDirButton = QtWidgets.QPushButton(self.groupBox_4)self.setMcDirButton.setGeometry(QtCore.QRect(12, 50, 321, 32))self.setMcDirButton.setObjectName("setMcDirButton")self.groupBox_5 = QtWidgets.QGroupBox(self.tab_3)self.groupBox_5.setGeometry(QtCore.QRect(10, 190, 201, 71))self.groupBox_5.setObjectName("groupBox_5")self.styleBox = QtWidgets.QComboBox(self.groupBox_5)self.styleBox.setGeometry(QtCore.QRect(10, 30, 181, 32))self.styleBox.setObjectName("styleBox")self.tabWidget.addTab(self.tab_3, "")self.stauts = QtWidgets.QLabel(self.centralwidget)self.stauts.setGeometry(QtCore.QRect(60, 310, 321, 31))self.stauts.setObjectName("stauts")self.label_4 = QtWidgets.QLabel(self.centralwidget)self.label_4.setGeometry(QtCore.QRect(10, 310, 41, 31))self.label_4.setObjectName("label_4")MainWindow.setCentralWidget(self.centralwidget)self.retranslateUi(MainWindow)self.tabWidget.setCurrentIndex(0)QtCore.QMetaObject.connectSlotsByName(MainWindow)def retranslateUi(self, MainWindow):_translate = QtCore.QCoreApplication.translateMainWindow.setWindowTitle(_translate("MainWindow", "Launcher Main"))self.groupBox.setTitle(_translate("MainWindow", "启动"))self.label.setText(_translate("MainWindow", "选择版本"))self.launchGameBtn.setText(_translate("MainWindow", "启动游戏"))self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "主页面"))self.groupBox_2.setTitle(_translate("MainWindow", "安装版本"))self.installGameButton.setText(_translate("MainWindow", "安装"))self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "下载"))self.groupBox_3.setTitle(_translate("MainWindow", "用户"))self.label_2.setText(_translate("MainWindow", "用户名"))self.groupBox_4.setTitle(_translate("MainWindow", "MC文件夹"))self.label_3.setText(_translate("MainWindow", "当前"))self.mcDirText.setText(_translate("MainWindow", "NONE"))self.setMcDirButton.setText(_translate("MainWindow", "选择..."))self.groupBox_5.setTitle(_translate("MainWindow", "主题样式"))self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3), _translate("MainWindow", "设置"))self.stauts.setText(_translate("MainWindow", "启动启动器"))self.label_4.setText(_translate("MainWindow", "状态:"))

功能:

改变界面颜色,文件路径,下载版本,启动游戏


截图:(没有骗你,是java版本,下载下来的,不是launcher或者其他地方的图片)

是不是很nice?这就是java版本。和原版一点也没有区别!

希望点个赞,关注一下我和 __小小的程序员__哦!

python也能开发minecraft启动器相关推荐

  1. |python|用tkinter做minecraft启动器 第一章:python配置

    哈啰啊,这是发的第一篇文章,做的不好,多多关照 好进入正题今天是配置python,先看后期的图片 好,我们首先得下载python(链接加载有点慢) python下载 | 传送门 | 然后点这个(红框框 ...

  2. Python探索之旅 | 第一部分第二课:安装Python和Python的常用开发软件

    作者 谢恩铭,公众号「程序员联盟」(微信号:coderhub). 转载请注明出处. 原文:https://www.jianshu.com/p/68fcd46254f5 <Python探索之旅&g ...

  3. 如何用Python做Web开发?——Django环境配置

    用Python做Web开发,Django框架是个非常好的起点.如何从零开始,配置好Django开发环境呢?本文带你一步步无痛上手. 概念 最近有个词儿很流行,叫做"全栈"(full ...

  4. 《Python 3程序开发指南(第2版•修订版)》——1.2 Python的关键要素

    本节书摘来自异步社区<Python 3程序开发指南(第2版•修订版)>一书中的第1章,第1.2节,作者[英]Mark Summerfield,王弘博,孙传庆 译,更多章节内容可以访问云栖社 ...

  5. python图形用户界面设计报告_19.1 Python图形用户界面开发工具包

    ,赠送一本"Python相关图书".咨询方式:加[51CTO-关老师付费群]523714201 验证消息:咨询赠书 本视频采用**Python 3.X版 本书是智捷课堂开发的立体化 ...

  6. pythonweb开发-如何用Python做Web开发?——Django环境配置

    用Python做Web开发,Django框架是个非常好的起点.如何从零开始,配置好Django开发环境呢?本文带你一步步无痛上手. 概念 最近有个词儿很流行,叫做"全栈"(full ...

  7. python利器手机版-将安卓手机打造成你的python全栈开发利器

    超神利器- 相信多数安卓用户都使用过Qpython这款移动端的Python编辑器吧?之前我也研究过一阵子这个工具,但因为一次简单的爬虫让我对它失望之极.Qpython不支持lxml这个模块,然而pyt ...

  8. python简单编程例子-中文方便就用中文编程!Python图形界面开发实例

    原标题:中文方便就用中文编程!Python图形界面开发实例 之前做的一个Python小程序,功能很简单,面对用户群也很窄,是五笔编码编.校人员使用的五笔编码编辑器. 这样的"周末" ...

  9. 不是python中用于开发用户界面的第三方库-模拟试卷C

    原标题:模拟试卷C 一.单项选择题 1. 按照"后进先出"原则组织数据的数据结构是____ 队列 栈 双向链表 二叉树 2. 以下选项的叙述中,正确的是 循环队列有队头和队尾两个指 ...

最新文章

  1. 建立YUM服务器CENTOS
  2. 数据查询语言(DQL)
  3. django富文本编辑器
  4. 二重指针、二维数组及二者如何进行赋值
  5. 计算机课ppt免费,第1课 认识计算机ppt课件.ppt
  6. 缠中说禅形态挖掘之五笔形态
  7. ubuntu-20.04.3-详细安装教程(图文)附下载地址
  8. jenkins 并发构建Android 报错:Gradle build daemon disappeared unexpectedly (it may have been killed or may
  9. CorelDRAW2022最新电脑版离线安装教程
  10. Unsupervised Time-Series Representation Learning with Iterative Bilinear Temporal-Spectral Fusion
  11. 《Netty权威指南》笔记 —— 第二十、二十一、二十二, 二十三章
  12. 刷主板bios改变机器码_主板BIOS升级超完整教程,一学就会!
  13. 百度UEditor编译器中获取HTML内容和纯文本,设置UEditor编辑器的内容
  14. 书香云集Pc版书籍导出
  15. 360浏览器模拟百度搜索引擎蜘蛛访问
  16. Gram矩阵+Gram矩阵和协方差矩阵的关系
  17. ngrok私有服务搭建(docker交叉编译)
  18. 老电脑安装XP时遇到问题的总结
  19. 面临公司变相裁员该如何应对
  20. 用于射频功率放大器线性化的多查找表数字预失真

热门文章

  1. libev:libevent的挑战者
  2. memcache 详解
  3. 用VB设计控制上网时间程序Java教程
  4. Ubuntu 配置源列表sources.list
  5. 计算机考研复试面试常问问题 计算机网络篇(上)
  6. “猫癣”“犇牛”木马病毒肆虐 专家提醒补漏洞
  7. 教你使用MATLAB制作一款 图形验证码 生成器(app designer)
  8. Group equivariant capsule networks(组等变胶囊网络) 论文翻译
  9. 又一个跨平台的快速app开发工具:AppArchitect
  10. 将批处理文件编译成可执行文件