安装PHP7的图形用户界面(GUI) 扩展
今天翻了翻PHP手册,无意中发现这个PHP7才加入的新扩展:图形用户界面(GUI) 扩展 PHP-UI,觉得挺有意思的,2016年10月才发布的,网上搜了一圈发现几乎没有相关资讯,连安装说明都没有一个。。。
官方介绍原文:
This extension wraps the very excellent libui to provide PHP 7 with an API for the creation of cross platform native look-and-feel interfaces.
大概说的是:该扩展是适用于 PHP7 基于 libui 开发的跨平台图形界面接口吧。。。
PHP扩展介绍
Github
经过一番折腾,终于能运行了,
下面说说我的安装过程:(仅以Windows7为例)
1. 先下载扩展
扩展下载:https://pecl.php.net/package/ui
按照你本地的PHP7版本情况选择下载对应的扩展文件,注意:仅支持 PHP7 哦
2. 安装扩展
解压刚才下载的压缩包
总共需要三个 .dll 文件
php_ui.dll libui.dll pthreadVC2.dll
将 php_ui.dll 复制到 PHP 的 ext 目录下,
其余两个文件 libui.dll 和 pthreadVC2.dll 放到 PHP 的根目录下,也就是与 php.exe 的同级目录
如果你之前操作不正确,在命令行中执行 PHP 时,将会弹出下面的错误提示:
无法启动此程序,因为计算机中丢失 libui.dll,尝试重新安装该程序以解决此问题。
这个提示出现说明你没有放入 libui 和 pthreadVC2 文件到 php 的根目录下,重新放入就正常了。
3. 开始测试
打开之前下载的压缩包,其中有三个已写好的测试代码:
贪吃蛇游戏,无限星空动画,趋势图
下面运行测试代码看看效果吧:
贪吃蛇:
这是个可操作的游戏哦,不过撞到自己的尾巴不会死,窗口可任意拉伸,越大行动速度就越快
无限星空图
趋势图
可以实时调节变化。
5.源码参考:
这是官方的测试案例源码,可以先参考下看看
贪吃蛇代码:
<?php define ("PHP_UI_SECOND", 1000000); define ("PHP_UI_SNAKE_FPS", 30); use UI\Window; use UI\Point; use UI\Size; use UI\Area; use UI\Key; use UI\Controls\Box; use UI\Draw\Pen; use UI\Draw\Brush; use UI\Draw\Path; use UI\Draw\Color; use UI\Draw\Stroke; use UI\Draw\Matrix; use UI\Draw\Text\Font; use UI\Draw\Text\Font\Descriptor; use UI\Executor; $win = new class("Snake", new Size(640, 480), false) extends Window { public function addExecutor(Executor $executor) { $this->executors[] = $executor; } protected function onClosing() { foreach ($this->executors as $executor) { $executor->kill(); } $this->destroy(); UI\quit(); } }; $box = new Box(Box::Vertical); $win->add($box); $snake = new class($box) extends Area{ public function __construct(Box $box) { $this->newSnake(); $box->append($this, true); } public function setExecutor(Executor $executor) { $this->executor = $executor; } protected function onKey(string $char, int $key, int $flags) { if ($flags & Area::Down) { switch ($key) { case Key::Up: if ($this->direction == Key::Down) return; $this->direction = $key; break; case Key::Down: if ($this->direction == Key::Up) return; $this->direction = $key; break; case Key::Right: if ($this->direction == Key::Left) return; $this->direction = $key; break; case Key::Left: if ($this->direction == Key::Right) return; $this->direction = $key; break; default: if ($char == " ") { $this->pause = !$this->pause; if ($this->pause) { /* this allows the CPU to idle while paused */ $this->executor->setInterval(0); } else { /* this will (re)start the game */ $this->executor->setInterval(PHP_UI_SECOND/PHP_UI_SNAKE_FPS); } } break; } } } protected function onDraw(Pen $pen, Size $size, Point $clip, Size $clipSize) { $zero = new Point(0, 0); $frame = $zero + 40; $frameSize = $size - 80; $path = new Path(); $path->addRectangle($zero, $size); $path->end(); $pen->fill($path, 0xf5f5f5ff); $stroke = new Stroke(); $pen->stroke($path, 0x000000FF, $stroke); $path = new Path(); $path->addRectangle($frame, $frameSize); $path->end(); $pen->stroke($path, 0x000000FF, $stroke); $matrix = new Matrix(); $matrix->translate($frame); $pen->transform($matrix); if (!$this->food) { $this->newFood($frameSize); } if (!$this->pause && ($run = microtime(true)) - $this->run > 0.1 / $this->level * 2) { $this->run = $run; $next = clone $this->snake[0]; switch ($this->direction) { case Key::Right: $next->x++; break; case Key::Left: $next->x--; break; case Key::Up: $next->y--; break; case Key::Down: $next->y++; break; } if ($next->x < 0 || $next->x >= ($frameSize->width)/10 || $next->y < 0 || $next->y >= ($frameSize->height)/10) { $this->newSnake(); $this->newFood($frameSize); foreach ($this->snake as $body) { $this->newCell($pen, $body); } $this->newCell($pen, $this->food); $this->pause = true; $this->direction = Key::Right; $this->score = 0; $this->level = 1; return; } if ($this->food == $next) { $tail = $next; $this->newFood($frameSize); $this->score += 10; $this->level = ceil($this->score / 100); } else { $tail = array_pop($this->snake); $tail->x = $next->x; $tail->y = $next->y; } array_unshift($this->snake, $tail); } foreach ($this->snake as $body) { $this->newCell($pen, $body); } $this->newCell($pen, $this->food); $matrix = new Matrix(); $matrix->translate($zero - 40); $pen->transform($matrix); if ($this->pause) { $this->drawPause($pen, $size); } else $this->drawScore($pen, $size); } private function newSnake() { $this->snake = []; for ($i = 0; $i < 5; $i++) $this->snake[$i] = new Point($i, 0); } private function newFood(Size $size) { $this->food = new Point( floor(mt_rand(40, ($size->width ) - 10) / 10), floor(mt_rand(40, ($size->height) - 10) / 10)); } private function newCell(Pen $pen, Point $point) { $path = new Path(); $path->addRectangle($point * 10, new Size(10, 10)); $path->end(); $pen->fill($path, 0x0000FFFF); $stroke = new Stroke(); $stroke->setThickness(2); $pen->stroke($path, 0x000000FF, $stroke); } private function drawPause(Pen $pen, Size $size) { $layout = new UI\Draw\Text\Layout(sprintf( "Press space bar to play ...", $this->level, $this->score ), new Font(new Descriptor("arial", 12)), $size->width); $layout->setColor(0x000000FF); $pen->write(new Point(20, 10), $layout); } private function drawScore(Pen $pen, Size $size) { $layout = new UI\Draw\Text\Layout(sprintf( "Level: %d Score: %d", $this->level, $this->score ), new Font(new Descriptor("arial", 12)), $size->width); $layout->setColor(0x000000FF); $pen->write(new Point(20, 10), $layout); } private $snake; private $food; private $direction = Key::Right; private $level = 1; private $score = 0; private $pause = true; private $run = 0; }; $animator = new class ($snake) extends Executor { public function __construct(Area $area) { $this->area = $area; /* construct executor with infinite timeout */ parent::__construct(); } protected function onExecute() { $this->area->redraw(); } }; $win->addExecutor($animator); $snake->setExecutor($animator); $win->show(); UI\run();
无限星空
<?php use UI\Window; use UI\Point; use UI\Size; use UI\Area; use UI\Key; use UI\Controls\Box; use UI\Draw\Pen; use UI\Draw\Brush; use UI\Draw\Path; use UI\Draw\Color; use UI\Executor; $win = new class("Starfield", new Size(640, 480), false) extends Window { public function addExecutor(Executor $executor) { $this->executors[] = $executor; } protected function onClosing() { foreach ($this->executors as $executor) { $executor->kill(); } $this->destroy(); UI\quit(); } }; $box = new Box(Box::Vertical); $win->add($box); $font = new UI\Draw\Text\Font( new UI\Draw\Text\Font\Descriptor("arial", 12) ); $stars = new class($box, 1024, 64, $font) extends Area { protected function onKey(string $key, int $ext, int $flags) { if ($flags & Area::Down) { switch ($ext) { case Key::Up: if ($this->velocity < 40) { $this->velocity++;; } break; case Key::Down: if ($this->velocity) { $this->velocity--; } break; } } } protected function onDraw(UI\Draw\Pen $pen, UI\Size $size, UI\Point $clip, UI\Size $clipSize) { $hSize = $size / 2; $path = new Path(); $path->addRectangle(Point::at(0), $size); $path->end(); $pen->fill($path, 0x000000FF); foreach ($this->stars as $idx => &$star) { $star[1] -= $this->velocity / 10; if ($star[1] <= 0) { $star[0]->x = mt_rand(-25, 25); $star[0]->y = mt_rand(-25, 25); $star[1] = $this->depth; } $pos = $star[0] * (128 / $star[1]) + $hSize; if ($pos->x >= 0 && $pos->x <= $size->width && $pos->y >= 0 && $pos->y <= $size->height) { $starSize = (1 - $star[1] / 32) * 5; $path = new Path(); if (PHP_OS == "WINNT") { $path->addRectangle($pos, new Size($starSize, $starSize)); } else { $path->newFigureWithArc($pos, $starSize/2, 0, M_PI*2, 0); } $path->end(); $color = new Color(); $color->r = $starSize; $color->g = $starSize; $color->b = $starSize; if ($star[2] && $star[3]++ % 3 == 0) { $color->a = mt_rand(0,10) / 10; } $pen->fill($path, $color); } } $this->writeRenderSpeed($pen, $size); } private function writeRenderSpeed(UI\Draw\Pen $pen, UI\Size $size) { $now = time(); @$this->frames[$now]++; $layout = new UI\Draw\Text\Layout(sprintf( "%d fps", isset($this->frames[$now - 1]) ? $this->frames[$now-1] : $this->frames[$now] ), $this->font, $size->width); $layout->setColor(0xFFFFFFFF); $pen->write(new Point(20, 20), $layout); unset($this->frames[$now-2]); } public function __construct($box, $max, $depth, $font, $velocity = 2) { $this->box = $box; $this->max = $max; $this->depth = $depth; $this->font = $font; $this->velocity = $velocity; for ($i = 0; $i < $this->max; $i++) { $this->stars[] = [ new Point(mt_rand(-25, 25), mt_rand(-25, 25)), mt_rand(1, $this->depth), mt_rand(0, 1), 0 ]; } $this->box->append($this, true); } }; $animator = new class(1000000/60, $stars) extends Executor { protected function onExecute() { $this->area->redraw(); } public function __construct(int $microseconds, Area $area) { $this->area = $area; parent::__construct($microseconds); } }; $win->addExecutor($animator); $win->show(); UI\run();
趋势图:
<?php use UI\Point; use UI\Size; use UI\Window; use UI\Controls\Box; use UI\Controls\Spin; use UI\Controls\ColorButton; use UI\Controls\Button; use UI\Controls\Entry; use UI\Controls\Label; use UI\Controls\Combo; use UI\Area; use UI\Draw\Pen; use UI\Draw\Path; use UI\Draw\Color; use UI\Draw\Brush; use UI\Draw\Stroke; use UI\Draw\Matrix; use UI\Draw\Text\Font\Descriptor; use UI\Draw\Text\Font; use UI\Draw\Text\Layout; $window = new Window("libui Histogram Example", new Size(640, 480), true); $window->setMargin(true); $hBox = new Box(Box::Horizontal); $hBox->setPadded(true); $vBox = new Box(Box::Vertical); $vBox->setPadded(true); $window->add($hBox); $hBox->append($vBox); $dataSources = []; $histogram = new class($dataSources) extends Area { private function getGraphPoints(Size $size) : array { $xincr = $size->width / 9; $yincr = $size->height / 100; $points = []; foreach ($this->sources as $i => $source) { $points[$i] = new Point($xincr * $i, $yincr * (100 - $source->getValue())); } return $points; } private function getGraphPath(array $locations, Size $size, bool $extend = false) : Path { $path = new Path(); $path->newFigure(array_shift($locations)); foreach ($locations as $location) { $path->lineTo($location); } if ($extend) { $path->lineTo(Point::at($size)); $path->lineTo(new Point(0, $size->height)); $path->closeFigure(); } $path->end(); return $path; } protected function onDraw(Pen $pen, Size $areaSize, Point $clipPoint, Size $clipSize) { $start = microtime(true); $path = new Path(); $path->addRectangle($clipPoint, $areaSize); $path->end(); $pen->fill($path, 0xFFFFFFFF); $graphSize = $areaSize - 40; $zero = Point::at(20); $path = new Path(); $path->newFigure($zero); $path->lineTo(new Point(20, 20 + $graphSize->height)); $path->lineTo(Point::at($graphSize + 20)); $path->end(); $stroke = new Stroke(); $stroke->setThickness(2); $pen->stroke($path, 0x000000FF, $stroke); $matrix = new Matrix(); $matrix->translate($zero); $pen->transform($matrix); $points = $this->getGraphPoints($graphSize); $path = $this->getGraphPath($points, $graphSize, true); $brush = new Brush($this->color->getColor()); $pen->fill($path, $brush); $path = $this->getGraphPath($points, $graphSize, false); $strokeColor = $brush->getColor(); $strokeColor->a /= 2; $brush->setColor($strokeColor); $pen->stroke($path, $brush, $stroke); $layout = new Layout(sprintf( "Drawn in %.5f seconds", microtime(true) - $start), $this->font->getFont(), $clipSize->width ); $layout->setColor(0x000000FF); $pen->write(new Point(10, $graphSize->height - 30), $layout); } public function setColorSource(ColorButton $source) { $this->color = $source; } public function getColorSource() { return $this->color; } public function setFontSource(Combo $font) { $this->font = $font; } public function getFontSource() { return $this->font; } public function __construct(array &$sources, ColorButton $color = null, Font $font = null) { $this->sources =& $sources; $this->color = $color; $this->font = $font; } private $sources; private $color; private $font; }; $colorBox = new Entry(); $colorBox->setText("0x8892BFFF"); $colorButton = new class($histogram, $colorBox, new Color(0x8892BFFF)) extends ColorButton { protected function onChange() { $redrawColor = $this->getColor(); $this->entry->setText(sprintf( "0x%02X%02X%02X%02X", $redrawColor->r * 255, $redrawColor->g * 255, $redrawColor->b * 255, $redrawColor->a * 255)); $this->histogram->redraw(); } public function __construct(Area $histogram, Entry $entry, Color $color) { $this->histogram = $histogram; $this->entry = $entry; $this->setColor($color); $this->histogram->setColorSource($this); } private $histogram; }; $redrawHistogram = function() use($histogram, $colorBox, $colorButton) { $redrawColor = $colorButton->getColor(); $colorBox->setText(sprintf( "0x%02X%02X%02X%02X", $redrawColor->r * 255, $redrawColor->g * 255, $redrawColor->b * 255, $redrawColor->a * 255)); $histogram->redraw(); }; $vBox->append(new Label("Change Data:")); for ($i = 0; $i < 10; $i++) { $dataSources[$i] = new class(0, 100, $redrawHistogram) extends Spin { protected function onChange() { ($this->redraw)(); } public function __construct($min, $max, Closure $redraw) { parent::__construct($min, $max); $this->redraw = $redraw; } private $redraw; }; $dataSources[$i]->setValue(mt_rand(0, 100)); $vBox->append($dataSources[$i]); } $vBox->append(new Label("Choose Color:")); $vBox->append($colorButton); $colorBoxButton = new class("Set Color", $colorButton, $colorBox, $redrawHistogram) extends Button { protected function onClick() { $this->button->setColor( new Color( hexdec($this->entry->getText()))); ($this->redraw)(); } public function __construct(string $text, ColorButton $button, Entry $entry, Closure $redraw) { $this->button = $button; $this->entry = $entry; $this->redraw = $redraw; parent::__construct($text); } private $button; private $entry; private $redraw; }; $vBox->append($colorBox); $vBox->append($colorBoxButton); $vBox->append(new Label("Choose Font:")); $fontCombo = new class($histogram) extends Combo { public function onSelected() { $this->histogram->redraw(); } public function __construct(Area $histogram) { $this->families = UI\Draw\Text\Font\fontFamilies(); $this->histogram = $histogram; sort($this->families); foreach ($this->families as $family) { $this->append($family); } $this->setSelected(0); $this->histogram->setFontSource($this); } public function getFont(int $selected = -1, int $size = 12) { return new Font( new Descriptor($this->families[ $selected > -1 ? $families : $this->getSelected() ], $size)); } private $items; private $families; }; $vBox->append($fontCombo); $hBox->append($histogram, true); $window->show(); UI\run(); ?>
一、推荐使用迅雷或快车等多线程下载软件下载本站资源。
二、未登录会员无法下载,登录后可获得更多便利功能,若未注册,请先注册。
三、如果服务器暂不能下载请稍后重试!总是不能下载,请点我报错 ,谢谢合作!
四、本站大部分资源是网上搜集或私下交流学习之用,任何涉及商业盈利目的均不得使用,否则产生的一切后果将由您自己承担!本站将不对任何资源负法律责任.如果您发现本站有部分资源侵害了您的权益,请速与我们联系,我们将尽快处理.
五、如有其他问题,请加网站设计交流群(点击这里查看交流群 )进行交流。
六、如需转载本站资源,请注明转载来自并附带链接
七、本站部分资源为加密压缩文件,统一解压密码为:www.aizhanzhe.com
- 1CSS控制文字在Div最底部显示
- 2Thinkphp5如何配置IP+端口访问项目模块
- 3elementUI el-dialog弹框居中
- 4教你如何搭建及优化站点
- 5国内互联网视频行业运营分析
- 6CSS实现悬浮顶部的Div工具栏
- 7记一次Thinkphp5.1框架mysql数据库崩溃(SQLSTATE [08004] Too many connections)
- 8service mysql start出错,mysql不能启动,解决mysql: unrecognized service错误
- 9连接SQL Server数据库提示:Login failed for user 'sa'错误的解决方案
- 10Thinkphp3.2在centos7上设置计划任务的方法