微信小程序-科学计算器微信小程序javapython
目录
微信小程序 科学计算器(微信小程序+java+python)
微信小程序之科学计算器 (微信小程序+java+python)
先把自己的小程序和页面贴出来
1.前后端实现步骤:
1.前端采用的就是微信小程序开发工具,后端采用的是以springboot为基础,调用python中的Math类进行开发。
2.开发中遇到的难题不多
(1)小程序中主要就是光标的定位,如何在对应位置进行增删。
(2)后端遇到的问题,将 python 代码集成到 java 中,总体难度不大。(全网都是教程)
(3)在url中存在转义字符 如 ‘+’ 等问题处理方案。
(4) 发布到linux遇到的坑。理论上来讲,java调用的pythond 的包,不存在平台的适用性,但是作死的将python文件命名为中文,导致一直调用失败。
2.微信小程序 代码展示:
xxx.wxml
<view class="page">
<view class="section">
<textarea focus="true" auto-focus cursor="1" bindfocus="bindfocus" bindinput="bindinput2" data-set="{{textarea}}" style=" width:100%;background-color: #ddd;" value="{{textarea}}">{{textareaa}}</textarea>
<!-- </view> -->
<view value="{{result}}">运行结果为:{{result}}</view>
<!-- <textarea focus="true" auto-focus cursor="1" style="background-color: crimson;" bindinput="ceshi_textarea" data-set="{{textarea}}" value="{{textarea}}"></textarea> -->
<!-- <view style="width: 100%;height:12%;background-color: #222;">
<text style=" width:100%;height:5%;" value="{{result}}"></text>
</view> -->
<view class="view_1" style=" width:100%;background-color: #ddd;">
<view >
<button class="btn_1" bindtap="btn_zuo">←</button>
<button class="btn_1" bindtap="btn_left">delete_left</button>
</view>
<view>
<button class="btn_1" bindtap="btn_you">→</button>
<button class="btn_1" bindtap="btn_clear">delete_all</button>
</view>
</view>
<view class="tui-table-view">
<view class='sort-ct-item' wx:for='{{list_1}}' wx:for-index="indexs" wx:for-item="items" wx:key="indexs">
<view class="tui-col-1" data-set="{{items}}" bindtap="copyBtn">
<view class='price'><text style="" data-set="{{items}}">{{items}}</text></view>
</view>
</view>
<view style="width: 100%;"></view>
<view class='sort-ct-item' wx:for='{{list_2}}' wx:for-index="indexs" wx:for-item="items" wx:key="indexs">
<view class="tui-col-3" data-set="{{items}}" bindtap="copyBtn">
<view class='price'><text style="border-radius: 5rpx;">{{items}}</text></view>
</view>
</view>
</view>
<button bindtap="btn_submit">提交</button>
</view>
</view>
wxss.wxml
/* pages/kexuejisuanqi/kexuejisuanqi.wxss */
/* pages/科学计算器/科学计算器.wxss */
.page{
width: 100%;
height: 100%;
}
.section{
position: fixed;
bottom: 20rpx;
background-color: burlywood;
}
.tui-table-view{
display: -webkit-flex;
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
width: 100%;
}
.tui-col-3{
/* flex: 0 0 auto; */
/* width: 19%; */
text-align: center;
color: #797979;
padding: 15rpx ;
margin-top: 10rpx;
margin-bottom: 10rpx;
font-size: 30rpx;
border: 4rpx solid black;
}
.tui-col-1{
/* flex: 0 0 auto; */
/* width: 19%; */
text-align: center;
color: #797979;
padding: 18rpx ;
margin-top: 10rpx;
margin-bottom: 10rpx;
font-size: 40rpx;
border: 4rpx solid black;
}
.view_1{
display: flex;
}
.btn_1{
border-radius: 15rpx;
padding: 10rpx 0;
margin: 15rpx;
font-family:'Courier New', Courier, monospace;
}
xxx.js
// pages/kexuejisuanqi/kexuejisuanqi.js
var app = getApp()
Page({
/**
* 页面的初始数据
*/
data: {
list_1: [
'1', '2', '3', '4',
'5', '6', '7', '8',
'9', '0',
'.', '+', '-', '*', '/',
'(', ')'
],
list_2: [
// 绝对值
'fabs',
//阶乘 整数阶乘
'factorial',
//e 次 x 幂
'exp',
//返回 x 的自然对数(底为 e )
'log',
//将返回 x 的 y 次幂 两个参数
'pow',
//返回 x 的平方根。
'sqrt',
//三角函数 //返回以弧度为单位的 x 的反余弦值。 结果范围在 0 到 pi 之间。
//返回以弧度为单位的 x 的反余弦值。 结果范围在 0 到 pi 之间。
'acos',
//返回以弧度为单位的 x 的反正弦值。 结果范围在 -pi/2 到 pi/2 之间。
'asin',
//返回以弧度为单位的 x 的反正切值。 结果范围在 -pi/2 到 pi/2 之间。
'atan',
//返回 x 弧度的余弦值。
'sin',
'cos',
'tan',
//角度弧度转换
//将角度 x 从弧度转换为度数
'degrees',
//角度 x 从度数转换为弧度。
'radians',
//双曲函数
//返回 x 的反双曲余弦值
'acosh',
//返回 x 的反双曲正弦值。
'asinh',
//返回 x 的反双曲正切值。
'atanh',
//返回 x 的双曲余弦值。
'cosh',
//返回 x 的双曲正弦值。
'sinh',
//返回 x 的双曲正切值。
'tanh',
//返回 x 处的 伽马函数 值。
'gamma',
// 返回Gamma函数在 x 绝对值的自然对数。
'lgamma',
//常量
//pi
'π',
//e
'e',
//lgamma
'lgamma',
],
textarea: "",
cursor: 0,
guangbiao: false,
guangbiaoqidong: false,
result:''
},
btn_left:function(){
console.log('btn_left')
var textarea = this.data.textarea;
var str = textarea.substring(0, this.data.cursor - 1)
var str2 = textarea.substring(this.data.cursor)
var str3 = str + str2;
this.setData({
textarea: str3,
cursor: this.data.cursor - 1
})
},
//固定位置插入| 光标
btn_charu2: function () {
var text = this.data.textarea;
var t1 = this.data.textarea.substring(0, this.data.cursor);
var t2 = this.data.textarea.substring(this.data.cursor)
this.setData({
textarea: t1 + "|" + t2,
// cursor: this.data.cursor + 1
})
},
//删除固定位置的光标 |
btn_delete2: function () {
var that = this
for (var i = 0; i < that.data.textarea.length; i++) {
// console.log(i)
if (that.data.textarea.charAt(i) == '|') {
that.data.textarea = that.data.textarea.replace('|', '')
}
}
},
//光标向左移动
btn_zuo: function (e) {
if (this.data.guangbiaoqidong == false) {
this.data.guangbiaoqidong = true
this.sendCode(e);
}
// this.hidden_view()
console.log(this.data.cursor, this.data.textarea.charAt(this.data.cursor))
this.setData({
cursor: this.data.cursor - 1
})
},
//光标向右移动
btn_you: function (e) {
if (this.data.guangbiaoqidong == false) {
this.data.guangbiaoqidong = true
this.sendCode(e);
}
console.log(this.data.cursor)
this.setData({
cursor: this.data.cursor + 1
})
},
//光标 定时器
sendCode: function (e) {
var that = this;
setInterval(function () {
if (that.data.guangbiao == false) {
// console.log('1')
that.data.guangbiao = true
that.btn_charu2()
} else {
// console.log('2')
that.data.guangbiao = false
that.btn_delete2()
}
}, 100)
},
//删除 | 定时器
deleteCode: function (e) {
var that = this;
setInterval(function () {
for (var i = 0; i < that.data.textarea.length; i++) {
if (that.data.cursor == i) {} else {
if (this.data.textarea.charAt(this.data.cursor) == '|') {
that.data.textarea.replace('|', '')
}
}
}
if (that.data.guangbiao == false) {}
}, 100)
},
btn_clear: function () {
this.setData({
textarea: ""
})
},
/**
* 获取点击的 按钮 ,并将值显示在 textarea
*/
copyBtn: function (e) {
var that = this;
var now_args = e.currentTarget.dataset.set
if (now_args == 'log'||now_args == 'pow') {
now_args = now_args + '(?,?)'
}
if (now_args != "." && now_args != "π" && now_args != "e" && now_args != "lgamma" && now_args != "0" && now_args != "1" && now_args != "2" && now_args != "3" && now_args != "4" && now_args != "5" && now_args != "6" && now_args != "7" && now_args != "8" && now_args != "9" && now_args != "(" && now_args != ")" && now_args != "/" && now_args != "*" && now_args != "+" && now_args != "-" && now_args != "log(?,?)"&& now_args != "pow(?,?)") {
now_args = now_args + '(?)'
} else {
}
//将值添加到光标处:
var textarea = this.data.textarea;
var str = textarea.substring(0, this.data.cursor)
var str2 = textarea.substring(this.data.cursor)
// var textarea = "";
if (this.data.cursor == 0) {
var textarea = str2 + now_args;
this.setData({
textarea: textarea
})
} else {
var textarea = str + now_args + str2;
this.setData({
textarea: textarea
})
// textarea = str + now_args + str2;
}
// var textarea = this.data.textarea + now_args;
},
bindTextAreaBlur: function (args) {
console.log("bindTextAreaBlur!!!->" + args)
},
btn_submit: function (args) {
console.log('btn_submit->args=', args)
var that = this
this.setData({
textarea: this.data.textarea
})
console.log("textarea=", this.data.textarea)
for (var i = 0; i < that.data.textarea.length; i++) {
// console.log(i)
if (that.data.textarea.charAt(i) == '|') {
that.data.textarea = that.data.textarea.replace('|', '')
}
if (that.data.textarea.charAt(i) == '+') {
that.data.textarea = that.data.textarea.replace('+', '%2B')
}
if (that.data.textarea.charAt(i) == '(') {
that.data.textarea = that.data.textarea.replace('(', '%28')
}
if (that.data.textarea.charAt(i) == ')') {
that.data.textarea = that.data.textarea.replace(')', '%29')
}
}
var biaodashi = this.data.textarea;
console.log(app.globalData.address + "getNum?content='" + that.data.textarea + "'");
wx.request({
url: app.globalData.address + 'getNum?content="' + that.data.textarea + '"',
// data:{
// content:that.data.textarea
// },
timeout: 150000,
success: function (args) {
console.log('success=>', args)
that.setData({
result: args.data
})
}
})
that.btn_clear()
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})
3.springboot重点代码展示
1.先把python的jar包放上来吧
<dependency>
<groupId>org.python</groupId>
<artifactId>jython-standalone</artifactId>
<version>2.7.2</version>
</dependency>
2.controller 类
该类接收来自网络上的包
import com.example.demo.Util.JiSuan_Util;
import org.python.antlr.ast.Str;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class JiSuanQiController {
@RequestMapping("getNum")
public @ResponseBody
String getJiSuanQi(@RequestParam(value = "content",required = false) String content){
//主要处理一些出现的字符,
content=content.replace("\"","");
content=content.replace("|","");
//exp是因为自己代码的匹配原则,与e冲突。
content=content.replace("exp","ttt");
//三个是转义字符传递
content=content.replace("%2B","+");
content=content.replace("%28","(");
content=content.replace("%29",")");
System.out.println(content);
Object num=JiSuan_Util.getNum(content);
System.out.println("JiSuan_Util--->"+num);
return num.toString();
}
}
3.两个工具类,实现连接python,及接收返回结果
(1) JiSuan_Util.java
import org.python.core.PyFunction;
import org.python.core.PyObject;
import org.python.core.PyString;
import org.python.util.PythonInterpreter;
/**
* 实现功能 将前端传进来的表达式 ,进行优化 函数表达式 前面加上 math. 关键字 提交 python处理
*/
public class JiSuan_Util {
public static PythonInterpreter interpreter = new PythonInterpreter();
/**
* python 处理 表达式 并返回结果
*/
public static Object getNum(String expression){
interpreter.execfile("/jisuanqi.py");
// interpreter.execfile("D:\\D\\python空间\\微信小程序\\计算器\\计算器.py");
// 第一个参数为期望获得的函数(变量)的名字,第二个参数为期望返回的对象类型
PyFunction pyFunction = interpreter.get("add", PyFunction.class);
//调用函数,如果函数需要参数,在Java中必须先将参数转化为对应的“Python类型”
PyObject pyobj = pyFunction.__call__(new PyString(processExpression(expression)));
System.out.println("the anwser is: " + pyobj);
return pyobj;
}
/**
* 加工表达式
*/
public static String processExpression(String expression){
System.out.println("processExpression->"+expression);
String str = expression;
for(int i = 0; i< MyMath.getMyMath().size(); i++){
str = str.replace(MyMath.getMyMath().get(i).getWx(),MyMath.getMyMath().get(i).getPython());
System.out.println("str->"+str);
}
System.out.println(str);
return str;
}
}
(2)MyMath.java
import java.util.ArrayList;
public class MyMath {
public String wx;
public String python;
public MyMath(String wx, String python) {
this.wx = wx;
this.python = python;
}
public String getWx() {
return wx;
}
public void setWx(String wx) {
this.wx = wx;
}
public String getPython() {
return python;
}
public void setPython(String python) {
this.python = python;
}
@Override
public String toString() {
return "MyMath{" +
"wx='" + wx + '\'' +
", python='" + python + '\'' +
'}';
}
/**
* 注:pow 函数为两个参数
* @return
*/
public static ArrayList<MyMath> getMyMath() {
ArrayList<MyMath> list = new ArrayList<MyMath>();
//绝对值
list.add(new MyMath("fabs","math.fabs"));
//以一个整数返回 x 的阶乘。 如果 x 不是整数或为负数时则将引发 ValueError。
list.add(new MyMath("factorial","math.factorial"));
//返回给定的整数参数的最大公约数。 如果有一个参数非零,则返回值将是能同时整除所有参数的最大正整数。 如果所有参数为零,则返回值为 0。 不带参数的 gcd() 返回 0。
list.add(new MyMath("gcd","math.gcd"));
//返回给定的整数参数的最小公倍数。 如果所有参数均非零,则返回值将是为所有参数的整数倍的最小正整数。 如果参数之一为零,则返回值为 0。 不带参数的 lcm() 返回 1。
list.add(new MyMath("lcm","math.lcm"));
//使用一个参数,返回 x 的自然对数(底为 e )。[自定义补充:必须为一个参数]
//将返回 x 的 y 次幂。 该值参数为两个
list.add(new MyMath("pow","math.pow"));
//返回 x 的平方根。
list.add(new MyMath("sqrt","math.sqrt"));
//三角函数
//返回以弧度为单位的 x 的反余弦值。 结果范围在 0 到 pi 之间。
list.add(new MyMath("acos","math.acos"));
//返回以弧度为单位的 x 的反正弦值。 结果范围在 -pi/2 到 pi/2 之间。
list.add(new MyMath("asin","math.asin"));
//返回以弧度为单位的 x 的反正切值。 结果范围在 -pi/2 到 pi/2 之间。
list.add(new MyMath("atan","math.atan"));
//返回 x 弧度的余弦值。
list.add(new MyMath("cos","math.cos"));
list.add(new MyMath("sin","math.sin"));
list.add(new MyMath("atan","math.atan"));
//角度弧度转换
//将角度 x 从弧度转换为度数
list.add(new MyMath("degrees","math.degrees"));
//角度 x 从度数转换为弧度。将
list.add(new MyMath("radians","math.radians"));
//双曲函数:
//返回 x 的反双曲余弦值
list.add(new MyMath("acosh","math.acosh"));
//返回 x 的反双曲正弦值。
list.add(new MyMath("asinh","math.asinh"));
//返回 x 的反双曲正切值。
list.add(new MyMath("atanh","math.atanh"));
//返回 x 的双曲余弦值。
list.add(new MyMath("cosh","math.cosh"));
//返回 x 的双曲正弦值。
list.add(new MyMath("sinh","math.sinh"));
//返回 x 的双曲正切值。
list.add(new MyMath("tanh","math.tanh"));
//返回 x 处的 伽马函数 值。
list.add(new MyMath("gamma","math.gamma"));
//返回Gamma函数在 x 绝对值的自然对数。
list.add(new MyMath("lgamma","math.lgamma"));
//常量
list.add(new MyMath("π","math.pi"));
list.add(new MyMath("e","math.e"));
list.add(new MyMath("lgamma","math.lgamma"));
list.add(new MyMath("log","math.log"));
//返回 e 次 x 幂
list.add(new MyMath("ttt","math.exp"));
return list;
}
}
- python代码 很简单(三行)
import math
def calculator(a):
return eval(a)
四、心得
- 本文中 微信小程序 只是将算式表达式传递给java,由java处理完成,交给python计算结果。在这里,对算式表达式的处理,可以在三个地方,微信小程序,java,python。根据自己对哪个语言精通,可以调节。
- java中也有自己的math包,如果觉得python难,可以网上查阅一下。
- 微信小程序端 有个取巧指出,让用户自己书写函数,这样微信小程序 端将大大简单,但java 端难度将增大。