0%

记录一次小开发

背景

前几星期的晚上,有位朋友打电话问我一个问题。给定一个总价,和若干物品的单价。求出每个物品采购的数量,使得采购总和刚好等于给定的总价。
例如这样:

他说:“他算了很久,都没有合适的结果。”我说:“电话不要挂断,我很快就帮你算出来。” 于是乎,我打开pycharm,几行python代码就算出来了合适的结果。(很快啊)

他说:“计算机太牛了,比人的效率高太多了。这样的问题,我经常在工地上遇到,以后遇到了还找你算。”

开发需求

既然是经常遇到问题,那是不是应该开发一个合适的用户程序,让用户更加方便地使用起来呢。我总不能把我的代码直接丢给人家,让人家直接运行啊。代码的运行需要一个开发环境,总不能让人家配置一套python或者c++什么的开发环境吧。所以我们需要开发一个简单的GUI程序。
总结一下当前比较火的GUI开发方向。移动端(主要设备是手机),浏览器,PC桌面,小程序。其实我对浏览器的网页开发一直是非常感兴趣的,因为跨平台,有vue,react等开发框架。但是浏览器需要service,所以我放弃啦。ok那就移动端吧,但是我这位兄弟用的是苹果手机,我用的是小米手机。而且我也没有苹果电脑。所以我放弃啦。那就只能PC桌面啦,而且他身边也有电脑。

开发

其实GUI开发一直是我弱项,整天把自己的学习精力放在探索计算机里没有黑魔法的事情上了。但是也不影响,看看文档就可以快速上手了。
简单画了一个布局,添加几个组件。几个小时就可以搞定。
为了支持可以动态添加物品,所以还需要一个递归的算法。自从看了SICP,对递归的理解更深了。递归代码也可以轻松拿捏。写之后才发现这个问题和著名的背包问题非常类似。所以算法是很重要,很核心的。

打包命令

1
pyinstaller -F main.py

测试



ok,能用。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import (QWidget, QPushButton, QLineEdit,
QInputDialog, QApplication, QLabel, QDialog, QDialogButtonBox, QVBoxLayout)
import sys
import time

f_ret = []
def f(total, price, ix, args = []):
p = price[ix - 1]
if ix == len(price):
if total % p == 0:
f_ret.append(args + [total // p])
return
for i in range(1, total // p):
f(total - p * i, price, ix + 1, args + [i])

class AnsDialog(QDialog):
def __init__(self, t, p):
super().__init__()
self.t = t
self.p = p
self.setWindowTitle("结果")

self.layout = QVBoxLayout()
for i in range(len(f_ret)):
ret = f_ret[i]
s = ""
for j in range(len(ret)):
s = s + str(ret[j]) + " * " + str(self.p[j]) + " + "
s = s[:-3] + ' = '
print(f"{s}{self.t}") # 输出到控制台窗口
message = QLabel(f"{s}{self.t}")
self.layout.addWidget(message)
self.setLayout(self.layout)


class Example(QWidget):

def __init__(self):
super().__init__()

self.initUI()

def initUI(self):
self.total_label = QLabel(self)
self.total_label.setText("总价")
self.total_label.move(20, 20)
self.total_price = QLineEdit(self)
self.total_price.move(50, 40)

self.unit_label = QLabel(self)
self.unit_label.setText("单价")
self.unit_label.move(20, 80)
self.unit_price_list = []
unit_price = QLineEdit(self)
unit_price.move(50, 110)
self.unit_price_list.append(unit_price)

self.add_btn = QPushButton('+', self)
self.add_btn.move(50, 80)
self.add_btn.clicked.connect(self.add_unit_price)

self.sub_btn = QPushButton('-', self)
self.sub_btn.move(120, 80)
self.sub_btn.clicked.connect(self.sub_unit_price)

self.calc_btn = QPushButton('计算', self)
self.calc_btn.move(200, 80)
self.calc_btn.clicked.connect(self.calc_price)

self.setGeometry(300, 300, 450, 350)
self.setWindowTitle('王工专用')
self.show()


def add_unit_price(self):
unit = self.unit_price_list[-1]
x, y = unit.x(), unit.y()

unit = QLineEdit(self)
unit.move(x, y + 25)
unit.show()
self.unit_price_list.append(unit)

def sub_unit_price(self):
if len(self.unit_price_list) > 1:
unit = self.unit_price_list.pop()
unit.close()
def calc_price(self):
total = int(self.total_price.text())
price = [i.text() for i in self.unit_price_list]
price = list(set(int(i) for i in price))
f_ret.clear()
f(total, price, 1)
dlg = AnsDialog(total, price)
dlg.exec()


def main():
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec())


if __name__ == '__main__':
main()