我是一个苦逼的辣鸡臭建模的,在日常苦逼打工中时常会用到旋转复制或者计算线段数。但作为一个没有强大心算能力的老年人,在遇到不规整的数的计算时就会显得力不从心、手足发虚。但恰巧我的工位电脑上没有计算器,由于电脑不能联网所以也不能在网上下载计算器工具。为了解决这个烦恼为广大建模同行提供便利,我趁年假用qt制作了这个计算器,以方便大家使用。由于代码较长,所以这里就不放源码了,需要下载可以到底部的下载链接。
这里分享一下我在制作这个工具时学习到的新知识,以方便初学者借鉴,如果你是大佬,请在心里嘲笑我,不要说出来。
首先来看在类方法中,如何将已有变量前缀和不可控的会变化的变量后缀结合起来生成一个完整变变量。使用exec()函数可以将字符串内容以代码形式运行,同时可以在里面使用字符串的操作函数。eval()函数也有相同效果,不同的是eval()会有返回值,返回这个字符串的内容。但exec()不会。
这个技巧很实用,比如要用某函数的传入参数作为变量名的一部分时,就可以使用它。
#循环放置0到9的按钮
for inf in range(10):
exec('self.but_{} = QtWidgets.QPushButton(u"{}")'.format(inf, inf))
exec('self.but_{}.setFixedSize(70, 70)'.format(inf))
exec('self.but_{}.setFont(QtGui.QFont("黑体", 60))'.format(inf))
这里我的目的是很方便的快速建立多个相似度很高的按钮,群友大佬小静儿提供了另一个方法。使用一个字典将按钮的名称和按钮本身储存起来,在使用时可以直接在字典里找到对应的按钮,避免使用多个变量。非常的先进。小静儿大佬的博客:http://smilejing.cn/

下面是QTextEdit的光标移动方法。使用self.textCursor()生成实例,通过该实例获取光标位置,使用切片可以在该位置生成需要输入的字符。但此时如果是从窗口的按钮ui填入字符,光标不会向后移动,所以需要手动设置光标位置到初始获取位置后的一位,因为每次输入的字符绝对只有一个。
def crea_tex(self, tex):
old_tex = self.input_tex.toPlainText()
cursor = self.input_tex.textCursor()
cru_pos = cursor.position() # 获取光标位置
self.input_tex.setText(old_tex[:cru_pos] + str(tex) + old_tex[cru_pos:])#在光标处插入新输入的内容
cursor.setPosition(cru_pos + 1)
self.input_tex.setTextCursor(cursor) # 移动光标到新输入的字符身后
这个工具的核心功能就是计算生成的字符算式。这里简单说一下思路。
先判断计算器内容是否有内容。没有则跳出。
再判断输入的内容中是否有不能参与计算的非法字符。有则跳出。这里的筛选方法很笨拙,应该有更好的办法,但我没有找到。其实就是懒得查
当没有问题后进入计算函数。并将计算结果放到输出框内。
def crea_run(self, *inf):
number_str = self.input_tex.toPlainText()#获取输入窗口内容
if number_str:#如果有内容就计算内容
str_lis = '0123456789.+-*/()'
for num_inf in number_str:#查看输入框中是否有非法字符
if num_inf not in str_lis:
print u'您输入的字符中有非法字符{}'.format(num_inf)
return False
else:
pass
number_str = self.brackets(number_str)
self.output_tex.setText(str(number_str))#并在输出框内填入内容
else:#如果没有内容就抛出提示
print u'你的输入框中没有式子。'
return False
这是整个计算函数的中枢。通过一直循环查找各层优先级达到分层解决计算问题。
首先是括号,这里拿括号会逐层从最底层的括号开始拿(正则表达式太难了,幸好我会面向ctrl c v编程)。
拿到括号时计算括号内容(注意乘除优先级),并把得数与括号外的内容结合。
直到没有括号优先级时按乘除优先级最后计算一次并返回得数。加减乘除函数我就不累述了,道理差不多。
def brackets(self, exp):
#循环查找是否有括号
while True:
exp_res = re.search(r"\([^()]+\)", exp)#查有没有括号,并把括号逐层提出来
if exp_res:#当有括号时
exp_group = exp_res.group()#括号的内容,包括括号
new_num = self.mulOrDiv(exp_group)
new_num = self.addOrSub(new_num)
exp = exp.replace(exp_group, str(new_num))#把括号外的字符和括号算出的内容重新组合
else:#如果没有括号 则直接抛出计算结果
num = self.mulOrDiv(exp)
num = self.addOrSub(num)
return num
这里是重写了QTextEdit的键盘回车换行信号,很多地方是固定写法,我对手写信号并不熟练,有意愿可以去看看智商帝的qt搬运教程https://www.bilibili.com/video/BV1dJ41157gV
这个类的作用是当我按下键盘的enter或return键时(虽然中国windows的键盘很多时候这两个键的功能是相同的,但美国键盘或mac的键盘这两个键的作用并不相同,一个是换行,一个是确定。)不触发默认的在QTextEdit中出现换行的行为,而是抛出一个反馈(可自定义),这个可以作为信号与我写好的生成得数的槽函数链接。
class MyTextEdit(QtWidgets.QTextEdit):
'''
重写textEdit控件的键盘回车信号,包括小键盘回车
'''
enter_pressed = QtCore.Signal(str)
def keyPressEvent(self, e):
super(MyTextEdit, self).keyPressEvent(e)
if e.key() == QtCore.Qt.Key_Enter:
self.enter_pressed.emit(u'得数为:')
elif e.key() == QtCore.Qt.Key_Return:
self.enter_pressed.emit(u'得数为:')
虽然这个计算器没有强悍的功能,甚至需要小心规范的使用,但写它最大的目的是锻炼代码能力和解决问题能力,并让我碌碌无为的一年里以在干一件正经事为结尾,来以此自我安慰或者说自我麻痹。
况且写工具首先应该保证工具能更快的投入项目参与生产,在解决主要问题后再想一些花里胡哨的效果去迭代它。如行业里的开发之神机器猫的TD十戒中所说的:完美的工具不存在。开发中长线工具是一个动态修正的过程。这里放入本戒链接:https://mp.weixin.qq.com/s/ua1zWyUjfQE3dst00yYLlg
另外放两篇还没关闭的参考文章:https://www.cnblogs.com/leixiaobai/p/10841266.htmlhttps://docs.python.org/3/library/stdtypes.html#string-methods
感谢您看到这里,我是一个梦想做td的模型应届生,希望这篇文章对您有一点点的帮助,如果我所说的和代码内容有不妥或更优选择,请在下方留言评论或发送到我的邮箱。我将万分感谢。