http://shedingkong.lofter.com/post/302b9d_16dab28
作者:caihaibin
网速测试工具编写
一、网速的测速原理为计算上传某一大小文件和下载某一大小文件时:
速度=大小/时间
二、误差影响多种:
网络环境(包括dns、执行脚本所需时间(包括服务器,客户端)、精细情况下,还包括文件头得相关信息。。。)、本地环境(不解释)
特别需要注意 gzip
三、设计:
1.把文件上传分两步来执行。第一步空上传。得到所需时间.
2.生成指定大小长度的文件,如:1024000长的字符串.
3.进行二次提交。后者时间减去第一次空上传的时间。得到1024000所需的实际时间。估算出上传的速度。
4.因为各种因素干扰。重复提交3~5次。取平均值。即当前客户端相对服务器的网速。
5.gzip解决方式(压缩算法大都是对相同内容进行压缩)
压缩过的文件。本身不容易再压缩,如jpg之类文件,测试下载,可以通过直接输出个定长的jpg文件。测试即可.
四、考虑网络不稳定:
1.剔除负值(头次请求高,二次请求慢,就会出现)
2.设置一个误差值。如 :30% 将多次的结果平均化,超过这误差值的结果剔除。再计算平均。
五、优化
1.使用swfupload 直接解析出上传时间。相对较准。
【转】265行代码实现第一人称游戏引擎 + 个人详细注解
http://www.php100.com/html/it/mobile/2014/0612/6971.html
玩才是学习的动力
背景分析
//一个圆圈弧度 //用来识别用户可视弧度 等等,绘制skybox时做图片截取处理. var CIRCLE = Math.PI * 2; var MOBILE = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i .test(navigator.userAgent) function Controls() { this.codes = { 37 : 'left', 39 : 'right', 38 : 'forward', 40 : 'backward' }; this.states = { 'left' : false, 'right' : false, 'forward' : false, 'backward' : false }; document.addEventListener('keydown', this.onKey.bind(this, true), false); document.addEventListener('keyup', this.onKey.bind(this, false), false); document.addEventListener('touchstart', this.onTouch.bind(this), false); document.addEventListener('touchmove', this.onTouch.bind(this), false); document.addEventListener('touchend', this.onTouchEnd.bind(this), false); } Controls.prototype.onTouch = function(e) { var t = e.touches[0]; this.onTouchEnd(e); if (t.pageY < window.innerHeight * 0.5) this.onKey(true, { keyCode : 38 }); else if (t.pageX < window.innerWidth * 0.5) this.onKey(true, { keyCode : 37 }); else if (t.pageY > window.innerWidth * 0.5) this.onKey(true, { keyCode : 39 }); }; Controls.prototype.onTouchEnd = function(e) { this.states = { 'left' : false, 'right' : false, 'forward' : false, 'backward' : false }; // 关闭默认事件 e.preventDefault(); // 关闭事件传递 e.stopPropagation(); }; Controls.prototype.onKey = function(val, e) { var state = this.codes[e.keyCode]; if (typeof state === 'undefined') return; this.states[state] = val; e.preventDefault && e.preventDefault(); e.stopPropagation && e.stopPropagation(); }; function Bitmap(src, width, height) { this.image = new Image(); this.image.src = src; this.width = width; this.height = height; } /** * * @param x * 坐标 * @param y * 坐标 * @param direction * 方向 * @returns {Player} */ function Player(x, y, direction) { this.x = x; this.y = y; this.direction = direction; // 武器 this.weapon = new Bitmap('knife_hand.png', 319, 320); this.paces = 0; } /** * 旋转 * * @param angle * 角度 */ Player.prototype.rotate = function(angle) { // 方向 this.direction = (this.direction + angle + CIRCLE) % (CIRCLE); }; /** * @param distance * 距离 */ Player.prototype.walk = function(distance, map) { var dx = Math.cos(this.direction) * distance; var dy = Math.sin(this.direction) * distance; if (map.get(this.x + dx, this.y) <= 0) this.x += dx; if (map.get(this.x, this.y + dy) <= 0) this.y += dy; this.paces += distance; }; Player.prototype.update = function(controls, map, seconds) { if (controls.left) this.rotate(-Math.PI * seconds); if (controls.right) this.rotate(Math.PI * seconds); if (controls.forward) this.walk(3 * seconds, map); if (controls.backward) this.walk(-3 * seconds, map); }; function Map(size) { // 地区大小 this.size = size; // 地区网格大小 this.wallGrid = new Uint8Array(size * size); // 天空画布大小 this.skybox = new Bitmap('deathvalley_panorama_sky.jpg', 4000, 1290); // 墙体画布大小 this.wallTexture = new Bitmap('wall_texture.jpg', 1024, 1024); this.light = 0; } Map.prototype.get = function(x, y) { x = Math.floor(x); y = Math.floor(y); if (x < 0 || x > this.size - 1 || y < 0 || y > this.size - 1) return -1; return this.wallGrid[y * this.size + x]; }; Map.prototype.randomize = function() { for ( var i = 0; i < this.size * this.size; i++) { this.wallGrid[i] = Math.random() < 0.3 ? 1 : 0; } }; /** * @point * @angle * @range 范围 */ Map.prototype.cast = function(point, angle, range) { var self = this; var sin = Math.sin(angle); var cos = Math.cos(angle); var noWall = { length2 : Infinity }; return ray({ x : point.x, y : point.y, height : 0, distance : 0 }); function ray(origin) { var stepX = step(sin, cos, origin.x, origin.y); var stepY = step(cos, sin, origin.y, origin.x, true); var nextStep = stepX.length2 < stepY.length2 ? inspect(stepX, 1, 0, origin.distance, stepX.y) : inspect(stepY, 0, 1, origin.distance, stepY.x); if (nextStep.distance > range) return [ origin ]; return [ origin ].concat(ray(nextStep)); } function step(rise, run, x, y, inverted) { if (run === 0) return noWall; var dx = run > 0 ? Math.floor(x + 1) - x : Math.ceil(x - 1) - x; var dy = dx * (rise / run); return { x : inverted ? y + dy : x + dx, y : inverted ? x + dx : y + dy, length2 : dx * dx + dy * dy }; } function inspect(step, shiftX, shiftY, distance, offset) { var dx = cos < 0 ? shiftX : 0; var dy = sin < 0 ? shiftY : 0; step.height = self.get(step.x - dx, step.y - dy); step.distance = distance + Math.sqrt(step.length2); if (shiftX) step.shading = cos < 0 ? 2 : 0; else step.shading = sin < 0 ? 2 : 1; step.offset = offset - Math.floor(offset); return step; } }; /** * 模拟闪电的时间间隔 this.light 为当前地区的亮度值 */ Map.prototype.update = function(seconds) { return; if (this.light > 0)// 按时间把亮度调低.当为最暗时,用0表示 this.light = Math.max(this.light - 10 * seconds, 0); else if (Math.random() * 5 < seconds) this.light = 2;// 按某概率 出现闪电 }; function Camera(canvas, resolution, fov) { // 画布 this.ctx = canvas.getContext('2d'); // 通过style 将 画面强制放大,填充屏幕。画面越精细,速度越慢,反之则画面模糊,但是速度快。默认大小为0.5 this.width = canvas.width = window.innerWidth * 0.5; this.height = canvas.height = window.innerHeight * 0.5; this.resolution = resolution; this.spacing = this.width / resolution; // 视角 为固定 0.4*pi this.fov = fov; this.range = MOBILE ? 8 : 14; this.lightRange = 5; // this.scale = (this.width + this.height) / 1200; } Camera.prototype.render = function(player, map) { // 单纯只是计算出闭合后。图片的相关特征,做背景 this.drawSky(player.direction, map.skybox, map.light); // 重点计算 // this.drawColumns(player, map); // 玩家武器图,只是 一张晃动的图 // this.drawWeapon(player.weapon, player.paces); }; /** * direction 方向 (摄像头[用户角度方向]) sky 天空元素 (闭合状态下[图,首尾相连,形成的一圈为360度,即2*pi=CIRCLE ]。) * ambient 环境 (遮罩层,用来降低光线) */ Camera.prototype.drawSky = function(direction, sky, ambient) { // 计算出当前背景图的可视范围 this.fov(可视范围) // 不清楚这里的计算原理。 var width = this.width * (CIRCLE / this.fov); // 2/0.4 // 旋转偏角 图片左边的部分偏移 // 宽度 direction 为当前视角弧度 var left = -width * direction / CIRCLE; this.ctx.save(); this.ctx.drawImage(sky.image, left, 0, width, this.height); if (left < width - this.width) { // console.log(left,direction / CIRCLE); this.ctx.drawImage(sky.image, left + width, 0, width, this.height); } // 一个遮罩层。让背景变亮或暗 , 即 map.ligth 配合闪电,做地面的渲染处理 if (ambient > 0) { this.ctx.fillStyle = '#ffffff'; this.ctx.globalAlpha = ambient * 0.1; this.ctx.fillRect(0, this.height * 0.5, this.width, this.height * 0.5); } this.ctx.restore(); }; Camera.prototype.drawColumns = function(player, map) { this.ctx.save(); for ( var column = 0; column < this.resolution; column++) { var angle = this.fov * (column / this.resolution - 0.5); var ray = map.cast(player, player.direction + angle, this.range); this.drawColumn(column, ray, angle, map); } this.ctx.restore(); }; Camera.prototype.drawWeapon = function(weapon, paces) { var bobX = Math.cos(paces * 2) * this.scale * 6; var bobY = Math.sin(paces * 4) * this.scale * 6; var left = this.width * 0.66 + bobX; var top = this.height * 0.6 + bobY; this.ctx.drawImage(weapon.image, left, top, weapon.width * this.scale, weapon.height * this.scale); }; Camera.prototype.drawColumn = function(column, ray, angle, map) { var ctx = this.ctx; var texture = map.wallTexture; var left = Math.floor(column * this.spacing); var width = Math.ceil(this.spacing); var hit = -1; while (++hit < ray.length && ray[hit].height <= 0) ; for ( var s = ray.length - 1; s >= 0; s--) { var step = ray[s]; var rainDrops = Math.pow(Math.random(), 3) * s; var rain = (rainDrops > 0) && this.project(0.1, angle, step.distance); if (s === hit) { var textureX = Math.floor(texture.width * step.offset); var wall = this.project(step.height, angle, step.distance); ctx.globalAlpha = 1; ctx.drawImage(texture.image, textureX, 0, 1, texture.height, left, wall.top, width, wall.height); ctx.fillStyle = '#000000'; ctx.globalAlpha = Math.max((step.distance + step.shading) / this.lightRange - map.light, 0); ctx.fillRect(left, wall.top, width, wall.height); } ctx.fillStyle = '#ffffff'; ctx.globalAlpha = 0.15; while (--rainDrops > 0) ctx.fillRect(left, Math.random() * rain.top, 1, rain.height); } }; Camera.prototype.project = function(height, angle, distance) { var z = distance * Math.cos(angle); var wallHeight = this.height * height / z; var bottom = this.height / 2 * (1 + 1 / z); return { top : bottom - wallHeight, height : wallHeight }; }; function GameLoop() { this.frame = this.frame.bind(this); this.lastTime = 0; this.callback = function() { }; } GameLoop.prototype.start = function(callback) { this.callback = callback; requestAnimationFrame(this.frame); }; GameLoop.prototype.frame = function(time) { var seconds = (time - this.lastTime) / 1000; this.lastTime = time; if (seconds < 0.2) this.callback(seconds); requestAnimationFrame(this.frame); }; var display = document.getElementById('display'); var player = new Player(15.3, -1.2, Math.PI * 0.3); var map = new Map(32); var controls = new Controls(); var camera = new Camera(display, MOBILE ? 160 : 320, Math.PI * 0.4); var loop = new GameLoop(); map.randomize(); // 系统自动循环时,自动调整时间 seconds 时间间隔长度 . loop.start(function frame(seconds) { map.update(seconds); player.update(controls.states, map, seconds); camera.render(player, map); });
武器分析
//一个圆圈弧度 //用来识别用户可视弧度 等等,绘制skybox时做图片截取处理. var CIRCLE = Math.PI * 2; var MOBILE = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i .test(navigator.userAgent) function Controls() { this.codes = { 37 : 'left', 39 : 'right', 38 : 'forward', 40 : 'backward' }; this.states = { 'left' : false, 'right' : false, 'forward' : false, 'backward' : false }; document.addEventListener('keydown', this.onKey.bind(this, true), false); document.addEventListener('keyup', this.onKey.bind(this, false), false); document.addEventListener('touchstart', this.onTouch.bind(this), false); document.addEventListener('touchmove', this.onTouch.bind(this), false); document.addEventListener('touchend', this.onTouchEnd.bind(this), false); } Controls.prototype.onTouch = function(e) { var t = e.touches[0]; this.onTouchEnd(e); if (t.pageY < window.innerHeight * 0.5) this.onKey(true, { keyCode : 38 }); else if (t.pageX < window.innerWidth * 0.5) this.onKey(true, { keyCode : 37 }); else if (t.pageY > window.innerWidth * 0.5) this.onKey(true, { keyCode : 39 }); }; Controls.prototype.onTouchEnd = function(e) { this.states = { 'left' : false, 'right' : false, 'forward' : false, 'backward' : false }; // 关闭默认事件 e.preventDefault(); // 关闭事件传递 e.stopPropagation(); }; Controls.prototype.onKey = function(val, e) { var state = this.codes[e.keyCode]; if (typeof state === 'undefined') return; this.states[state] = val; e.preventDefault && e.preventDefault(); e.stopPropagation && e.stopPropagation(); }; function Bitmap(src, width, height) { this.image = new Image(); this.image.src = src; this.width = width; this.height = height; } /** * * @param x * 坐标 * @param y * 坐标 * @param direction * 方向 * @returns {Player} */ function Player(x, y, direction) { this.x = x; this.y = y; this.direction = direction; // 武器 this.weapon = new Bitmap('knife_hand.png', 319, 320); this.paces = 0; } /** * 旋转 * * @param angle * 角度 */ Player.prototype.rotate = function(angle) { // 方向 this.direction = (this.direction + angle + CIRCLE) % (CIRCLE); }; /** * @param distance * 距离 */ Player.prototype.walk = function(distance, map) { var dx = Math.cos(this.direction) * distance; var dy = Math.sin(this.direction) * distance; if (map.get(this.x + dx, this.y) <= 0) this.x += dx; if (map.get(this.x, this.y + dy) <= 0) this.y += dy; //前进的距离。步数 //旋转不算 this.paces += distance; }; Player.prototype.update = function(controls, map, seconds) { if (controls.left) this.rotate(-Math.PI * seconds); if (controls.right) this.rotate(Math.PI * seconds); if (controls.forward) this.walk(3 * seconds, map); if (controls.backward) this.walk(-3 * seconds, map); }; function Map(size) { // 地区大小 this.size = size; // 地区网格大小 this.wallGrid = new Uint8Array(size * size); // 天空画布大小 this.skybox = new Bitmap('deathvalley_panorama.jpg', 4000, 1290); // 墙体画布大小 this.wallTexture = new Bitmap('wall_texture.jpg', 1024, 1024); this.light = 0; } Map.prototype.get = function(x, y) { x = Math.floor(x); y = Math.floor(y); if (x < 0 || x > this.size - 1 || y < 0 || y > this.size - 1) return -1; return this.wallGrid[y * this.size + x]; }; Map.prototype.randomize = function() { for ( var i = 0; i < this.size * this.size; i++) { this.wallGrid[i] = Math.random() < 0.3 ? 1 : 0; } }; /** * @point * @angle * @range 范围 */ Map.prototype.cast = function(point, angle, range) { var self = this; var sin = Math.sin(angle); var cos = Math.cos(angle); var noWall = { length2 : Infinity }; return ray({ x : point.x, y : point.y, height : 0, distance : 0 }); function ray(origin) { var stepX = step(sin, cos, origin.x, origin.y); var stepY = step(cos, sin, origin.y, origin.x, true); var nextStep = stepX.length2 < stepY.length2 ? inspect(stepX, 1, 0, origin.distance, stepX.y) : inspect(stepY, 0, 1, origin.distance, stepY.x); if (nextStep.distance > range) return [ origin ]; return [ origin ].concat(ray(nextStep)); } function step(rise, run, x, y, inverted) { if (run === 0) return noWall; var dx = run > 0 ? Math.floor(x + 1) - x : Math.ceil(x - 1) - x; var dy = dx * (rise / run); return { x : inverted ? y + dy : x + dx, y : inverted ? x + dx : y + dy, length2 : dx * dx + dy * dy }; } function inspect(step, shiftX, shiftY, distance, offset) { var dx = cos < 0 ? shiftX : 0; var dy = sin < 0 ? shiftY : 0; step.height = self.get(step.x - dx, step.y - dy); step.distance = distance + Math.sqrt(step.length2); if (shiftX) step.shading = cos < 0 ? 2 : 0; else step.shading = sin < 0 ? 2 : 1; step.offset = offset - Math.floor(offset); return step; } }; /** * 模拟闪电的时间间隔 * this.light 为当前地区的亮度值 */ Map.prototype.update = function(seconds) { if (this.light > 0)//按时间把亮度调低.当为最暗时,用0表示 this.light = Math.max(this.light - 10 * seconds, 0); else if (Math.random() * 5 < seconds) this.light = 2;//按某概率 出现闪电 }; function Camera(canvas, resolution, fov) { // 画布 this.ctx = canvas.getContext('2d'); // 通过style 将 画面强制放大,填充屏幕。画面越精细,速度越慢,反之则画面模糊,但是速度快。默认大小为0.5 this.width = canvas.width = window.innerWidth * 0.5; this.height = canvas.height = window.innerHeight * 0.5; //分辨率 this.resolution = resolution; this.spacing = this.width / resolution; // 视角 为固定 0.4*pi this.fov = fov; this.range = MOBILE ? 8 : 14; this.lightRange = 5; //只用来识别武器的分变率。或者说,大小 this.scale = (this.width + this.height) / 1200; } Camera.prototype.render = function(player, map) { // 单纯只是计算出闭合后。图片的相关特征,做背景 this.drawSky(player.direction, map.skybox, map.light); // 重点计算 this.drawColumns(player, map); // 玩家武器图,只是 一张晃动的图 //旋转时不晃动。晃动的幅度根据当前前进的步数或者后腿时的步数 this.drawWeapon(player.weapon, player.paces); }; /** * direction 方向 (摄像头[用户角度方向]) sky 天空元素 (闭合状态下[图,首尾相连,形成的一圈为360度,即2*pi=CIRCLE ]。) * ambient 环境 (遮罩层,用来降低光线) */ Camera.prototype.drawSky = function(direction, sky, ambient) { // 计算出当前背景图的可视范围 this.fov(可视范围) //不清楚这里的计算原理。 var width = this.width * (CIRCLE / this.fov); // 2/0.4 // 旋转偏角 图片左边的部分偏移 // 宽度 direction 为当前视角弧度 var left = -width * direction / CIRCLE; this.ctx.save(); this.ctx.drawImage(sky.image, left, 0, width, this.height); if (left < width - this.width) { //console.log(left,direction / CIRCLE); this.ctx.drawImage(sky.image, left + width, 0, width, this.height); } if (ambient > 0) { this.ctx.fillStyle = '#ffffff'; this.ctx.globalAlpha = ambient * 0.1; this.ctx.fillRect(0, this.height * 0.5, this.width, this.height * 0.5); } this.ctx.restore(); }; Camera.prototype.drawColumns = function(player, map) { this.ctx.save(); for ( var column = 0; column < this.resolution; column++) { var angle = this.fov * (column / this.resolution - 0.5); var ray = map.cast(player, player.direction + angle, this.range); this.drawColumn(column, ray, angle, map); } this.ctx.restore(); }; Camera.prototype.drawWeapon = function(weapon, paces) { //利用cos 的正弦和余弦的波动范围为1至-1,加上对应的识别大小做抖动 //模拟人走动时,摆动的弧度.曲线. var bobX = Math.cos(paces * 2) * this.scale * 6; var bobY = Math.sin(paces * 4) * this.scale * 6; var left = this.width * 0.66 + bobX; var top = this.height * 0.6 + bobY; this.ctx.drawImage(weapon.image, left, top, weapon.width * this.scale, weapon.height * this.scale); }; Camera.prototype.drawColumn = function(column, ray, angle, map) { var ctx = this.ctx; var texture = map.wallTexture; var left = Math.floor(column * this.spacing); var width = Math.ceil(this.spacing); var hit = -1; while (++hit < ray.length && ray[hit].height <= 0) ; for ( var s = ray.length - 1; s >= 0; s--) { var step = ray[s]; var rainDrops = Math.pow(Math.random(), 3) * s; var rain = (rainDrops > 0) && this.project(0.1, angle, step.distance); if (s === hit) { var textureX = Math.floor(texture.width * step.offset); var wall = this.project(step.height, angle, step.distance); ctx.globalAlpha = 1; ctx.drawImage(texture.image, textureX, 0, 1, texture.height, left, wall.top, width, wall.height); ctx.fillStyle = '#000000'; ctx.globalAlpha = Math.max((step.distance + step.shading) / this.lightRange - map.light, 0); ctx.fillRect(left, wall.top, width, wall.height); } ctx.fillStyle = '#ffffff'; ctx.globalAlpha = 0.15; while (--rainDrops > 0) ctx.fillRect(left, Math.random() * rain.top, 1, rain.height); } }; Camera.prototype.project = function(height, angle, distance) { var z = distance * Math.cos(angle); var wallHeight = this.height * height / z; var bottom = this.height / 2 * (1 + 1 / z); return { top : bottom - wallHeight, height : wallHeight }; }; function GameLoop() { this.frame = this.frame.bind(this); this.lastTime = 0; this.callback = function() { }; } GameLoop.prototype.start = function(callback) { this.callback = callback; requestAnimationFrame(this.frame); }; GameLoop.prototype.frame = function(time) { var seconds = (time - this.lastTime) / 1000; this.lastTime = time; if (seconds < 0.2) this.callback(seconds); requestAnimationFrame(this.frame); }; var display = document.getElementById('display'); var player = new Player(15.3, -1.2, Math.PI * 0.3); var map = new Map(32); var controls = new Controls(); var camera = new Camera(display, MOBILE ? 160 : 320, Math.PI * 0.4); var loop = new GameLoop(); map.randomize(); //系统自动循环时,自动调整时间 seconds 时间间隔长度 . loop.start(function frame(seconds) { map.update(seconds); player.update(controls.states, map, seconds); camera.render(player, map); });
小试 javafx
安装:
http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html
引入:
jdkjrelibjfxrt.jar
demo
http://docs.oracle.com/javase/8/javafx/get-started-tutorial/get_start_apps.htm#JFXST804
浏览器demo
package helloworld; import javafx.application.Application; import javafx.geometry.HPos; import javafx.geometry.VPos; import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; import javafx.scene.layout.Region; import javafx.scene.paint.Color; import javafx.scene.web.WebEngine; import javafx.scene.web.WebView; import javafx.stage.Stage; public class WebViewSample extends Application { private Scene scene; @Override public void start(Stage stage) { // create the scene stage.setTitle("Web View"); scene = new Scene(new Browser(), 750, 500, Color.web("#666970")); stage.setScene(scene); scene.getStylesheets().add("webviewsample/BrowserToolbar.css"); stage.show(); } public static void main(String[] args) { launch(args); } } class Browser extends Region { final WebView browser = new WebView(); final WebEngine webEngine = browser.getEngine(); public Browser() { // apply the styles getStyleClass().add("browser"); // load the web page webEngine.load("http://blog.martoo.cn"); getStyleClass().add("webviewsample/BrowserToolbar.css"); // add the web view to the scene getChildren().add(browser); } private Node createSpacer() { Region spacer = new Region(); HBox.setHgrow(spacer, Priority.ALWAYS); return spacer; } @Override protected void layoutChildren() { double w = getWidth(); double h = getHeight(); layoutInArea(browser, 0, 0, w, h, 0, HPos.CENTER, VPos.CENTER); } @Override protected double computePrefWidth(double height) { return 750; } @Override protected double computePrefHeight(double width) { return 500; } }
scene.getStylesheets().add("webviewsample/BrowserToolbar.css");
相对当前包的根目录。
如:
/helloworld/WebViewSample.java
/webviewsample/BrowserToolbar.css
样式文件demo:
/src/helloworld/HelloWorld.java
package helloworld; import javafx.application.Application; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class HelloWorld extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage primaryStage) { primaryStage.setTitle("Hello World!"); Button btn = new Button(); btn.setText("Say 'Hello World'"); btn.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { System.out.println("Hello World!"); } }); StackPane root = new StackPane(); root.getChildren().add(btn); Scene scene = new Scene(root, 300, 250); scene.getStylesheets().add( HelloWorld.class.getResource("../test.css").toExternalForm()); primaryStage.setScene(scene); primaryStage.show(); } }
/src/test.css
.root { -fx-background-image: url("background.jpg"); } .label { -fx-font-size: 12px; -fx-font-weight: bold; -fx-text-fill: #333333; -fx-effect: dropshadow( gaussian , rgba(255,255,255,0.5) , 0,0,0,1 ); } .button { -fx-font-size: 19px; -fx-font-weight: bold; -fx-text-fill: #333333; -fx-effect: dropshadow( gaussian , rgba(255,255,255,0.5) , 0,0,0,1 ); }
编写 PHP 为程序逻辑代码的 SWING客户端
首先,需要确保目的程序 ,php能独立执行。能输出。
纯粹只是因为用java写复杂逻辑代码比较蛋疼,或者说,因为有现成的代码是php的,重写需要花大量的时间。所以以java 的命令形式进行调用。
步骤 :
1.php代码一份
2.php运行环境一份
2.1 如果非指定形式调用。默认配置文件需要为 : php.ini ,不能有别名
2.2 配置内部内容需要清理不必要的配置,引用路径调整
2.3 单独执行一个文件,调整到不出问题,能正常执行为止
c:ooxxphp.exe “c:aabbindex.php”
3.用java Swing 绘制一个壳,用myeclipse ,前提需要有java 基础,或类似的winform基础比较容易上手,不然适当进行学习即可.
4.用exe4j 打包
参考:http://blog.martoo.cn/?p=613
补充相关代码:
一、命令调用
try { String php_exe = System.getProperty("user.dir") + "/php/php/php.exe"; String php_file = System.getProperty("user.dir") + "/php/exec.php"; if (!filexists(php_exe)) { JOptionPane.showMessageDialog(null, "The php.exe file is not exist"); System.exit(0); } if (!filexists(php_file)) { JOptionPane .showMessageDialog(null, "The php file is not exist"); System.exit(0); } String shell = php_exe + " "" + php_file + """; Process ps = Runtime.getRuntime().exec(shell); ps.waitFor(); BufferedReader br = new BufferedReader(new InputStreamReader( ps.getInputStream())); StringBuffer sb = new StringBuffer(); String line; String contentempty = ""; while ((line = br.readLine()) != null) { contentempty += line; sb.append(line).append("n"); } String result = sb.toString(); if (!contentempty.isEmpty()) { recordinfo(result); JOptionPane.showMessageDialog(null, result); } } catch (Exception e) { recordinfo(e.getMessage()); }
public static void recordinfo(String log) { String path = System.getProperty("user.dir") + "/php_log.txt"; try { FileWriter fw = new FileWriter(path, true); PrintWriter pw = new PrintWriter(fw); pw.println(log); pw.close(); // bw.close(); fw.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
public static boolean filexists(String filename) { return new File(filename).exists(); }
输出信息可直接用于弹出框提示。
也可以记录为日志。
二、通讯操作
使用java properties
properties 保存和读取代码
Properties prop = new Properties(); FileInputStream fis; FileOutputStream fos; try { fis = new FileInputStream(System.getProperty("user.dir") + "/php/prop.properties"); fos = new FileOutputStream(System.getProperty("user.dir") + "/php/prop.properties"); prop.load(fis); prop.setProperty("csvpath", jfc.getSelectedFile() .getAbsolutePath()); prop.save(fos, " config file"); // System.out.println(prop.getProperty("a")); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }
php 获取代码:
参考:http://blog.martoo.cn/?p=825
三:常用功能代码
文件选择框
JFileChooser jfc = new JFileChooser(); if (jfc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { //获取路径 System.out.println(jfc.getSelectedFile().getAbsolutePath()); }
弹出提示框
JOptionPane .showMessageDialog(null, "The php file is not exist");
补充 : 意大利操作系统(win7 64x)关闭不了问题
Process ps; try { ps = Runtime.getRuntime().exec("taskkill /f /im xxx.exe"); ps.waitFor(); BufferedReader br = new BufferedReader(new InputStreamReader( ps.getInputStream())); StringBuffer sb = new StringBuffer(); String line; String contentempty = ""; while ((line = br.readLine()) != null) { contentempty += line; sb.append(line).append("n"); } String result = sb.toString(); if (!contentempty.isEmpty()) { recordinfo(result); JOptionPane.showMessageDialog(null, result); } } catch (IOException e2) { e2.printStackTrace(); } catch (InterruptedException xe) { xe.printStackTrace(); }
转发请注明出处http://blog.martoo.cn
如有漏缺,请联系我 QQ 243008827
php get java properties fix(utf-8)
$properties = parse_properties ( 'prop.properties' ); var_export ( $properties ); function unicode2utf8($str) { if (! $str) return $str; $decode = json_decode ( $str ); if ($decode) return $decode; $str = '["' . $str . '"]'; $decode = json_decode ( $str ); if (count ( $decode ) == 1) { return $decode [0]; } return $str; } function parse_properties($propertiespath) { $txtProperties = file_get_contents ( $propertiespath ); $result = array (); $lines = split ( "n", $txtProperties ); $key = ""; $isWaitingOtherLine = false; foreach ( $lines as $i => $line ) { if (empty ( $line ) || (! $isWaitingOtherLine && strpos ( $line, "#" ) === 0)) continue; if (! $isWaitingOtherLine) { $key = substr ( $line, 0, strpos ( $line, '=' ) ); $value = substr ( $line, strpos ( $line, '=' ) + 1, strlen ( $line ) ); } else { $value .= $line; } /* Check if ends with single '' */ if (strrpos ( $value, "" ) === strlen ( $value ) - strlen ( "" )) { $value = substr ( $value, 0, strlen ( $value ) - 1 ) . "n"; $isWaitingOtherLine = true; } else { $isWaitingOtherLine = false; } $value = trim ( $value ); $value = preg_replace ( "/(\uw{4})/e", "unicode2utf8('1')", $value ); $value = preg_replace ( "/\\/", "", $value ); $value = preg_replace ( "/\:/", ":", $value ); $result [$key] = $value; unset ( $lines [$i] ); } return $result; }
转发请注明出处http://blog.martoo.cn
如有漏缺,请联系我 QQ 243008827
【转】Zend Studio / Ecliplse插件EasyExplorer,打开资源文件所在的文件夹
http://blog.snsgou.com/post-145.html
个人设置为:
explorer.exe /e,{0}
【转】每个程序员都必读的10篇文章
http://it.deepinmind.com/%E5%85%B6%E5%AE%83/2014/05/15/10-articles-every-programmer-must-read.html
感悟:路漫漫其修远兮,吾将上下而求索
支付宝 错误代码 ILLEGAL_SIGN
签名异常,不解释。
静排查。可导入异常的参数有
body
subject
一开始以为长度限制,因为官方文档申明
body (string 1000)
subject (string 256)
截取,依旧出问题
经各种排查,发现问题原因为参数出现特殊字符。现提供特殊字符的过滤处理
处理一:
$parameter['subject']=preg_replace('/s/', '', $parameter['subject']); $parameter['body']=preg_replace('/s/', '', $parameter['body']);
处理二:
//限制提交字符长度 //过滤特殊字符 s 否则识别有问题 $parameter['subject']= preg_split('/[^())(【】.!!w+-*^x{4e00}-x{9fa5}]+/u', $parameter['subject']); $parameter['subject']=implode(' ', $parameter['subject']); $parameter['body']= preg_split('/[^())(【】.!!w+-*^x{4e00}-x{9fa5}]+/u', $parameter['body']); $parameter['body']=implode(' ', $parameter['body']);
转发请注明出处http://blog.martoo.cn
如有漏缺,请联系我 QQ 243008827
Sqlite 使用
官网:https://bitbucket.org/xerial/sqlite-jdbc
jar:https://bitbucket.org/xerial/sqlite-jdbc/downloads
mysql 转 sqlite 相关处理
基本上语法通用,需要特殊处理的有.
用navicat premium 导出两种数据库,比较后,需要处理的有
1. ` 全部替换成 ”
2. 类型只有 text integer blob real 这些。根据需要进行处理。
异常判断
encrypted sqlite db
如果用 navicat premium 打开正常,直接用记事本看下当前的 sqlite 的版本是多少.
这边的是php 5.2 默认的扩展是 sqlite 2.0
需要打开,然后做下转换处理.
blob类型取出时,被转码成
需要做特殊处理
stripcslashes()
这边只是普通的查询,具体情况自行判断.
转发请注明出处http://blog.martoo.cn
如有漏缺,请联系我 QQ 243008827