scienceasdf


  • 首页

  • 分类

  • 归档

  • 标签

在手机上绘制根轨迹(2)

发表于 2018-04-04 | 分类于 Programming

另一种方式实现手机上绘制根轨迹。并且在手机上绘制螺旋桨性能曲线。


在手机上绘制根轨迹

上一次写的easyAuto,好倒是挺好的,但是有一个问题:仅仅有安卓的版本,没有iOS版本。这样一来,有很多用户无法得到方便。因此,要么自己买一套iOS的设备,要么换一种方式:网页实现。

网页绘制的好处有很多,可以实现真正的跨平台,每一次代码的更新用户并不需要任何的升级这些,因此好处太多了。没能开发iOS程序一直是我的遗憾,这样也算是一种弥补。现在的前端技术很火,bootcdn上面一大堆js库,都很有意思,没事浏览浏览上面的目录,说不定能发现宝贝。

在上次的文章里我们详细的讨论了算法,又是多项式又是矩阵什么的,比较麻烦。网上找到的轮子有

  • math.js库,比较强大,但是矩阵不能求特征值
  • numerical.js库,很久没有更新了,矩阵能够求特征值,还有样条插值函数
  • polynomial.js,比较简陋,就是用来表示多项式的 即使有这些低层次的轮子,要移植我曾经的一大堆专门的数值代码也是非常麻烦的。手写就不说了,自己想想都觉得多。我在网上看到了几种方案:
  • emscripten-qt直接移植Qt程序,这个项目已经没有维护了,不可能能移植QtCharts模块
  • Qt+WebAssembly,看了几个demo,效果很差
  • 在网页里面直接运行apk,也没有看见理想的方案
  • 用emscripten移植数值算法的代码,但是自己本来就完全不会javascript,这样自己也会更麻烦

那也没有实现的办法呢?我想到了WolframAlpha,试了试,可以画根轨迹,当然这个问题可以结束了,所有手机要想画根轨迹直接访问WolframAlpha不就完了?!但是还是要自己写程序,看了看有没有WolframAlpha的API,还真有,那就好说。通过API访问https://api.wolframalpha.com/v2/query?input=root+locus+for+transfer+function+(s%5E2%2B3)%2F(s%5E3%2B5)&format=image&output=JSON&appid=DEMO可以得到一个这样的json:

{
    "queryresult": {
        "success": true,
        "error": false,
        "numpods": 2,
        "datatypes": "ControlSystem",
        "timedout": "",
        "timedoutpods": "",
        "timing": 2.244,
        "parsetiming": 1.397,
        "parsetimedout": false,
        "recalculate": "",
        "id": "MSPa3194185g424ef9ic5i8b000031903e0de369bii3",
        "host": "http://www4d.wolframalpha.com",
        "server": "15",
        "related": "http://www4d.wolframalpha.com/api/v2/relatedQueries.jsp?id=MSPa3195185g424ef9ic5i8b00002hd488g9fggigd5f3827527191664667052",
        "version": "2.6",
        "pods": [
            {
                "title": "Input interpretation",
                "scanner": "Identity",
                "id": "Input",
                "position": 100,
                "error": false,
                "numsubpods": 1,
                "subpods": [
                    {
                        "title": "",
                        "img": {
                            "src": "http://www4d.wolframalpha.com/Calculate/MSP/MSP3196185g424ef9ic5i8b00000e5afg304gfd51fb?MSPStoreType=image/gif&s=15",
                            "alt": "root locus plot | transfer function  (3 + s^2)/(5 + s^3)",
                            "title": "root locus plot | transfer function  (3 + s^2)/(5 + s^3)",
                            "width": 314,
                            "height": 55
                        }
                    }
                ]
            },
            {
                "title": "Root locus plot",
                "scanner": "ControlSystems",
                "id": "RootLocusPlot",
                "position": 200,
                "error": false,
                "numsubpods": 1,
                "subpods": [
                    {
                        "title": "",
                        "img": {
                            "src": "http://www4d.wolframalpha.com/Calculate/MSP/MSP3197185g424ef9ic5i8b0000445b174i6b48h4ea?MSPStoreType=image/gif&s=15",
                            "alt": "\n(shown for gain between 0 and 10)",
                            "title": "\n(shown for gain between 0 and 10)",
                            "width": 300,
                            "height": 318
                        }
                    }
                ],
                "states": [
                    {
                        "name": "Increase range",
                        "input": "RootLocusPlot__Increase range"
                    },
                    {
                        "name": "Decrease range",
                        "input": "RootLocusPlot__Decrease range"
                    }
                ]
            }
        ]
    }
}

这样只用通过javascript进行http的get请求就能行了。理论很美满,显示很骨感,试了大半天,总是会遇到Access-Control-Allow-Origin的问题。上谷歌去查各种方案,都说WolframAlpha的API不能通过javascript访问,要么用服务端代码,要么用proxy,好像没有解决方案。但是,在网上查javascript跨域的问题,也是得到了一大堆奇奇怪怪的解决方法,我最终实现了跨域访问:

var str1 = document.getElementById("num").value;
var str2 = document.getElementById("den").value;
var querystr = "https://api.wolframalpha.com/v2/query?input=root+locus+for+transfer+function+(" +
    encodeURIComponent(str1) + encodeURIComponent(")/(") + encodeURIComponent(str2) +
    ")&format=image&output=JSON&appid=XXXX&callback=?";
$.ajax({ 
  type: 'GET', 
  url: querystr , 
  //是否使用缓存 
  cache:false, 
  //数据类型,这里我用的是json 
  dataType: "json", 
  crossDomain: true, 
  //必要的时候需要用JSON.stringify() 将JSON对象转换成字符串 
  //data: JSON.strigify({key:value}), 
  //data : ""
  //请求成功的回调函数 success: 
  success : function(data){  
    document.getElementById("res1").src = data.queryresult.pods[0].subpods[0].img.src;
    document.getElementById("res2").src = data.queryresult.pods[1].subpods[0].img.src;
  }
});

不知道实现了跨域访问的原因到底是在URL里面加了”&callback=?”还是设置了crossDomain为true的原因:cold_sweat:。这样就实现了在网页上绘制根轨迹。不过这个网页的使用体验肯定没有安卓版的easyAuto好,一个是输入格式更为严格,第二个是速度太慢。就这个访问速度,我相信即使是javascript代码也能做到更快把图画出来,不过我是真的不想再去用javascript写数值的代码了。

螺旋桨性能查询网页

做这个的原因和上一个一样,想实现彻底的跨平台。之前把demoProp的所有数据全部导入到了一个sqlite文件中,加上索引一共40+MB,正好在网上看到了sql.js项目,这个是emscripten把sqlite直接翻译过来的结果,想试一试,于是把数据库和网页挂在网上,试了试发现访问速度太慢了。而且一不注意,手机用了200+MB的流量,血淋淋的教训啊。我明白这个的意思了:用http请求把url的数据库先下载下来,然后再在内存中运行sql语句。这个代价相比PHP+MySQL的代价的确太大了。我把索引全部删除,数据库的大小还是20+MB,没办法,想了想一般在无人机我们关注的是静拉力,于是删除了所有动拉力数据,仅保留静拉力数据,这下只有600+KB了。再把一些无关的字段删去,sqlite对sql的支持太差,删除字段还需要这样写:

create table temp as select propName,RPM,PWR,Thrust from propellers;  
drop table propellers;  
alter table temp rename to propellers;  

这样数据库只剩300KB了。当然,也可以把所有数据以文本形式保存在网站上,具体对于某个螺旋桨,只需要读取具体的一个数据就行,不过处理文件肯定没有sql语句来得方便。

关于图表的绘制,我使用的是ECharts3.而UI的绘制则是使用jQuery Mobile,都是直接挂的bootcdn,希望服务器不要宕机:stuck_out_tongue_winking_eye:。jQuery Mobile的空间要想更好地适应移动端,需要加上如下代码:

<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1">

最后放上链接: 在线绘制根轨迹 在线查询螺旋桨数据

阅读全文 »

将VS code和Sublime Text3的VIM改成behave-mswin-like

发表于 2018-03-31 | 分类于 Programming

修改sublime和VS code的keymap配置,使其能够有mswin.vim的操作方式。


最近学习VIM,但是我一般不直接用VIM,因为配置插件太过于麻烦,而且UI感觉也不美观,因此我用的都是别的IDE/编辑器的VIM操作模式。Qt creator自带的fakeVim感觉非常好用,因为可以直接导入vimrc文件。我平时的习惯还是希望能够有mswin.vim的配置,包括Home和End键,Qt Creator导入很方便。而Kate, Kile虽然也提供导入vimrc文件的功能,但是实现很不完整,还是需要自己手动修改keymap。Kile是一个可以支持vim操作模式的LaTeX的IDE,这一点非常好。

Kate和Kile

这个一开始就是在设置里面进行手动地输入。也需要改一下热键,Ctrl+Q原本是关闭程序的,我把它改成了Alt+Q。最后得到了一个katevirc的文件,Kile和KDevelop都会按照这个配置来。文件的全文如下:

[Kate Vi Input Mode Settings]
Command Mode Mapping Keys=
Command Mode Mappings=
Command Mode Mappings Recursion=
Insert Mode Mapping Keys=<c-y>,<end>,<c-v>,<c-z>,<home>,<c-a>
Insert Mode Mappings=<c-o><c-r>,<c-o>$,<esc>"+gPi,<c-o>u,<c-o>^,<esc>ggvG
Insert Mode Mappings Recursion=false,false,false,false,false,false
Macro Completions=
Macro Contents=
Macro Registers=
Map Leader=\\
Normal Mode Mapping Keys=<c-y>,<c-tab>,<c-q>,<end>,<c-v>,<c-s>,<c-z>,<home>,<c-a>,<c-f4>
Normal Mode Mappings=U,<c-w>w,<c-v>,$,"+gP,:w<cr>,u,^,ggvG,<c-w>c
Normal Mode Mappings Recursion=false,false,false,false,false,false,false,false,false,false
Visual Mode Mapping Keys=<c-x>,<end>,<c-v>,<home>,<c-a>,<c-c>
Visual Mode Mappings="+x,$,"+p,^,vggvG,"+y<esc>
Visual Mode Mappings Recursion=false,false,false,false,false,false

Sublime Text 3

这个需要安装插件NeoVintageous,别的插件功能太弱。这个插件可以自己写配置文件,不过也不是很强大,imap这些不支持。不过在Insert Mode里面似乎是直接支持相关操作的。另外不知道为什么,Normal Mode里面的Ctrl+S不可用。配置文件全文如下:

"" backspace in Visual mode deletes selection  
vnoremap <BS> d  
"   
"" CTRL-X and SHIFT-Del are Cut  
vnoremap <C-x> "+x  
"
vnoremap <S-Del> "+x  
"   
"" CTRL-C and CTRL-Insert are Copy  
vnoremap <C-c> "+y  
vnoremap <C-Insert> "+y  
"   
"" CTRL-V and SHIFT-Insert are Paste  
""map <C-v>        p  
noremap <C-v>         "+p 

"" Pasting blockwise and linewise selections is not possible in Insert and  
"" Visual mode "without the +virtualedit feature.  They are pasted as if they  
"" were characterwise instead.  
"" Uses the paste.vim auto"load script.  
"   
vmap <S-Insert>        <C-V>  
"   
"" Use CTRL-Q to do what CTRL-V used to do 
nnoremap <C-q>        <C-v>  
"   
"" Use CTRL-S for saving, also in Insert mode  
"noremap <C-s>        :w   
"vnoremap <C-s>       v:w  
"   

"" CTRL-Z is Undo; not in cmdline though  
noremap <C-z> u  
"   
"" CTRL-Y is Redo (although not repeat); not in cmdline though  
noremap <C-y> <C-r>  
""inoremap <C-Y> <C-O><C-R>  
"
"" CTRL-A is Select all  
noremap <C-a> ggvG
""onoremap <C-a> <C-C>gggH<C-O>G  
""snoremap <C-a> <C-C>gggH<C-O>G  
vnoremap <C-a> vggvG   
"" CTRL-Tab is Next window  
noremap <C-Tab> <C-W>w  
onoremap <C-Tab> <C-C><C-W>w   
"
"   
"" CTRL-F4 is Close window  
noremap <C-F4> <C-W>c  
onoremap <C-F4> <C-C><C-W>c  
"     
nnoremap i i<Ctrl-Shift-1>  

VS Code

这个需要同时改一些Key binding和vim插件的配置,用户设置文件如下:

{
    "markdown-preview-enhanced.mathRenderingOption": "MathJax",
    "emmet.showSuggestionsAsSnippets": true,
    "[markdown]": {
        "editor.quickSuggestions":true    
    },
    "latex-workshop.view.pdf.viewer": "tab",
    "latex-workshop.view.pdf.hand": true,
    // 可变编译方式 
    "latex-workshop.latex.toolchain": [
        {
          "command": "", // 注意这里是留空的
          "args": [
            "-synctex=1",
            "-interaction=nonstopmode",
            "-file-line-error",
            "%DOC%"
          ]
        }
      ],
      "window.zoomLevel": 1,
      "vim.neovimPath": "D:\\downloads\\nvim-win64\\Neovim\\bin\\nvim.exe",
      "vim.enableNeovim": true,
      "vim.insertModeKeyBindings": [
        {  
          "before":["<C-v>"],  
          "after":["\"+gP"],  
        },  
      ],
      "vim.insertModeKeyBindingsNonRecursive": [
        {  
          "before":["<C-s>"],  
          "after":["<C-o>:w"],  
        }, 
        {  
          "before":["<C-z>"],  
          "after":["<C-o>u"],  
        },  
        {  
          "before":["<C-y>"],  
          "after":["<C-o><C-r>"],  
        },
        {  
          "before":["<C-a>"],  
          "after":["<C-o>gg<C-o>gH<C-o>G"],  
        },
         {  
          "before":["<C-Tab>"],  
          "after":["<C-O><C-W>w"],  
        },
         {  
          "before":["<C-F4>"],  
          "after":["<C-O><C-W>c"],  
        },       
      ],
      "vim.otherModesKeyBindingsNonRecursive": [
        {  
          "before":["<C-s>"],  
          "after":[":w"],  
        },
        {  
          "before":["<C-z>"],  
          "after":["u"],  
        }, 
        {  
          "before":["<C-y>"],  
          "after":["<C-r>"],  
        },
        {  
          "before":["<C-a>"],  
          "after":["gggH<C-O>G"],  
        },
        {  
          "before":["<C-F4>"],  
          "after":["<C-w>c"],  
        },
      ],
      "vim.otherModesKeyBindings": [],
  }

Key Binding的配置文件如下:

// 将键绑定放入此文件中以覆盖默认值
[
    {
        "key": "alt+q",
        "command": "workbench.action.quickOpenView"
    },
    {
        "key": "ctrl+q",
        "command": "-workbench.action.quickOpenView"
    },
    {
        "key": "alt+q",
        "command": "workbench.action.quickOpenNavigateNextInViewPicker",
        "when": "inQuickOpen && inViewsPicker"
    },
    {
        "key": "ctrl+q",
        "command": "-workbench.action.quickOpenNavigateNextInViewPicker",
        "when": "inQuickOpen && inViewsPicker"
    },
    {
        "key": "alt+y",
        "command": "extension.vim_ctrl+y",
        "when": "editorTextFocus && vim.active && vim.use<C-y> && !inDebugRepl"
    },
    {
        "key": "ctrl+y",
        "command": "-extension.vim_ctrl+y",
        "when": "editorTextFocus && vim.active && vim.use<C-y> && !inDebugRepl"
    },
    {
        "key": "alt+a",
        "command": "extension.vim_ctrl+a",
        "when": "editorTextFocus && vim.active && vim.use<C-a> && !inDebugRepl"
    },
    {
        "key": "ctrl+a",
        "command": "-extension.vim_ctrl+a",
        "when": "editorTextFocus && vim.active && vim.use<C-a> && !inDebugRepl"
    },
    {
        "key": "alt+c",
        "command": "extension.vim_ctrl+c",
        "when": "editorTextFocus && vim.active && vim.overrideCtrlC && vim.use<C-c> && !inDebugRepl"
    },
    {
        "key": "ctrl+c",
        "command": "-extension.vim_ctrl+c",
        "when": "editorTextFocus && vim.active && vim.overrideCtrlC && vim.use<C-c> && !inDebugRepl"
    },
    {
        "key": "ctrl+q",
        "command": "extension.vim_ctrl+v",
        "when": "editorTextFocus && vim.active && vim.use<C-v> && !inDebugRepl && vim.mode != 'Insert'"
    },
    {
        "key": "ctrl+v",
        "command": "-extension.vim_ctrl+v",
        "when": "editorTextFocus && vim.active && vim.use<C-v> && !inDebugRepl && vim.mode != 'Insert'"
    }
]

其他

还是没有解决输入法切换的Keymap:disappointed:。还有为什么Jekyll的右边生成的目录排版有时会抽风啊?

阅读全文 »

利用AutoHotKey实现VI编辑模式下ESC键自动切换至英文输入法

发表于 2018-03-26 | 分类于 Programming

利用AutoHotKey实现ESC自动切换输入法。


最近学习VIM,然而大多数情况下都是用的各种编辑器的VIM模式,我一般不会去使用GVim。然而每次的输入法切换非常影响键入。因此在知乎上搜索到了如下的解决方案:

#Persistent ;一直运行
~esc::

Send, {ESC}

; 下方代码可只保留一个
SwitchIME(0x04090409) ; 英语(美国) 美式键盘
SwitchIME(0x08040804) ; 中文(中国) 简体中文-美式键盘
return


SwitchIME(dwLayout){
    HKL:=DllCall("LoadKeyboardLayout", Str, dwLayout, UInt, 1)
    ControlGetFocus,ctl,A
    SendMessage,0x50,0,HKL,%ctl%,A
}

作者:杜立涛 链接:https://www.zhihu.com/question/41446565/answer/91110371 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 不过这个还存在一些不方便的地方,看以后我是渐渐习惯了这些麻烦还是自己又继续来深入AutoHotKey:

  • 重新回到INSERT模式时,我希望回到中文输入法
  • 在不是编辑器的窗口里,我希望ESC键是一个正常的功能
阅读全文 »

一个点球大战游戏的开发

发表于 2018-03-24 | 分类于 Programming

开发了一个点球大战的手机小游戏。


开发了一个点球大战的小游戏,实现了游戏引擎与GUI的分离。

球员类

射手类

类的定义如下:

class striker{
public:
    striker(){}
    striker(bool AI);

    double pShootLeft;
    double pShootRight;
    double pShootCenter;

    QString name;

    direction shoot();

    bool isAI;

};

这里需要考虑的一个问题是:为了追求尽可能模拟现实,因此罚点球射向左边、右边的概率会远大于射向中间的概率,因此对于一个非用户操控的球员(即AI操控的球员),概率如下:

unsigned seed1 = std::chrono::system_clock::now().time_since_epoch().count();
std::mt19937 generator(seed1);
std::uniform_real_distribution<double> dis(0,1.0);
auto dice= std::bind(dis,generator);
isAI = true;
double l = dice();
double c = dice();
double r = dice();
pSaveLeft = (.95 * l) / (.95 * l + .95 * r + .1 * c);
pSaveRight = (.95 * r) / (.95 * l + .95 * r + .1 * c);
pSaveCenter = (.1 * c) / (.95 * l + .95 * r + .1 * c);

MinGW都没有实现std::default_random_device,因此用了种子的方法生成随机数。

守门员和这个类似,就不再赘述了。

游戏引擎

这是第一次对这个东西进行了架构,与GUI分离后,实现松耦合后能够很容易地编码。不过由于也是第一次架构,因此也存在一些或许不合理的地方。实际上用设计模式应该会收到更好的效果。

回合类

class rounds{
private:
    direction direc;

public:
    rounds(striker *st1, goalKeeper *gk1, game* eng);
    rounds(striker *st1, goalKeeper *gk1, direction direct, game* eng);

    QString string1;
    QString string2;
    QString string3;

    striker* st;
    goalKeeper* gk;

    game* m_game;

    bool goal();
};

引擎类

class game{
public:
    game(bool youAreKnown, bool youCanKonwAll, int userTurn);

    // The round number represents the already finished rounds counter
    int redRound;
    int redScore;
    int blueRound;
    int blueScore;
    int usrTurn;
    goalKeeper redGK;
    goalKeeper blueGK;
    std::vector<striker> stsRed;
    std::vector<striker> stsBlue;
    bool youKnowAll;
    bool redFirst;

    bool usrNeedInput();
    void nextRound();
    void nextRound(direction dir);
    gameState getGameState();
    roundState getRoundState();

    QString string1;
    QString string2;
    QString string3;

//private:
    allStr stringEngine;

};

game类里面主要就是nextRound成员函数构造round类并进行模拟。这里也是有一些设计的有一些欠妥当,导致round类的构造函数需要一个game的指针,以让关于游戏信息的字符串传回去。

在点球大战中还需要专门判断点球大战是否提前结束了,这样才更符合真实的点球大战,因为如果某一方劣势已经确定就不会踢满5轮点球大战了。

gameState game::getGameState()
{
    if (redRound > 5 && blueRound == redRound){
        if(redScore == blueScore) return notFinished;
        if(redScore > blueScore) return redWin;
        if(redScore < blueScore) return blueWin;
    }
    if(redRound > 5 || blueRound > 5){
        return notFinished;
    }
    if(redScore > (5 - blueRound + blueScore)){
        return redWin;
    }
    if(blueScore > (5 - redRound + redScore)){
        return blueWin;
    }
    return notFinished;
}

字符串引擎

为了实现松耦合,需要专门设计一个字符串处理的类,类的定义如下:

class allStr
{
public:
    allStr();

    QString getPrologue();
    QString getStIntro();
    QString getRedWinStr();
    QString getBlueWinStr();
    QString getPenaltyStr(direction shootDirection, direction saveDirection, bool outside, bool goal);

//private:
    std::vector<QString> redGkName;
    std::vector<QString> redStName;
    std::vector<QString> blueGkName;
    std::vector<QString> blueStName;

    std::vector<QString> prologue1;
    std::vector<QString> prologue2;
    std::vector<QString> prologue3;

    std::vector<QString> stIntro1;
    std::vector<QString> stIntro2;

    std::vector<QString> redWinStr1;
    std::vector<QString> redWinStr2;
    std::vector<QString> blueWinStr1;
    std::vector<QString> blueWinStr2;

    std::vector<QString> sameNoGoal1;
    std::vector<QString> sameNoGoal2;
    std::vector<QString> sameAndGoal1;
    std::vector<QString> sameAndGoal2;
    std::vector<QString> lrOutside1;
    std::vector<QString> lrOutside2;

    std::vector<QString> lr_c_goal1;
    std::vector<QString> lr_c_goal2;
    std::vector<QString> lr_c_noGoal1;
    std::vector<QString> lr_c_noGoal2;

    std::vector<QString> lr_wrongSave1;
    std::vector<QString> lr_wrongSave2;

    std::vector<QString> c_outside;
    std::vector<QString> c_lr_goal1;
    std::vector<QString> c_lr_goal2;

    std::vector<QString> c_c1;
    std::vector<QString> c_c2;

    std::vector<QString> c_lr_noGoal1;
    std::vector<QString> c_lr_noGoal2;

};

这些字符串在构造函数里面将所有的字符串插入并使用std::shuffle打乱,通过获取字符串的成员函数可以返回一些随机的但是能够组合在一起的句子,成为游戏中的解说信息。

总结

这里写得很少,但是完成这个小游戏还是费挺大劲,遇到了各种各样奇奇怪怪的坑。什么定时器的使用,各种结果的处理,还是挺麻烦的。另外这里我还是没有考虑到点球大战踢满11轮的情况,一旦踢满11轮程序按理说会崩溃,但是现在晚了这么久我还没有遇到哪一次踢满了11轮:satisfied:。

阅读全文 »

实现Qt程序的新版本检查

发表于 2017-12-17 | 分类于 Programming

利用GitHub提供的API,实现程序的新版本检查功能。


GitHub的开发者API

对于GitHub上的仓库,我们可以发布Release,每个Release除了源代码以外还可以附加编译后的二进制文件。发布Release之后便可以通过API获取一些有用的信息。不过需要注意的是,如下图所示,发布的Release是不能勾选“This is a pre-release”选项的。 例如对于我的easyAuto仓库,那么API是https://api.github.com/repos/scienceasdf/accoutAssist/releases/latest。在浏览器中打开,可以看出这里提供json格式的许多信息。当然,如果是pre-release版本的话,就会得到下面的结果:

{
  "message": "Not Found",
  "documentation_url": "https://developer.github.com/v3/repos/releases/#get-the-latest-release"
}

Qt的HTTPS请求与处理

首先需要在.pro文件中加上这两句,分别是加上网络模块和版本号的宏定义:

QT      += ... network
DEFINES += "VERSION=2.2"

接下来就是具体实现的代码:

#include <QtNetwork>
// ...
void accountAssit::on_checkUpdate_clicked()
{
    QNetworkAccessManager networkManager;


    QUrl url("https://api.github.com/repos/scienceasdf/accoutAssist/releases/latest");
    QNetworkRequest request;
    request.setUrl(url);

    m_currentReply = networkManager.get(request);  // GET
    connect(&networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(onResultUpdate(QNetworkReply*)));
    QEventLoop eventLoop;
    QObject::connect(&networkManager, &QNetworkAccessManager::finished, &eventLoop, &QEventLoop::quit);
    eventLoop.exec();
}

void accountAssit::onResultUpdate(QNetworkReply * reply)
{
    if (m_currentReply->error() != QNetworkReply::NoError){
        //qDebug()<<"ERROR!";
        return;  // ...only in a blog post
    }

    QString data = (QString) reply->readAll();
    qDebug()<<data;
    QJsonDocument d = QJsonDocument::fromJson(data.toUtf8());
    QJsonObject sett2 = d.object();
    QJsonValue value = sett2.value(QString("tag_name"));
    qDebug() << value;
    if(value.toDouble() > VERSION){
        QMessageBox::StandardButton button;
        button = QMessageBox::question(this, tr("有新的版本"),
                QString(tr("是否下载新的版本?")),
                QMessageBox::Yes | QMessageBox::No);

            if (button == QMessageBox::Yes){

        }
    }
    else{
        QMessageBox::information(0, "更新检查","此版本已经是最新发布版本", QMessageBox::Yes);
    }
}

在代码中,accountAssist是一个窗体,里面有一个类型为QNetworkReply*的重要成员:m_currentReply,用来保存网络是否正常的状态。当在获取HTTPS内容时,使用QEventLoop不阻塞GUI线程。当全文获取之后,转到槽函数onResultUpdate,对收到的所有内容进行处理。Qt自带了QJson的处理,非常的方便。如果发现最新版的release版本号大于宏定义的版本号,那么就提示有新的版本。不过这个也太简单粗暴了,如果版本号是从2.1更新到了2.10,这种方法就不奏效。解决方法也很简单,定义大版本号和小版本号,分别比较。比如“2.10”,QString自带了split函数,其实之前做easyAuto还可以用这个方法

QStringList list = QString("2.10").split("\n");
foreach(QString str, list){
	//...
}

最后值得注意的是,在安卓程序里,必须要SSL连接,所以需要在网上下载libcrypto.so和libssl.so,并在.pro文件里加上

android {
  ANDROID_EXTRA_LIBS += $$PWD/libcrypto.so
  ANDROID_EXTRA_LIBS += $$PWD/libssl.so
}
阅读全文 »

实现Qt程序的滑动手势

发表于 2017-12-16 | 分类于 Programming

Copy了一份实现单指滑动手势的源码。

阅读全文 »

easyAuto的单元测试

发表于 2017-11-16 | 分类于 Programming

出于各种考虑,在easyAuto里面我第一次写了单元测试。

阅读全文 »
1 … 4 5 6 7
scienceasdf

scienceasdf

We will bury them !

45 日志
10 分类
RSS
GitHub ZhiHu 404公益@宝贝回家 神奇的网页
© 2017 - 2020 scienceasdf
由 Jekyll 强力驱动
主题 - NexT.Pisces