好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

使用fbs打包pyqt5本人亲自尝试过的

首先安装python3.6 安装教略 新建个文件夹(testfbs) 进入 testfbs目录下 在testfbs下打开控制台 创建python虚拟环境命令如下:

python -m venv venv 进入环境目录 命令如下:

cd venv/scripts/

在此环境激活环境命令如下:

activate.bat

activate python36

venv/scripts/在目录下执行安装fbs

pip install fbs -i https://pypi.doubanio测试数据/simple

接着new一个新窗口在testfbs目录下

执行下面命令创建项目(为什么这样因为你要使用虚拟环境中的fbs)

D:\testfbs\venv\Scripts\fbs startproject

执行命令之后就会出现输入项目名字之类的 填写后项目就算创建成功了

接着就是打开D:\testfbs\src\main\python目录

这个下会有一个main.py

下面是一个我打包2048的一个例子代码

#!/usr/bin/env?python#?-*-?coding:?utf-8?-*-from?fbs_runtime.application_context.PyQt5?import?ApplicationContextfrom?PyQt5.QtWidgets?import?QMainWindow,?QApplication,?QMessageBoxfrom?PyQt5.QtGui?import?QPainter,?QColor,?QFont,?QPenfrom?PyQt5.QtCore?import?Qt,?QRectimport?sysimport?osimport?copyimport?randomclass?GameForm(QMainWindow):
????def?__init__(self,?parent=None):
????????super(GameForm,?self).__init__(parent)
????????self.initUi()
????????#?定义各数字的背景颜色
????????self.colors?=?{0:?(204,?192,?179),?2:?(238,?228,?218),?4:?(237,?224,?200),
???????????????????????8:?(242,?177,?121),?16:?(245,?149,?99),?32:?(246,?124,?95),
???????????????????????64:?(246,?94,?59),?128:?(237,?207,?114),?256:?(237,?207,?114),
???????????????????????512:?(237,?207,?114),?1024:?(237,?207,?114),?2048:?(237,?207,?114),
???????????????????????4096:?(237,?207,?114),?8192:?(237,?207,?114),?16384:?(237,?207,?114),
???????????????????????32768:?(237,?207,?114),?65536:?(237,?207,?114),?131072:?(237,?207,?114),
???????????????????????262144:?(237,?207,?114),?524288:?(237,?207,?114),?1048576:?(237,?207,?114)}
????????self.initGameData()
????????self.chiese_grid?=?["","相遇",?"初识",?"爱慕",?"暧昧",?"试探",?"表白",?"尴尬",?"牵手",?"热恋",?"分手",?"",?"",?"",?"",?"",?"",?"",?]
????????self.chiese_grid1?=?["","北齐",?"北周",?"北魏",?"隋朝",?"唐朝",?"宋朝",?"明朝",?"清朝",?"民国",?"中国",?"",?"",?"",?"",?"",?"",?"",?]
????????self.chiese_grid2?=?["","相遇",?"初识",?"爱慕",?"暧昧",?"试探",?"表白",?"尴尬",?"牵手",?"热恋",?"分手",?"",?"",?"",?"",?"",?"",?"",?]


????def?is2powern(self,?s):
????????if?s==0:
????????????return?0
????????elif?s==1:
????????????return?1

????????for?i?in?range(1,100):
????????????if?2**i==s:
????????????????return?i????def?initUi(self):
????????self.setWindowTitle("2048")
????????self.resize(505,?720)
????????self.setFixedSize(self.width(),?self.height())
????????self.initGameOpt()

????def?initGameOpt(self):
????????'''?初始化游戏配置?'''
????????self.lbFont?=?QFont('SimSun',?12)??#?label字体
????????self.lgFont?=?QFont('SimSun',?50)??#?Logo字体
????????self.nmFont?=?QFont('SimSun',?36)??#?面板数字字体

????def?initGameData(self):
????????'''?初始化游戏数字?'''
????????self.data?=?[[0,?0,?0,?0],?[0,?0,?0,?0],?[0,?0,?0,?0],?[0,?0,?0,?0]]
????????count?=?0
????????while?count?<?2:
????????????row?=?random.randint(0,?len(self.data)?-?1)
????????????col?=?random.randint(0,?len(self.data[0])?-?1)
????????????if?self.data[row][col]?!=?0:
????????????????continue
????????????self.data[row][col]?=?2?if?random.randint(0,?1)?else?4
????????????count?+=?1

????????self.curScore?=?0
????????self.bstScore?=?0
????????#?载入最高得分
????????if?os.path.exists("bestscore.ini"):
????????????with?open("bestscore.ini",?"r")?as?f:
????????????????self.bstScore?=?int(f.read())

????def?paintEvent(self,?e):
????????'''?重写绘图事件?'''
????????qp?=?QPainter()
????????qp.begin(self)
????????self.drawGameGraph(qp)
????????qp.end()

????def?keyPressEvent(self,?e):
????????keyCode?=?e.key()
????????ret?=?False
????????if?keyCode?==?Qt.Key_Left:
????????????ret?=?self.move("Left")
????????elif?keyCode?==?Qt.Key_Right:
????????????ret?=?self.move("Right")
????????elif?keyCode?==?Qt.Key_Up:
????????????ret?=?self.move("Up")
????????elif?keyCode?==?Qt.Key_Down:
????????????ret?=?self.move("Down")
????????else:
????????????pass

????????if?ret:
????????????self.repaint()

????def?closeEvent(self,?e):
????????#?保存最高得分
????????with?open("bestscore.ini",?"w")?as?f:
????????????f.write(str(self.bstScore))

????def?drawGameGraph(self,?qp):
????????'''?绘制游戏图形?'''
????????self.drawLog(qp)
????????self.drawLabel(qp)
????????self.drawScore(qp)
????????self.drawBg(qp)
????????self.drawTiles(qp)

????def?drawScore(self,?qp):
????????'''?绘制得分?'''
????????qp.setFont(self.lbFont)
????????fontsize?=?self.lbFont.pointSize()
????????scoreLabelSize?=?len(u"SCORE")?*?fontsize
????????bestLabelSize?=?len(u"BEST")?*?fontsize
????????curScoreBoardMinW?=?15?*?2?+?scoreLabelSize??#?SCORE栏的最小宽度
????????bstScoreBoardMinW?=?15?*?2?+?bestLabelSize??#?BEST栏的最小宽度
????????curScoreSize?=?len(str(self.curScore))?*?fontsize
????????bstScoreSize?=?len(str(self.bstScore))?*?fontsize
????????curScoreBoardNedW?=?10?+?curScoreSize
????????bstScoreBoardNedW?=?10?+?bstScoreSize
????????curScoreBoardW?=?max(curScoreBoardMinW,?curScoreBoardNedW)
????????bstScoreBoardW?=?max(bstScoreBoardMinW,?bstScoreBoardNedW)
????????qp.setBrush(QColor(187,?173,?160))
????????qp.setPen(QColor(187,?173,?160))
????????qp.drawRect(505?-?15?-?bstScoreBoardW,?40,?bstScoreBoardW,?50)
????????qp.drawRect(505?-?15?-?bstScoreBoardW?-?5?-?curScoreBoardW,?40,?curScoreBoardW,?50)

????????bstLabelRect?=?QRect(505?-?15?-?bstScoreBoardW,?40,?bstScoreBoardW,?25)
????????bstScoreRect?=?QRect(505?-?15?-?bstScoreBoardW,?65,?bstScoreBoardW,?25)
????????scoerLabelRect?=?QRect(505?-?15?-?bstScoreBoardW?-?5?-?curScoreBoardW,?40,?curScoreBoardW,?25)
????????curScoreRect?=?QRect(505?-?15?-?bstScoreBoardW?-?5?-?curScoreBoardW,?65,?curScoreBoardW,?25)

????????qp.setPen(QColor(238,?228,?218))
????????qp.drawText(bstLabelRect,?Qt.AlignCenter,?u"BEST")
????????qp.drawText(scoerLabelRect,?Qt.AlignCenter,?u"SCORE")

????????qp.setPen(QColor(255,?255,?255))
????????qp.drawText(bstScoreRect,?Qt.AlignCenter,?str(self.bstScore))
????????qp.drawText(curScoreRect,?Qt.AlignCenter,?str(self.curScore))

????def?drawBg(self,?qp):
????????'''?绘制背景图?'''
????????col?=?QColor(187,?173,?160)
????????qp.setPen(col)

????????qp.setBrush(QColor(187,?173,?160))
????????qp.drawRect(15,?150,?475,?475)??#?绘制游戏区域

????def?drawLog(self,?qp):
????????'''?绘制Logo?'''
????????pen?=?QPen(QColor(255,?93,?29),?15)
????????qp.setFont(self.lgFont)
????????qp.setPen(pen)
????????qp.drawText(QRect(10,?0,?150,?130),?Qt.AlignCenter,?"2048")

????def?drawLabel(self,?qp):
????????'''?绘制所有标签信息?'''
????????qp.setFont(self.lbFont)
????????qp.setPen(QColor(119,?110,?101))
????????qp.drawText(15,?134,?u"合并相同数字,得到2048吧!")
????????qp.drawText(15,?660,?u"怎么玩:")
????????qp.drawText(45,?680,?u"用->?<-?上下左右箭头按键来移动方块.")
????????qp.drawText(45,?700,?u"当两个相同数字的方块碰到一起时,会合成一个!")

????def?drawTiles(self,?qp):
????????'''?绘制数字背景?'''
????????qp.setFont(self.nmFont)
????????for?row?in?range(4):
????????????for?col?in?range(4):
????????????????value?=?self.data[row][col]
????????????????color?=?self.colors[value]

????????????????qp.setPen(QColor(*color))
????????????????qp.setBrush(QColor(*color))
????????????????qp.drawRect(30?+?col?*?115,?165?+?row?*?115,?100,?100)??#?绘制数字的背景小方块
????????????????size?=?self.nmFont.pointSize()?*?len(str(value))??#?获取当前字体下显示数字的长度
????????????????#?根据尺寸调整字体大小
????????????????while?size?>?100?-?15?*?2:
????????????????????self.nmFont?=?QFont('SimSun',?self.nmFont.pointSize()?*?4?//?5)
????????????????????qp.setFont(self.nmFont)
????????????????????size?=?self.nmFont.pointSize()?*?len(str(value))??#?获取当前字体下显示数字的长度
????????????????print("[%d][%d]:?value[%d]?weight:?%d"?%?(row,?col,?value,?size))

????????????????#?显示非0数字
????????????????if?value?==?2?or?value?==?4:
????????????????????qp.setPen(QColor(119,?110,?101))??#?设置2和4数字的前景色
????????????????else:
????????????????????qp.setPen(QColor(255,?255,?255))??#?设置其他数字的前景色
????????????????if?value?!=?0:
????????????????????rect?=?QRect(30?+?col?*?115,?165?+?row?*?115,?100,?100)
????????????????????#?这里可以将其改为中文

????????????????????#?qp.drawText(rect,?Qt.AlignCenter,?str(value))
????????????????????print(value)
????????????????????qp.drawText(rect,?Qt.AlignCenter,?self.chiese_grid1[self.is2powern(value)])

????def?putTile(self):
????????'''?找到一个空位置(数值为0),并随机填充2或4?'''
????????available?=?[]
????????for?row?in?range(len(self.data)):
????????????for?col?in?range(len(self.data[0])):
????????????????if?self.data[row][col]?==?0:
????????????????????available.append((row,?col))
????????if?available:
????????????row,?col?=?available[random.randint(0,?len(available)?-?1)]
????????????self.data[row][col]?=?2?if?random.randint(0,?1)?else?4
????????????return?True
????????return?False

????def?merge(self,?row):
????????'''?合并一行或一列?'''
????????pair?=?False
????????newRow?=?[]
????????for?i?in?range(len(row)):
????????????if?pair:
????????????????newRow.append(2?*?row[i])
????????????????self.curScore?+=?2?*?row[i]
????????????????pair?=?False
????????????else:
????????????????#?可以和
????????????????if?i?+?1?<?len(row)?and?row[i]?==?row[i?+?1]:
????????????????????pair?=?True
????????????????else:
????????????????????#?不可以和
????????????????????newRow.append(row[i])
????????return?newRow????def?slideUpDown(self,?isUp):
????????'''?上下方向移动数字方格?'''
????????numRows?=?len(self.data)
????????numCols?=?len(self.data[0])
????????oldData?=?copy.deepcopy(self.data)

????????for?col?in?range(numCols):
????????????cvl?=?[]
????????????for?row?in?range(numRows):
????????????????if?self.data[row][col]?!=?0:
????????????????????cvl.append(self.data[row][col])??#?将列里面的非0元素提取出来

????????????if?len(cvl)?>=?2:
????????????????#?看看能不能合并
????????????????cvl?=?self.merge(cvl)??#?合并相同数字

????????????#?根据移动方向填充0
????????????for?i?in?range(numRows?-?len(cvl)):
????????????????if?isUp:
????????????????????cvl.append(0)
????????????????else:
????????????????????cvl.insert(0,?0)

????????????print("row=%d"?%?row)
????????????row?=?0
????????????for?row?in?range(numRows):
????????????????self.data[row][col]?=?cvl[row]

????????return?oldData?!=?self.data??#?返回数据是否发生了变化

????def?slideLeftRight(self,?isLeft):
????????'''?左右方向移动数字方格?'''
????????numRows?=?len(self.data)
????????numCols?=?len(self.data[0])
????????oldData?=?copy.deepcopy(self.data)

????????for?row?in?range(numRows):
????????????rvl?=?[]
????????????for?col?in?range(numCols):
????????????????if?self.data[row][col]?!=?0:
????????????????????rvl.append(self.data[row][col])

????????????if?len(rvl)?>=?2:
????????????????rvl?=?self.merge(rvl)

????????????for?i?in?range(numCols?-?len(rvl)):
????????????????if?isLeft:
????????????????????rvl.append(0)
????????????????else:
????????????????????rvl.insert(0,?0)

????????????col?=?0
????????????for?col?in?range(numCols):
????????????????self.data[row][col]?=?rvl[col]

????????return?oldData?!=?self.data????def?move(self,?direction):
????????'''?移动数字方格?'''
????????isMove?=?False
????????if?direction?==?"Up":
????????????isMove?=?self.slideUpDown(True)
????????elif?direction?==?"Down":
????????????isMove?=?self.slideUpDown(False)
????????elif?direction?==?"Left":
????????????isMove?=?self.slideLeftRight(True)
????????elif?direction?==?"Right":
????????????isMove?=?self.slideLeftRight(False)
????????else:
????????????pass

????????if?not?isMove:
????????????return?False

????????self.putTile()??#?新增一个数字
????????if?self.curScore?>?self.bstScore:
????????????self.bstScore?=?self.curScore????????if?self.isGameOver():
????????????button?=?QMessageBox.warning(self,?"Warning",?u"游戏结束,是否重新开始?",
?????????????????????????????????????????QMessageBox.Ok?|?QMessageBox.No,
?????????????????????????????????????????QMessageBox.Ok)

????????????if?button?==?QMessageBox.Ok:
????????????????self.initGameOpt()
????????????????bstScore?=?self.bstScore
????????????????self.initGameData()
????????????????self.bstScore?=?bstScore????????????????return?True
????????????else:
????????????????return?False
????????else:
????????????return?True

????def?isGameOver(self):
????????'''?判断游戏是否无法继续?'''
????????copyData?=?copy.deepcopy(self.data)??#?先暂存数据值
????????curScore?=?self.curScore

????????flag?=?False
????????if?not?self.slideUpDown(True)?and?not?self.slideUpDown(False)?and?\????????????????not?self.slideLeftRight(True)?and?not?self.slideLeftRight(False):
????????????flag?=?True??#?全部方向都不能再移动
????????self.curScore?=?curScore????????if?not?flag:
????????????self.data?=?copyData??#?仍可以移动,则恢复原来数据
????????return?flagif?__name__?==?'__main__':
????appctxt?=?ApplicationContext()??#?1.?Instantiate?ApplicationContext
????app?=?QApplication(sys.argv)
????form?=?GameForm()
????form.show()
????exit_code?=?appctxt.app.exec_()??#?2.?Invoke?appctxt.app.exec_()
????sys.exit(exit_code)

其实main.py中的代码是一个最小的打包例子重点就是这几句

from?fbs_runtime.application_context.PyQt5?import?ApplicationContextif?__name__?==?'__main__':
????appctxt?=?ApplicationContext()??#?1.?Instantiate?ApplicationContext
????app?=?QApplication(sys.argv)

????#?下这两句是调用你自己的程序其他不变
????form?=?GameForm()
????form.show()
????#?上这两句是调用你自己的程序其他不变
????exit_code?=?appctxt.app.exec_()??#?2.?Invoke?appctxt.app.exec_()
????sys.exit(exit_code)

当前目录下还有一个图标,你可以直接将自己的图标命名为这个官方给的图标是一样的这样就可以了

还有就会说资源路径问题(比如你写的是src/test.jpg)那么就这样写

import?os
basepath=os.path.split(os.path.abspath(__file__))[0]path=os.path.join(basepath,"src/test.jpg")

接着就执行 执行一定会报错 哪里错改哪里最常现的就是缺少包

D:\testfbs\venv\Scripts\fbs run

那么就使用如下操作安装你的包 继续run 直到跑起来

D:\testfbs\venv\Scripts\pip install PyQt5-sip -i https://pypi.doubanio测试数据/simple D:\testfbs\venv\Scripts\pip install PyQt5 -i https://pypi.doubanio测试数据/simple

代码跑成功后 直接执行下面命令 D:\testfbs\venv\Scripts\fbs freeze

执行后你会在testfbs目录下看到target文件夹 在这个文件夹中会两个文件夹一个是PyInstaller和另一个也就是你之前填写的项目名字假如你起名wei wei目录下就会有一个可执行文件好那么在打开执行文件之前 你要将资源(src)整个文件夹直接粘到此目录下 如果不出意外你的软件就打包成功了 你可以直接将target这个文件分享给任何人当然要是同一平台的

查看更多关于使用fbs打包pyqt5本人亲自尝试过的的详细内容...

  阅读:54次