I have two separate c++ projects that run simultaneously and exchange information between them using TCP/IP.
The names of those two projects are "World" and "Platform". To display Data and output in Real time, I have created a Qapplication object inside "World" class.
(I do not want to use Qt forms to create QGprahics view I just want to code it). TCP/IP works without any problems.
here is my code:
main.cpp:
#include "QTcpServer"
#include "QTcpSocket"
#include "QApplication"
#include "QGraphicsScene"
#include "QTime"
World::World()
{
WorldSettings settings;
Sys = new Dynamics(settings);
}
void World::run()
{
while (!time->finished())
{
if (controlStatus)
{
sendWorldData();
getPlatformData();
}
displayData();
}
int World::displayData()
{ char *argv[] = {"a", "arg1", "arg2", NULL};
int argc = sizeof(argv) / sizeof(char*) - 1;
QApplication a(argc, argv);
QGraphicsScene * scene = new QGraphicsScene();
// create an item to put into the scene
QGraphicsRectItem * sag = new QGraphicsRectItem();
sag->setRect(0,0,10,15);
view->show();
return a.exec();
}
with run this file, in first step time, the widget viwe is display and then the program stops running.(In other words, the program stops in the first iteration).
I expect the code I'm writing to behave like this:First, the widget is displayed and then the data are displayed in the corresponding graphic items, number displays, etc. and in every iteration of the code, these display objects are updated. In other words, I have a real time program that I need to display it's output data in real time.
Related
i am making a Tail Log application. It is executing perfectly but the output window is not showing any results.
Below is the code:
LogTail.cpp
#include "logtail.h"
#include <QApplication>
#include <QTextEdit>
#include<QDebug>
//start id=constructor
LogTail::LogTail(QString fn) {
//if (fn == QString()) {
// fn = "C:/Users/arpit.k/OneDrive - Accord Software & Systems Pvt. Ltd/Documents/QT/LogTail3/sample.log";
// }
connect (this, SIGNAL(readyReadStandardOutput()),
this, SLOT(logOutput())); /* When there is input ready, call this slot.*/
QStringList argv;
argv << "-f" << fn; /* tail -f filename */
start("tail", argv); /* Returns immediately, and now there is a child process running, "attached"
to this process. When this process exits, the child tail process will also terminate. */
}
LogTail::~LogTail() {
terminate(); /* Attempts to terminate this process. */
}
//end
//start id=logOutput
// tail sends its output to stdout.
void LogTail::logOutput() { /* Slot called whenever there is input to read. */
QByteArray bytes = readAllStandardOutput();
QStringList lines = QString(bytes).split("\n");
foreach (QString line, lines) {
//qDebug() << line;
emit logString(line);
}
}
//end
main.cpp
#include "logtail.h"
#include <QTextEdit>
#include <QApplication>
int main (int argc, char* argv[]) {
QApplication app(argc, argv);
QStringList al = app.arguments();
QTextEdit textEdit;
textEdit.setWindowTitle("Debug");
textEdit.setWindowTitle("logtail demo");
QString filename = "sample.log";
if (al.size() > 1) filename = al[1];
LogTail tail(filename); /* Create object, starts process too. */
tail.connect (&tail, SIGNAL(logString(const QString&)),
&textEdit, SLOT(append(const QString&)));
textEdit.show();
return app.exec();
}
Note: sample.log file contains some log data
Output window doesn't show any logs:
(https://i.stack.imgur.com/ENhqs.png)
I need it to display recent 10 Log lines!
Assuming you are subclassing from QProcess (you should post a complete minimal example in order to get an accurate answer).
You are starting the process in the constructor of LogTail, 'tail' will probably output some data or some events that will trigger readyReadStandardOutput before you have the chance to connect the signal in the main function.
readyReadStandardOutput will be triggered only once as you never cleared the input buffer (you never had the chance to read the available data).
So in order to make your example work you should call logOutput after you start the process.
Anyway I will suggest you to implement differently, I would call start from outside or at least outside the constructor, that way your object will be more scalable.
My class names is like (what it does)_(type) for example: reg_QDialog
Here is code of an executing dlg and if Accepted creating QMainWindow:
if(log_dlg->exec() == QDialog::Accepted)
{
find_wnd = new find_QMainWindow();
find_wnd->show();
}
log_dlg has 2 btns: "Enter" (here is the accept result) and "Reg" (opens a new dlg)
"Enter" and "Reg" code is here:
void log_QDialog::on_btn_enter_clicked()
{
this->accept();
}
void log_QDialog::on_btn_reg_clicked()
{
reg_QDialog *reg_dlg = new reg_QDialog();
this->hide();
if(reg_wnd->exec() == QDialog::Accepted)
{
//code
}
this->show();
}
So, here is the problem:
Step by step:
1) run the prog //it starts with dlg_log
2) "Reg" //creating dlg_reg
3) accept dlg_reg //returning to dlg_log
4) "Enter" //trying to create QMainWindow
QMainWindow is not created, and the app just closed
After "returning"(it's, actually, just hiding and then showing) from the reg_dlg and pushing btn with accept result it does nothing! It just closes the programm, but it had to show QMainWindow!
All real code of main.cpp:
#include "log_window_root.h"
#include "find_mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
log_window_root * log_wnd;
find_mainwindow * find_wnd;
log_wnd = new log_window_root();
log_wnd->setWindowFlags(Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint);
log_wnd->setModal(true);
if(log_wnd->exec() == QDialog::Accepted)
{
find_wnd = new find_mainwindow();
find_wnd->setWindowFlags(Qt::MSWindowsFixedSizeDialogHint);
find_wnd->show();
}
return a.exec();
}
You are a operating a bit beyond the limits of Qt. Looking at the documentation:
Generally, no user interaction can take place before calling exec().
As a special case, modal widgets like QMessageBox can be used before
calling exec(), because modal widgets call exec() to start a local
event loop.
Testing your code on Mac OS will give you the dreaded warning
modalSession has been exited prematurely - check for a reentrant call
to endModalSession
which shows, that you are working on thin ice and your code will break any time.
Consider reworking your code so that the MainWindow comes up and then show your dialogs. If you want to go on with the Dialog sequence, then remove the hide()/show() pair from on_btn_reg_clicked (these calls mess up your event loops).
QApplication exits and close when the last window has been closed.
You can discard this by setting QApplication::quitOnLastWindowClosed property to false.
QApplication a(argc, argv);
a.setQuitOnLastWindowClosed(false);
You may want to revert it to it's previous state when your job is done with those dialogs.
As #Jens mentioned in the other answer to your question, this is will break evenloop at some point and QApplication exits before even a.exec() being called. So, you can also create a zero width/height or off-screen QWidget as a parent of your dialogs. A QSplashScreen is also a good candidate for this. All your dialogs should be your splash screen children. At last, you can finish your splash screen by calling QSplashScreen::finish.
[Re-posting from duplicate-closed question since the top banner on it may cause people to skip that question entirely, and IMHO this one doesn't have a good answer.]
Here's a very simple example of showing a dialog before a QMainWindow. The dialog simply presents the option of starting the main app or not. They key points are that the QDialog portion happens before any other widgets are created (eg. QMainWindow here), and the app (main()) exits before that if needed. No reason to keep the QDialog around after it is used, so I create it on the stack and delete afterwards.
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QDialog *d = new QDialog();
QPushButton *pbYes = new QPushButton("Would you like to play a game?", d);
QPushButton *pbNo = new QPushButton("Get me out of here!", d);
QObject::connect(pbYes, &QPushButton::clicked, [d]() { d->done(QDialog::Accepted); });
QObject::connect(pbNo, &QPushButton::clicked, [d]() { d->done(QDialog::Rejected); });
d->setLayout(new QVBoxLayout);
d->layout()->addWidget(pbYes);
d->layout()->addWidget(pbNo);
const int ret = d->exec();
delete d;
if (ret == QDialog::Rejected)
return 0;
QMainWindow mw;
mw.setCentralWidget(new QLabel("Welcome to the Game!", &mw));
mw.show();
return a.exec();
}
I'm writing a QT application that includes QTextBrowser.
When the app doing some functions the function prints lines in the QTextBrowser and during write the lines if i press the mouse left button on any printed line on the QTextBrowser the app restart printing the lines from that line i pressed on.
how to prevent that ?
Example:
all function output:
Device user: xvalid 1
Device model: alpha 16
Device name: Samsoni
Working stage: level 16
during the lines printing if i press on second line with left mouse button this will happen:
Device user: xvalid 1
Device model: alpha 16 Device name: Samsoni
Working stage: level 16
as you see the app will re-set the start writing point from where i pressed
The docs indicates that when you use insertHtml() it is similar to:
edit->textCursor().insertHtml(fragment);
That is, the HTML is added where the cursor is and when you press with the mouse the cursor moves to the position where you click.
The solution is to move the cursor to the end:
QTextCursor cursor = your_QTextBrowser->textCursor(); // get current cursor
cursor.movePosition(QTextCursor::End); // move it to the end of the document
cursor.insertHtml(text); // insert HTML
Example:
#include <QApplication>
#include <QTextBrowser>
#include <QTimer>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTextBrowser w;
int counter = 0;
QTimer timer;
QObject::connect(&timer, &QTimer::timeout, [&w, &counter](){
QString text = QString::number(counter);
// at html
QTextCursor cursor = w.textCursor();
cursor.movePosition(QTextCursor::End);
cursor.insertHtml(text);
counter++;
});
timer.start(1000);
w.show();
return a.exec();
}
I'm making an application for Mac OS X in Qt, and wanted to spawn a thread that doesn't close on application close.
Is this possible? If so, how? I don't want the process to be stopped if a user force quits the application.
Thanks in advance.
Note: If this is not possible, is there any way I can make this happen? (Maybe with calling a command in bash?)
it's possible to achieve your goal by initiating a new process via QProcess::startDetached, as per documents http://doc.qt.io/qt-4.8/qprocess.html#startDetached
Starts the program program with the arguments arguments in a new process, and detaches from it. Returns true on success; otherwise returns false. If the calling process exits, the detached process will continue to live.
Unix: The started process will run in its own session and act like a daemon.
Edit:
Here is an example for MacOS
// run start script
QString scriptPath = "path-to-start-script/start.sh" ;
QString cmd = "open -a " + scriptPath;
QProcess::startDetached(cmd);
When you terminate a process, all threads within that process die - the process is the thread "container". If you want to spawn something that lives on beyond your current process, then spawn a new independant process.
If your user force-quits the application, that usually means that they want to control the energy or resource expenditure on their system. Thinking that you know better than the user would be rather in the user's face. Don't anger your users :)
All you really want is:
For the process to survive quitting it through normal means (pressing ⌘-Q, selecting Quit from the menu, closing the last window, etc.).
For the dock icon to disappear after the GUI has been quit, as is the normal and expected behavior.
For a cleanup code to run after the GUI has vanished.
To that effect, you only need to hide the dock icon/menubar and then perform the cleanup:
main.mm
// https://github.com/KubaO/stackoverflown/tree/master/questions/hidedock-39378276
#include <QtWidgets>
#include <AppKit/AppKit.h>
void hideDockIcon() {
[NSApp setActivationPolicy: NSApplicationActivationPolicyProhibited];
}
int main(int argc, char ** argv) {
QApplication app{argc, argv};
QLabel label{"Quit Me"};
label.setMinimumSize(200, 100);
label.show();
int rc = app.exec();
hideDockIcon();
qDebug() << "cleaning up";
QThread::sleep(5);
qDebug() << "cleanup finished";
return rc;
}
hidedock-39378276.pro
QT = widgets
CONFIG += c++11
TARGET = hidedock-39378276
TEMPLATE = app
OBJECTIVE_SOURCES += main.mm
LIBS += -framework AppKit
If u mean closing of Gui window by "Application Close" then it can be done easily...
#include "MainWindow.h"
#include <QApplication>
//////////////////////////////////////
#include <thread>
struct blabla {
std::thread th;
blabla():th([]{
// body of your thread
}) {}
~blabla(){
if(th.joinable())
th.join();
}
} singleton_obj;
/////////////////////////////////////
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
Now the applicaton window will quit but the daemon thread will run n background...
Enjoy
My program has two modes GUI(on qml) and no GUI(command line).What code I must write for changing mode by passing argument in cmd
for example if I pass nameofapp.exe -no-gui must be work no-gui version
for simple qt/c++ application we have this code
QCoreApplication* createApplication(int &argc, char *argv[])
{
for (int i = 1; i < argc; ++i)
if (!qstrcmp(argv[i], "-no-gui"))
return new QCoreApplication(argc, argv);
return new QApplication(argc, argv);
}
int main(int argc, char* argv[])
{
QScopedPointer<QCoreApplication> app(createApplication(argc, argv));
if (qobject_cast<QApplication *>(app.data())) {
// start GUI version...
} else {
// start non-GUI version...
}
return app->exec();
}
It's from documentation,I want such of this for qml
OS is windows 7 ultimate but I don't think that it's depends on OS
You need at least one top level QObject per application type which will "make things happen" in the main event loop.
Assuming that you have made a clear separation of concern between the view and the backend (eg MVC), you will have 3 classes (which are QObject) :
MyAppBackend which does the actual work
MyGUIMainWindow which manage GUI input\outpout.
MyCLIMainObject which manage command line input\outpout
Each one should have a method to start doing work. For instance just showing a widget is how simple Qt apps start.
int main()
{
QApplication app;
MyGUIMainWindow window;
window.show();
return app.exec();
}
window.show() will queue an event which will be processed when app.exec(). is executed.
You need to do the same with a function which either post an event or emit a signal.
int main(int argc, char* argv[])
{
QScopedPointer<QCoreApplication> app(createApplication(argc, argv));
MyAppBackend backend;
backend.startDeffered();
if (qobject_cast<QApplication *>(app.data())) {
// start GUI version...
MyGUIMainWindow* window = new MyGUIMainWindow(0,...);
window->show();
} else {
// start non-GUI version...
MyCLIMainObject* cliobj = new MyCLIMainObject(0,...);
cliobj->showCLi();
}
return app->exec();
}