qt creator - MainWindow from code from the main.cpp in Qt -
want understand difference in code between mainwindow
, main.cpp
. specifically, how chunk of code written exclusively in main.cpp
needs modified part of mainwindow.cpp
, mainwindow.h
.
as example, trying modify code fine answer work in mainwindow
.
main.cpp
#include <qtwidgets> #include <qtnetwork> int main(int argc, char *argv[]) { qapplication a(argc, argv); //setup gui (you doing in designer) qwidget widget; qformlayout layout(&widget); qlineedit lineeditname; qlineedit lineeditgender; qlineedit lineeditregion; auto edits = {&lineeditname, &lineeditgender, &lineeditregion}; for(auto edit : edits) edit->setreadonly(true); layout.addrow("name:", &lineeditname); layout.addrow("gender:", &lineeditgender); layout.addrow("region:", &lineeditregion); qpushbutton button("get name"); layout.addrow(&button); //send request uinames api qnetworkaccessmanager networkmanager; qobject::connect(&networkmanager, &qnetworkaccessmanager::finished, [&](qnetworkreply* reply){ //this lambda called when reply received //it can slot in gui window class //check errors if(reply->error() != qnetworkreply::noerror){ for(auto edit : edits) edit->settext("error"); networkmanager.clearaccesscache(); } else { //parse reply json , display result in ui qjsonobject jsonobject= qjsondocument::fromjson(reply->readall()).object(); qstring fullname= jsonobject["name"].tostring(); fullname.append(" "); fullname.append(jsonobject["surname"].tostring()); lineeditname.settext(fullname); lineeditgender.settext(jsonobject["gender"].tostring()); lineeditregion.settext(jsonobject["region"].tostring()); } button.setenabled(true); reply->deletelater(); }); //url parameters qurlquery query; query.addqueryitem("amount", "1"); query.addqueryitem("region", "united states"); qurl url("http://uinames.com/api/"); url.setquery(query); qnetworkrequest networkrequest(url); //send request when button clicked qobject::connect(&button, &qpushbutton::clicked, [&](){ networkmanager.get(networkrequest); button.setenabled(false); for(auto edit : edits) edit->settext("loading. . ."); }); widget.show(); return a.exec(); }
edit
added timer part of same answer; please demonstrate how version timer can done well
qtimer timer; qobject::connect(&timer, &qtimer::timeout, [&](){ networkmanager.get(networkrequest); button.setenabled(false); for(auto edit : edits) edit->settext("loading. . ."); }); timer.start(60000); //60000 msecs = 60 secs
i struggle modifying networkmanager
class members, how structure code , how replace lambda functions.
if can provide required modifications me gain better understanding great.
you want separate out user interface , controller (business logic) separate classes.
the body of main()
instantiates ui , controller , connects them. timer fetches new results every 5 seconds. timer rolled controller
, - show separated out example of adding functionality existing class without modifying it.
main.cpp
// https://github.com/kubao/stackoverflown/tree/master/questions/into-mainwin-39643510 #include "mainwindow.h" #include "controller.h" int main(int argc, char *argv[]) { qapplication app{argc, argv}; mainwindow ui; controller ctl; qtimer timer; timer.start(5*1000); qobject::connect(&timer, &qtimer::timeout, &ctl, &controller::get); qobject::connect(&ctl, &controller::busy, &ui, [&]{ ui.setstate(mainwindow::loading); }); qobject::connect(&ui, &mainwindow::request, &ctl, &controller::get); qobject::connect(&ctl, &controller::error, &ui, [&]{ ui.setstate(mainwindow::error); }); qobject::connect(&ctl, &controller::values, &ui, &mainwindow::setfields); ui.show(); return app.exec(); }
the controller knows nothing of user interface, , deals processing requests only. emits busy
signal every time request starts being processed.
if wanted provide better feedback multiple active requests, busy
signal need emitted when there no requests pending , new 1 added, , idle
signal emitted when last request has finished , there no more pending ones.
controller.h
#ifndef controller_h #define controller_h #include <qtnetwork> class controller : public qobject { q_object qnetworkaccessmanager manager{this}; qnetworkrequest request; q_slot void onreply(qnetworkreply *); public: explicit controller(qobject * parent = nullptr); q_slot void get(); q_signal void busy(); q_signal void error(const qstring &); q_signal void values(const qstring & name, const qstring & gender, const qstring & region); }; #endif // controller_h
controller.cpp
#include "controller.h" controller::controller(qobject *parent) : qobject(parent) { qurlquery query; query.addqueryitem("amount", "1"); query.addqueryitem("region", "united states"); qurl url("http://uinames.com/api/"); url.setquery(query); request = qnetworkrequest(url); connect(&manager, &qnetworkaccessmanager::finished, this, &controller::onreply); } void controller::onreply(qnetworkreply * reply) { if (reply->error() != qnetworkreply::noerror) { emit error(reply->errorstring()); manager.clearaccesscache(); } else { //parse reply json , display result in ui auto jsonobject = qjsondocument::fromjson(reply->readall()).object(); auto fullname = jsonobject["name"].tostring(); fullname.append(" "); fullname.append(jsonobject["surname"].tostring()); emit values(fullname, jsonobject["gender"].tostring(), jsonobject["region"].tostring()); } reply->deletelater(); } void controller::get() { emit busy(); manager.get(request); }
the user interface knows nothing of business logic, provides api that's sufficient business logic use it. can in 1 of 3 states: normal
state results visible, loading
state busy feedback shown, , error
state error information shown. setfields
slot returns state normal
.
mainwindow.h
#ifndef mainwindow_h #define mainwindow_h #include <qtwidgets> class mainwindow : public qwidget { q_object qformlayout layout{this}; qlineedit lineeditname; qlineedit lineeditgender; qlineedit lineeditregion; qpushbutton button{"get name"}; qlineedit * edits[3] = {&lineeditname, &lineeditgender, &lineeditregion}; public: enum state { normal, loading, error }; explicit mainwindow(qwidget * parent = nullptr); q_slot void setfields(const qstring & name, const qstring & gender, const qstring & region); q_slot void setstate(state); q_signal void request(); }; #endif // mainwindow_h
mainwindow.cpp
#include "mainwindow.h" mainwindow::mainwindow(qwidget *parent) : qwidget(parent) { for(auto edit : edits) edit->setreadonly(true); layout.addrow("name:", &lineeditname); layout.addrow("gender:", &lineeditgender); layout.addrow("region:", &lineeditregion); layout.addrow(&button); connect(&button, &qpushbutton::clicked, this, &mainwindow::request); } void mainwindow::setfields(const qstring & name, const qstring & gender, const qstring & region) { setstate(normal); lineeditname.settext(name); lineeditgender.settext(gender); lineeditregion.settext(region); } void mainwindow::setstate(mainwindow::state state) { if (state == normal) { (auto edit : edits) edit->setenabled(true); button.setenabled(true); } else if (state == loading) { (auto edit : edits) edit->setenabled(false); button.setenabled(false); } else if (state == error) { (auto edit : edits) edit->settext("error..."); button.setenabled(true); } }
Comments
Post a Comment