在这篇文章里,我们将使用Ubuntu SDK从零开始来创建一个“中国天气”的Scope应用。通过这个过程,让开发者了解Scope在Ubuntu上的开发流程,以及对Scope有更深的认识。该应用完全使用std C++来完成的。更多关于Scope的知识,可以在网址:http://developer.ubuntu.com/scopes/。我们开发应用的最终显示图为:

     

1)启动Ubuntu SDK来创建一个基本的Scope应用

首先,我们来打开我们的Ubuntu SDK来创建一个最基本的应用。我们选择菜单“New file or Project”或使用热键“Ctrl + N”。我们选择“Unity Scope”模版。
我们给我们的应用一个名字“ChinaWeather”。我们同事也选择template的类型为“Scope using HTTP+JSON API”
   
接下来,我们也同时选择不同的Kit,这样我们都可以在他们上面编译并部署我们的应用。
我们直接在电脑的Desktop上运行我们的应用。为了确保我们能够在desktop上运行我们的scope并看到界面,我们可以点击“Projects”,并在Desktop中的“Run Configuration”中进行设置。确保选中“chinaweather”。
我们可以在“Unity Scope tool”中输入北京,我们就可以看到北京的天气的情况:
如果你能运行到这里,说明你的安装环境是没有问题的。如果有问题的话,请参阅我的Ubuntu SDK安装文章。这个最基本的应用其实没有什么内容。在下面的章节中我们来向这里添加一些东西以实现我们所需要的一些东西。
如果大家有手机的话,也可以直接在手机上运行看一下运行的效果。

2)完成我们的Client API代码

我们可以看到在项目的“src”目录下有两个目录:apiscope。api目录下的代码主要是为了来访问我们的web service来得到一个json或是xml的数据。这个数据可以在我们的Scope中进行利用并得到显示。下面我们来完成我们的工作。
首先我们需要在百度的开发者网站来申请我们的开发者账号。大家可以放问网站来申请账号。我们首先来做一个测试以确保我们的账号是可以工作的。按照文中所提到的,我们可以在浏览器中输入如下的地址:http://api.map.baidu.com/telematics/v3/weather?location=%E5%8C%97%E4%BA%AC&output=json&ak=DdzwVcsGMoYpeg5xQlAFrXQt。我们可以得到如下的内容:
{"error":0,"status":"success","date":"2014-09-29","results":[{"currentCity":"北京","pm25":"42","index":[{"title":"穿衣","zs":"较冷","tipt":"穿衣指数","des":"建议着大衣、呢外套加毛衣、卫衣等服装。体弱者宜着厚外套、厚毛衣。因昼夜温差较大,注意增减衣服。"},{"title":"洗车","zs":"较不宜","tipt":"洗车指数","des":"较不宜洗车,未来一天无雨,风力较大,如果执意擦洗汽车,要做好蒙上污垢的心理准备。"},{"title":"旅游","zs":"适宜","tipt":"旅游指数","des":"天气较好,温度适宜,但风稍微有点大。这样的天气适宜旅游,您可以尽情地享受大自然的无限风光。"},{"title":"感冒","zs":"易发","tipt":"感冒指数","des":"昼夜温差大,风力较强,易发生感冒,请注意适当增减衣服,加强自我防护避免感冒。"},{"title":"运动","zs":"较适宜","tipt":"运动指数","des":"天气较好,但风力较大,推荐您进行室内运动,若在户外运动请注意避风保暖。"},{"title":"紫外线强度","zs":"弱","tipt":"紫外线强度指数","des":"紫外线强度较弱,建议出门前涂擦SPF在12-15之间、PA+的防晒护肤品。"}],"weather_data":[{"date":"周一 09月29日 (实时:23℃)","dayPictureUrl":"http://api.map.baidu.com/images/weather/day/duoyun.png","nightPictureUrl":"http://api.map.baidu.com/images/weather/night/qing.png","weather":"多云转晴","wind":"北风4-5级","temperature":"23 ~ 10℃"},{"date":"周二","dayPictureUrl":"http://api.map.baidu.com/images/weather/day/duoyun.png","nightPictureUrl":"http://api.map.baidu.com/images/weather/night/yin.png","weather":"多云转阴","wind":"微风","temperature":"18 ~ 12℃"},{"date":"周三","dayPictureUrl":"http://api.map.baidu.com/images/weather/day/zhenyu.png","nightPictureUrl":"http://api.map.baidu.com/images/weather/night/zhenyu.png","weather":"阵雨","wind":"微风","temperature":"15 ~ 12℃"},{"date":"周四","dayPictureUrl":"http://api.map.baidu.com/images/weather/day/duoyun.png","nightPictureUrl":"http://api.map.baidu.com/images/weather/night/duoyun.png","weather":"多云","wind":"微风","temperature":"23 ~ 13℃"}]}]}

首先,我们可以看到API是工作的。没有任何问题。显示的架构是json格式的。我们下面来修改架构中的“Client”类来完成对所得到的json格式的内容进行解析。首先,我们删除整个“Client::Current Client::weather(const string& query)”函数,因为这个是我们不需要的。为了能够编译,我们也删除或注释掉在query.cpp文件run函数中的部分内容,这样我们可以集中精力来完成这个Client API的设计。我们只留下最基本的部分以帮助我们来完成如下的设计。

void Query::run(sc::SearchReplyProxy const& reply) {try {// Start by getting information about the queryconst sc::CannedQuery &query(sc::SearchQueryBase::query());// Trim the query string of whitespacestring query_string = alg::trim_copy(query.query_string());Client::Forecast forecast;if (query_string.empty()) {// If there is no search string, get the forecast for Londonforecast = client_.forecast_daily("北京");} else {// otherwise, get the forecast for the search stringforecast = client_.forecast_daily(query_string);}// Register a category for the forecastauto forecast_cat = reply->register_category("forecast","7 day forecast", "", sc::CategoryRenderer(WEATHER_TEMPLATE));// For each of the forecast daysfor (const auto &weather : forecast.weather) {// Create a resultsc::CategorisedResult res(forecast_cat);}} catch (domain_error &e) {// Handle exceptions being thrown by the client APIcerr << e.what() << endl;reply->error(current_exception());}
}
为了能够正确地使用API,我们还必须在项目的设置文件中做一些设置。打开IDE项目中的api文件夹,并打开config.h文件。把它的内容修改为:
#ifndef API_CONFIG_H_
#define API_CONFIG_H_#include <memory>
#include <string>namespace api {struct Config {typedef std::shared_ptr<Config> Ptr;/** The root of all API request URLs*/std::string apiroot { "http://api.map.baidu.com" };/** The custom HTTP user agent string for this library*/std::string user_agent { "chineweather 0.1; (foo)" };
};}#endif /* API_CONFIG_H_ */

为了适应我们的情况,我们把forecast_daily API修改为:

    virtual Forecast forecast_daily(const std::string &query);

这是因为我们的百度API中不需要天数。为了能够使得我们的数据结构和我们上面百度天气API接口返回的数据相匹配,我们对“client.h”做了修改:

class Client {
public:/*** Information about a City*/struct City {unsigned int id;std::string name;std::string country;};/*** Weather information for a day.*/struct Weather {std::string date;std::string dayPictureUrl;std::string nightPictureUrl;std::string weather;std::string wind;std::string temperature;std::string uri;};/*** A list of weather information*/typedef std::deque<Weather> WeatherList;/*** Forecast information about a city*/struct Forecast {City city;std::string pmIndex;WeatherList weather;};Client(Config::Ptr config);virtual ~Client() = default;/*** Get the weather forecast for the specified location and duration*/virtual Forecast forecast_daily(const std::string &query);/*** Cancel any pending queries (this method can be called from a different thread)*/virtual void cancel();virtual Config::Ptr config();protected:void get(const core::net::Uri::Path &path,const core::net::Uri::QueryParameters ¶meters,Json::Value &root);/*** Progress callback that allows the query to cancel pending HTTP requests.*/core::net::http::Request::Progress::Next progress_report(const core::net::http::Request::Progress& progress);/*** Hang onto the configuration information*/Config::Ptr config_;/*** Thread-safe cancelled flag*/std::atomic<bool> cancelled_;
};}

特别值得注意的是,我们修改了weather的数据结构。这个和我们从百度API中返回的数据结构是一样的:

{"date":"周一 09月29日 (实时:23℃)","dayPictureUrl":"http://api.map.baidu.com/images/weather/day/duoyun.png","nightPictureUrl":"http://api.map.baidu.com/images/weather/night/qing.png","weather":"多云转晴","wind":"北风4-5级","temperature":"23 ~ 10℃"}

下面我们来看一看在client.cpp文件中的“get"函数。这是一个标准的函数接口。它是通过http来访问所需要访问输入参数所提供的地址,并得到相应的内容。这个内容可以是json或xml形式的。这个函数,我们不需要做任何的改变。

void Client::get(const net::Uri::Path &path, const net::Uri::QueryParameters &parameters, json::Value &root)

我们来修改forecast_daily函数,如下:

Client::Forecast Client::forecast_daily(const string& query) {json::Value root;// Build a URI and get the contents// The fist parameter forms the path part of the URI.// The second parameter forms the CGI parameters.get( { "telematics", "v3", "weather" },{ { "location", query },{ "output", "json" }, { "ak", "DdzwVcsGMoYpeg5xQlAFrXQt" } }, root);// e.g. http://api.map.baidu.com/telematics/v3/weather?location=%1&output=json&ak=DdzwVcsGMoYpeg5xQlAFrXQtForecast result;//    // Iterate through the weather datastring date = root["date"].asString();cerr << "date: "  << date << endl;int indexofYear = date.find_first_of("-", 0);cerr << "indexofYear: " << indexofYear << endl;string year = date.substr(0, indexofYear);cerr << "year: " << year << endl;int indexofMonth = date.find("-", indexofYear+1);cerr << "indexofMonth: " << indexofMonth << endl;string month = date.substr(indexofYear + 1, indexofMonth-indexofYear-1);cerr << "month: " << month << endl;string day = date.substr(indexofMonth +1, date.length()-indexofMonth);cerr << "day: " << day << endl;std::locale::global(std::locale(""));// current date/time based on current systemtime_t now = time(0);tm *localtm = localtime(&now);localtm->tm_year = stoi( year ) - 1900;localtm->tm_mon = stoi( month );localtm->tm_mday = stoi( day );json::Value results = root["results"];for (json::ArrayIndex index = 0; index < results.size(); ++index) {json::Value item = results.get(index, json::Value());// Extract the first weather itemresult.city.name = item["currentCity"].asString();cerr << "city name: " << result.city.name << endl;result.pmIndex = item["pm25"].asString();cerr << "PM index: " << result.pmIndex  << endl;json::Value weathers = item["weather_data"];for ( json::ArrayIndex i = 0; i < weathers.size(); i ++ ) {json::Value weather = weathers.get(i, json::Value());localtm->tm_mday++;time_t newtime = mktime(localtm);tm *newlocaltm = localtime(&newtime);char buffer[256];strftime(buffer, sizeof(buffer), "%a %Y年%b%d ", newlocaltm);string date = buffer;cerr << "date: " << date << endl;string dayPictureUrl = weather["dayPictureUrl"].asString();cerr << "dayPictureUrl: " << dayPictureUrl << endl;string nightPictureUrl = weather["nightPictureUrl"].asString();cerr << "nightPictureUrl: " << nightPictureUrl << endl;string weather1 = weather["weather"].asString();cerr << "weather: " << weather1 << endl;string temperature = weather["temperature"].asString();cerr << "temperature: " << temperature << endl;string wind = weather["wind"].asString();cerr << "wind: " << wind << endl;cerr << "====================================" << endl;result.weather.emplace_back(Weather { date,dayPictureUrl,nightPictureUrl,weather1,wind,temperature,URI});}}return result;
}
同时我们在client.h中定义如下的宏:
#define URI "http://www.weather.com.cn/html/weather/101010100.shtml"
重新编译项目,如果遇到任何的问题,我们必须停下来解决以使得整个项目能够被正确地编译。在Ubuntu Desktop下运行我们的应用。我们可以在Application Output窗口看见许多的输出。

3)代码讲解

src/scope/scope.cpp

这个文件定义了一个unity::scopes::ScopeBase的类。它提供了客户端用来和Scope交互的起始接口。

  • 这个类定义了“start", "stop"及"run"来运行scope。绝大多数开发者并不需要修改这个类的大部分实现。在我们的例程中,我们将不做任何的修改
  • 它也同时实现了另外的两个方法:search 和 preview。我们一般来说不需要修改这俩个方法的实现。但是他们所调用的函数在具体的文件中必须实现

注意:我们可以通过研究Scope API的头文件来对API有更多的认识。更多的详细描述,开发者可以在http://developer.ubuntu.com/api/scopes/sdk-14.10/查看。

src/scope/query.cpp

这个文件定义了一个unity::scopes::SearchQueryBase类。

这个类用来产生由用户提供的查询字符串而生产的查询结果。这个结果可能是基于json或是xml的。这个类可以用来进行对返回的结果处理并显示。

  • 得到由用户输入的查询字符串
  • 向web services发送请求
  • 生成搜索的结果(根据每个不同而不同)
  • 创建搜索结果category(比如不同的layout-- grid/carousel)
  • 根据不同的搜寻结果来绑定不同的category以显示我们所需要的UI
  • 推送不同的category来显示给最终用户

创建并注册CategoryRenderers

在本例中,我们创建了两个JSON objects. 它们是最原始的字符串,如下所示,它有两个field:template及components。template是用来定义是用什么layout来显示我们所搜索到的结果。这里我们选择的是”grid"及小的card-size。components项可以用来让我们选择预先定义好的field来显示我们所需要的结果。这里我们添加了"title"及“art"。

std::string CR_GRID = R"({"schema-version" : 1,"template" : {"category-layout" : "grid","card-size": "medium"},"components" : {"title" : "title","art" : {"field": "art","aspect-ratio": 1.6,"fill-mode": "fit"}}}

这是一个grid的layout,同时我们可以显示一个title及一个图片(art)。我们在文件的开始部分加入如上的的template的定义。

更多关于 CategoryRenderer 类的介绍可以在 docs找到。

我们为每个JSON Object创建了一个CategoryRenderer,并同时向reply object注册。我们修改我们的run方法来实现显示:

void Query::run(sc::SearchReplyProxy const& reply) {try {// Start by getting information about the queryconst sc::CannedQuery &query(sc::SearchQueryBase::query());// Trim the query string of whitespacestring query_string = alg::trim_copy(query.query_string());Client::Forecast forecast;cerr << "query_string: " << query_string;if (query_string.empty()) {// If there is no search string, get the forecast for Londonforecast = client_.forecast_daily("北京");} else {// otherwise, get the forecast for the search stringforecast = client_.forecast_daily(query_string);}// Register a category for the forecastauto forecast_cat = reply->register_category("Chineweather",forecast.city.name,"", sc::CategoryRenderer(CR_GRID));// For each of the forecast daysfor (const auto &weather : forecast.weather) {// Create a resultsc::CategorisedResult res(forecast_cat);// Set the rest of the attributesres.set_art(weather.dayPictureUrl);stringstream ss(stringstream::in | stringstream::out);ss << "白天: " << weather.date;res.set_title(ss.str());// We must have a URIres.set_uri(weather.uri);res.set_dnd_uri(weather.uri);// Add some extra data, and they will be shown in the previewres["weather"] = sc::Variant(weather.weather);res["temperature"] = sc::Variant(weather.temperature);res["wind"] = sc::Variant(weather.wind);// Push the resultif (!reply->push(res)) {// If we fail to push, it means the query has been cancelled.// So don't continue;return;}res.set_art(weather.nightPictureUrl);ss.str(std::string());ss << "夜晚: " << weather.date;res.set_title(ss.str());// We must have a URIres.set_uri(weather.uri);res.set_dnd_uri(weather.uri);// Push the resultif (!reply->push(res)) {// If we fail to push, it means the query has been cancelled.// So don't continue;return;}}} catch (domain_error &e) {// Handle exceptions being thrown by the client APIcerr << e.what() << endl;reply->error(current_exception());}
}

我们从我们的Client API中的Client::Forecast来获取我们所需要的web service的数据,把数据填入到相应的CategorisedResult中。

我们运行我们的程序,我们可以在屏幕上看到如下的画面:
    
我们也可以尝试点击我们的画面,在另外一个画面中可以看到一个图片。到这里,我们基本上已经看到了Scope工作的了。我们下面来更进一步来在Preview中显示更多的内容。

src/scope/preview.cpp

这个文件定义了一个unity::scopes::PreviewQueryBase类。

这个类定义了一个widget及一个layout来展示我们搜索到的结果。这是一个preview结i果,就像它的名字所描述的那样。

  • 定义在preview时所需要的widget
  • 让widget和搜索到的数据field一一对应起来
  • 定义不同数量的layout列(由屏幕的尺寸来定)
  • 把不同的widget分配到layout中的不同列中
  • 把reply实例显示到layout的widget中

大多数的代码在“run&quot;中实现。跟多关于这个类的介绍可以在http://developer.ubuntu.com/api/scopes/sdk-14.10/previewwidgets/找到。

Preview

Preview需要来生成widget并连接它们的field到CategorisedResult所定义的数据项中。它同时也用来为不同的显示环境(比如屏幕尺寸)生成不同的layout。根据不同的显示环境来生成不同数量的column。

Preview Widgets

这是一组预先定义好的widgets。每个都有一个类型。更据这个类型我们可以生成它们。你可以在这里找到Preview Widget列表及它们提供的的field类型。

这个例子使用了如下的widgets

  • header:它有title及subtitle field
  • image:它有source field有来显示从哪里得到这个art
  • text:它有text field
  • action:用来展示一个有"Open"的按钮。当用户点击时,所包含的URI将被打开

如下是一个例子,它定义了一个叫做“headerId"的PreviewWidget。第二个参数是它的类型"header"。

[cpp] view plaincopy
  1. PreviewWidget w_header("headerId", "header");

最终的程序如下:

#include <scope/preview.h>#include <unity/scopes/ColumnLayout.h>
#include <unity/scopes/PreviewWidget.h>
#include <unity/scopes/PreviewReply.h>
#include <unity/scopes/Result.h>
#include <unity/scopes/VariantBuilder.h>#include <iostream>namespace sc = unity::scopes;using namespace std;
using namespace scope;
using namespace unity::scopes;Preview::Preview(const sc::Result &result, const sc::ActionMetadata &metadata) :sc::PreviewQueryBase(result, metadata) {
}void Preview::cancelled() {
}void Preview::run(sc::PreviewReplyProxy const& reply) {//// This preview handler just reuses values of the original result via// add_attribute_mapping() calls, but it could also do another network// request for more details if needed.//// Client can display Previews differently depending on the context// By creates two layouts (one with one column, one with two) and then// adding widgets to them differently, Unity can pick the layout the// scope developer thinks is best for the modesc::ColumnLayout layout1col(1), layout2col(2);// add columns and widgets (by id) to layouts.// The single column layout gets one column and all widetslayout1col.add_column({"headerId", "artId", "tempId", "windId", "actionsId"});// The two column layout gets two columns.// The first column gets the art and header widgets (by id)layout2col.add_column({"artId", "headerId"});// The second column gets the info and actions widgetslayout2col.add_column({"infoId", "windId", "actionsId"});// Push the layouts into the PreviewReplyProxy intance, thus making them// available for use in Preview diplayreply->register_layout({layout1col, layout2col});//Create some widgets// header type first. note 'headerId' used in layouts// second field ('header) is a standard preview widget typePreviewWidget w_header("headerId", "header");// This maps the title field of the header widget (first param)  to the// title field in the result to be displayed in this preview, thus providing// the result-specific data to the preview for displayw_header.add_attribute_mapping("title", "title"); // attribute, result field name// Standard subtitle field here gets our 'artist' key valuew_header.add_attribute_mapping("subtitle", "weather");PreviewWidget w_art("artId", "image");w_art.add_attribute_mapping("source", "art"); // // key, result field namePreviewWidget w_info("tempId", "text");w_info.add_attribute_mapping("text", "temperature");PreviewWidget w_wind("windId", "text");w_wind.add_attribute_mapping("text", "wind");Result result = PreviewQueryBase::result();
//    QString urlString(result["uri"].get_string().c_str());cerr << "[Details] GET " << result["uri"].get_string() << endl;// Create an Open button and provide the URI to open for this preview resultPreviewWidget w_actions("actionsId", "actions");VariantBuilder builder;builder.add_tuple({{"id", Variant("open")},{"label", Variant("Open")},{"uri", Variant(result["uri"].get_string())} // uri set, this action will be handled by the Dash});w_actions.add_attribute_value("actions", builder.end());// Bundle out widgets as required into a PreviewWidgetListPreviewWidgetList widgets({w_header, w_art, w_info, w_wind, w_actions});// And push them to the PreviewReplyProxy as needed for use in the previewreply->push(widgets);
}

我们再重新运行程序,我们可以看到如下的画面:

      
在手机上的运行情况如下:
   
最后,我们可以找到data文件夹,并换上我们喜欢的应用图标。这样,我们就基本完成了我们所要完成的应用了。
所有的程序代码可以在如下的网址找到:
bzr branch lp:~liu-xiao-guo/debiantrial/chinaweathernew
该应用的另外一个用Qt进行开发的范例可以在如下的网址找到:
bzr branch lp:~liu-xiao-guo/debiantrial/chinaweatherfinal

4)调试Scope

当我们在开发应用时,我们可以通过上面的“cerr”在“Application Output”输出结果来查看结果。当在手机运行时,我们也可以通过查看如下的文件来看Scope的运行情况:
我们可以通过查看在手机中的文件“~/.cache/upstart/scope-registry.log”来看最新的Scope的运行情况。

使用Ubuntu SDK创建中国天气Scope应用(C++)相关推荐

  1. yocto编译linux,好实用!用 Yocto 在 Ubuntu 上创建最小化 Linux 发行版

    导读 本文主要聚焦在如何使用 Yocto 在 Ubuntu 上创建一个最小化的 Linux 发行版.Yocto 项目在嵌入式 Linux 的世界非常著名,这是因为它用起来非常灵活.方便.Yocto 的 ...

  2. Ubuntu SDK 安装

    在这篇文章里,你将学到如何安装Ubuntu SDK到你的系统中,并生成一个简单的应用以测试你的安装是否成功.对英文好的学习者,可以参考Ubuntu 网站中的英文地址来进行安装.如果开发者想对Ubunt ...

  3. 抓取中国天气网当前时段所有城市的天气数据(python+xpath)

    先给大家看一看效果图(我一共获取到了462个城市的天气): 前不久,2019年开放数据中心峰会在北京国际会议中心成功召开,ODCC指出:"对数据进行汇聚,在体系化融合中产生新的价值已成为未来 ...

  4. Java爬取中国天气网实况天气数据

    因实验室需求,需要找一个实况天气API. 百度云.阿里云.腾讯云上边我都去找了,很多平台要么没有,要么要收费(免费的可调用次数太少了).而我在高德开放平台上找到了一个,但是不符合要求,被老师pass掉 ...

  5. 使用Python爬取中国天气网天气数据

    使用Python获取中国天气网中"广州"天气数据 注意:原文章写于2016年12月 广州天气页面:http://www.weather.com.cn/weather/1012801 ...

  6. Qt5获取并解析中国天气网数据

    天气查询 API 接口 中国天气网提供 3 个 API 接口,以北京为例: http://m.weather.com.cn/data/101010100.html http://weather.com ...

  7. Scrapy实例:爬取中国天气网天气数据

    1.创建项目 在你存放项目的目录下,按shift+鼠标右键打开命令行,输入命令创建项目: PS F:\ScrapyProject> scrapy startproject weather # w ...

  8. 【Jmeter】jmeter利用csv测试实例——中国天气网,查询几个城市的天气

    记录第一个成功的测试实例,文章有些长,尽力记录的详细,欢迎交流. 问题背景 2个并发 参数化数据为你要查询的地区,提示至少使用csv data 组件.并能够说明组件中的sharing mode含义和实 ...

  9. Android解析中国天气网的Json数据

    在Android开发中.一般的APP都是通过获取server端的数据来更新UI.从server获取到的数据能够是Json.它的数据量要比XML要小,这里解析中国天气网上获取的数据,尽管已经不再更新了. ...

最新文章

  1. python实时处理_python实时处理log文件脚本
  2. 第十六章 推荐系统-机器学习老师板书-斯坦福吴恩达教授
  3. All your files have been encrypted
  4. mysql怎样修改my ini_mysql修改my.ini报错怎么办
  5. C#LeetCode刷题之#55-跳跃游戏(Jump Game)
  6. php sql 条件拼组_sql where查询拼接技巧
  7. 如何安装中文manpage
  8. echarts3.0 本期累计堆叠
  9. LaTex软件安装方式
  10. APP - K歌之王请进!全民K歌可一键分享到微信状态
  11. 我想学习编程, 但不知道从哪里开始
  12. 计算机学院举办 温暖冬日 感恩社会 活动,温暖冬日 感恩社会 计算机学院举办冬季送温暖活动...
  13. MyEclipse链接SQLSERVER数据库时18456的问题
  14. 单条视频播放超7000万,网红界“大油田”如何掀起快手流量浪潮?
  15. 动态规划 - 切钢条 (python)
  16. linux英伟达显卡内核不匹配,Linux 5.11 内核将添加对英伟达 RTX 30 系列显卡的支持...
  17. 生成网络论文阅读:DDPM(一):Denoising Diffusion Probabilistic Models论文概述
  18. 《ODAY安全:软件漏洞分析技术》学习心得
  19. 基于人脸识别的课堂签到管理系统2020,7,19
  20. 男人30岁前要完成的事

热门文章

  1. 基于HttpClient的正方教务系统模拟登录(带验证码)
  2. 产品经理考个 PMP 有用吗?
  3. React语法开发微信小程序
  4. mac office
  5. 三相桥式全控整流电路原理及电路图,三相桥式全控整流电路原理及电路图
  6. java (iText) 工具包生成 PDF文档
  7. #TP4056#--3.7V锂电池充放电电路(实践日志篇)
  8. Python著名的lib和开发框架(均为转载)
  9. Icon 图标--各种方向性图标(方向性图标---提示建议性图标---编辑类图标----数据类图标---品牌和标识----网站通用图标)
  10. 在Chrome中实现百度网盘在线倍速播放