欢迎您来到懒之才-站长的分享平台!   学会偷懒,并懒出境界是提高工作效率最有效的方法!
首页 > 经验分享 > PHP > 安装PHP7的图形用户界面(GUI) 扩展

安装PHP7的图形用户界面(GUI) 扩展

2018-09-19 3097 收藏 0 赞一个 0 真差劲 0 去评论

今天翻了翻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扩展介绍

http://php.net/ui

Github

https://github.com/krakjoe/ui

经过一番折腾,终于能运行了, 

下面说说我的安装过程:(仅以Windows7为例)

1. 先下载扩展

扩展下载:https://pecl.php.net/package/ui 

按照你本地的PHP7版本情况选择下载对应的扩展文件,注意:仅支持 PHP7 哦

2. 安装扩展

解压刚才下载的压缩包 

总共需要三个 .dll 文件

php_ui.dll 
libui.dll 
pthreadVC2.dll

1.png

将 php_ui.dll 复制到 PHP 的 ext 目录下, 

其余两个文件 libui.dll 和 pthreadVC2.dll 放到 PHP 的根目录下,也就是与 php.exe 的同级目录

如果你之前操作不正确,在命令行中执行 PHP 时,将会弹出下面的错误提示:

无法启动此程序,因为计算机中丢失 libui.dll,尝试重新安装该程序以解决此问题。

1.png

这个提示出现说明你没有放入 libui 和 pthreadVC2 文件到 php 的根目录下,重新放入就正常了。

3. 开始测试

打开之前下载的压缩包,其中有三个已写好的测试代码: 
贪吃蛇游戏,无限星空动画,趋势图

下面运行测试代码看看效果吧:

贪吃蛇:

1.png

这是个可操作的游戏哦,不过撞到自己的尾巴不会死,窗口可任意拉伸,越大行动速度就越快

无限星空图

1.png

趋势图

1.png

可以实时调节变化。

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

大家评论