Incomplete Type is not Allowed QApplication - c++

I am learning C++ with Qt. I have installed Qt 5.15 and am using VS2019. I have the below code (as per an example in a textbook I am working through):
#include <QtGui>
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
QTextStream cout(stdout);
//declarations of variables
int answer = 0;
do{
//local variables
int factArg = 0;
int fact(1);
factArg = QInputDialog::getInt(0, "Factorial Calculator", "Factorial of:", 1);
cout << "User entered: " << factArg << endl;
int i = 2;
while (i <= factArg) {
fact = fact * i;
++i;
}
QString response = QString("The factorial of %1 is %2.\n%3").arg(factArg).arg(fact).arg("Do you want to compute another factorial?");
answer = QMessageBox::question(0, "Play again?", response, QMessageBox::Yes | QMessageBox::No);
} while (answer == QMessageBox::Yes);
return EXIT_SUCCESS;
}
However, I am recieving the below error when creating an instance of QApplication as app:
Incomplete Type is not Allowed
I am also recieving the below error for the QInputDialog and QMessageBox classes:
name followed by '::' must be a class or namespace name
I am not sure why this is happening - presumably something with a namespace, but I am not sure what scope to provide. I have searched the web but to no avail.
UPDATE
Adding the below header references give cannot open source file error for each.
#include <QApplication>
#include <QInputDialog>
#include <QMessageBox>
I have also added suggestions from the comments to my code, now below:
#include <QtGui>
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
QTextStream cout(stdout);
//declarations of variables
int answer = 0;
do{
//local variables
int factArg = 0;
int fact(1);
factArg = QInputDialog::getInt(0, "Factorial Calculator", "Factorial of:", 1);
cout << "User entered: " << factArg << endl;
int i = 2;
while (i <= factArg) {
fact = fact * i;
++i;
}
QString response = QString("The factorial of %1 is %2.\n%3").arg(factArg).arg(fact).arg("Do you want to compute another factorial?");
answer = QMessageBox::question(0, "Play again?", response, QMessageBox::Yes | QMessageBox::No);
} while (answer == QMessageBox::Yes);
return EXIT_SUCCESS;
}
But I am still recieving the same errors.

You have to include some qt headers in the app... that is the meaning of the message
you just need to add this to your code
#include <QApplication>
#include <QInputDialog>
#include <QMessageBox>

The correct headers to include are the following:
#include <QtWidgets/QApplication>
#include <QtWidgets/QInputDialog>
#include <QtWidgets/QMessageBox>
Once declaring these, the compiler accepts the code.

I'm going to cut and paste a working program for you.
Qt seems to have a bunch of forward definitions. I can tell I'm missing the right include file if I try to get the IDE to actually help me select a method call. In short, you pretty much have to #include every widget type or other class you're going to use. I haven't run into any shortcuts.
#include <QApplication>
#include "MainWindow.h"
using namespace std;
/**
* Main entry point.
*/
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow mainWindow;
mainWindow.show();
return app.exec();
}

Related

How to get global mouse position in Qt6?

I'm trying to get global position of the mouse however the functions mentioned in older topics are either deprecated or not working as intended. I have tried QCursor::pos() as seen below but it didn't work as intended.
#include <QtCore/QCoreApplication>
#include <QCursor>
#include <iostream>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
while(1)
{
std::cout << QCursor::pos().x() << " " << QCursor::pos().y() << std::endl;
}
return a.exec();
}
Output: 2147483647 2147483647
It is very simple. QCursor is in the Gui module of Qt see here, so you have to change QCoreApplication to QGuiApplication and then it works (already tested it).

Qt on Mac: app.exec() blocks terminal input, how to rewrite this minimal example?

I have been reading a lot about this, but I don't fully get how to go about it (e.g. see How to avoid Qt app.exec() blocking main thread).
The following code is a very naievely written minimal example of what I'm trying to achieve. For the sake of this example: there is a terminal in which you put exam grades for the same subject for one student. Concretely: how a student did for his/her English course over the whole year. Every time you put in the grade of a student, a Qt chart updates and shows the progression.
This is the code I wrote:
#include <iostream>
#include <vector>
#include <QApplication>
#include <QMainWindow>
#include <QChartView>
#include <QLineSeries>
int main(int argc, char **argv)
{
QApplication app(argc, argv);
std::vector<int> examScores;
int totalExams = 5;
QtCharts::QLineSeries *series = new QtCharts::QLineSeries();
QtCharts::QChart *chart = new QtCharts::QChart();
chart->legend()->hide();
chart->createDefaultAxes();
QtCharts::QChartView *chartView = new QtCharts::QChartView(chart);
chartView->setRenderHint(QPainter::Antialiasing);
QMainWindow window;
window.setCentralWidget(chartView);
window.resize(400, 300);
for (int i = 1; i <= totalExams; i++)
{
std::cout << "Enter score of exam " << i << " ";
std::string userInput;
getline(std::cin, userInput);
int score = std::stoi(userInput);
examScores.push_back(score);
series->append(i, score);
chart->addSeries(series);
window.show();
app.exec();
chart->removeSeries(series);
}
return 0;
}
Now, there are many issues here from a software engineering perspective (e.g. not sanitizing input, and so on), but what I can't wrap my head around is how to rewrite app.exec();. I know it shouldn't be there, since it's blocking, and I know Qt isn't meant to be written this way.
So I'm wondering: how would you rewrite this example in order to make app.exec(); non-blocking and allow the program to receive user input on the terminal at all times?
This is how I put it into its own thread while still being able to handle CLI input. A lot of things are still wrong with this code from a code review perspective, but the basic functionality (putting it into a different thread) works.
#include <iostream>
#include <vector>
#include <thread>
#include <QApplication>
#include <QMainWindow>
#include <QChartView>
#include <QLineSeries>
std::vector<int> examScores;
void pollForUserInput(QtCharts::QLineSeries *series, int totalExams)
{
for (int i = 1; i <= totalExams; i++)
{
std::cout << "\nEnter score of exam " << i << " " << std::endl;
std::string userInput;
getline(std::cin, userInput);
int score = std::stoi(userInput);
examScores.push_back(score);
series->append(i, score);
}
std::cout << "done" << std::endl;
}
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QtCharts::QLineSeries *series = new QtCharts::QLineSeries();
int totalExams = 5;
std::thread t1(pollForUserInput, series, totalExams);
QtCharts::QChart *chart = new QtCharts::QChart();
chart->legend()->hide();
chart->addSeries(series);
chart->createDefaultAxes();
chart->axisX()->setRange(1, totalExams); // see https://stackoverflow.com/questions/38804179/how-to-repaint-a-qchart
chart->axisY()->setRange(1, 10); // see https://stackoverflow.com/questions/38804179/how-to-repaint-a-qchart
QtCharts::QChartView *chartView = new QtCharts::QChartView(chart);
chartView->setRenderHint(QPainter::Antialiasing);
QMainWindow window;
window.setCentralWidget(chartView);
window.resize(400, 300);
window.show();
return app.exec();
}

Display the value of an entry

i am using the library Gtkmm with c++ but i have a problem to display the value of an entry. This is my code :
#include <gtkmm/box.h>
#include <gtkmm/button.h>
#include <gtkmm/main.h>
#include <gtkmm/window.h>
#include <gtkmm/entry.h>
#include <iostream>
int main(int argc, char* argv[]) {
Gtk::Main app(argc, argv);
Gtk::Window fenetre;
Gtk::VBox *boiteV = Gtk::manage(new Gtk::VBox(false, 10));
Gtk::Entry *param = Gtk::manage(new Gtk::Entry());
boiteV->pack_start(*param);
Gtk::Button *bouton = Gtk::manage(new Gtk::Button("Tester !"));
boiteV->pack_start(*bouton);
fenetre.add(*boiteV);
std::string a = param->get_text();
bouton->signal_clicked().connect([&a]() {std::cout << a << std::endl;});
fenetre.show_all();
Gtk::Main::run(fenetre);
return EXIT_SUCCESS;
}
My problem is when i click on the button i have nothing whereas i wrote a value in the entry. Thank you a lot for your help !
The problem is that you take the string a after creation of the button and capture that string (which is empty) in the lambda function. When you press the button, the text is not queried again, but the value of the string a, which never changed, is printed.
You can instead capture the pointer to the button itself (by value!) and call get_text() every time like this:
bouton->signal_clicked().connect(
[param]() {
std::cout << param->get_text() << std::endl;
}
);

Qt freeing memory

I wrote a C++ program in Qt that used dynamic memory allocation, and I made sure to include the free() call at the end. However, when the program reaches the free statement, it crashes. (I know this because the test that I added never printed after the free statements) Anyway, here's the code:
#include <QCoreApplication>
#include <QSerialPort>
#include <iostream>
#include <time.h>
#include <stdlib.h>
#include <Windows.h>
using namespace std;
int main(int argc, char *argv[])
{
QSerialPort serial0;
//serial.open(serial);
serial0.setBaudRate(QSerialPort::Baud9600);
serial0.setDataBits(QSerialPort::Data8);
serial0.setParity(QSerialPort::NoParity);
serial0.setStopBits(QSerialPort::OneStop);
serial0.setFlowControl(QSerialPort::NoFlowControl);
char *com="com";
int number;
char *comPlusNumber;
comPlusNumber=(char*) malloc(8*sizeof(char));
int j=10000;
while(j>0)
{
number=j;
sprintf(comPlusNumber, "%s%d",com,number);
//printf("%s \n",comPlusNumber);
serial0.setPortName(comPlusNumber);
serial0.open(QIODevice::ReadWrite);
if(serial0.isOpen()==true)
{
printf("YES*****************");
printf("%s \n",comPlusNumber);
}
else
//printf("No %d\n", number);
serial0.close();
j--;
}
free(com);
free(comPlusNumber);
printf("\n\n Test");
//QCoreApplication a(argc, argv);
//return a.exec();
}
I just wanted to make sure that I wasn't creating a memory leak.
Use the framework. You've got the power of Qt!
There are several problems:
The C-style string manipulations are unnecessary and wrong. Use QString:
auto name = QStringLiteral("COM%1").arg(i);
You can't use the serial port without a QCoreApplication instance present.
You shouldn't be testing for the presence of a port by iterating what you think might be valid ports. This is non-portable and unnecessary. Get a list of ports to start with.
Thus:
// https://github.com/KubaO/stackoverflown/tree/master/questions/simple-serial-35181906
#include <QtCore>
#include <QtSerialPort>
int main(int argc, char ** argv) {
QCoreApplication app{argc, argv};
QSerialPort serial;
serial.setBaudRate(QSerialPort::Baud9600);
serial.setDataBits(QSerialPort::Data8);
serial.setParity(QSerialPort::NoParity);
serial.setStopBits(QSerialPort::OneStop);
serial.setFlowControl(QSerialPort::NoFlowControl);
for (auto port : QSerialPortInfo::availablePorts()) {
serial.setPort(port);
serial.open(QIODevice::ReadWrite);
if (serial.isOpen()) {
qDebug() << "port" << port.portName() << "is open";
serial.close();
} else
qDebug() << "port" << port.portName() << "couldn't be opened";
}
}
Here's the output on my machine:
port "cu.serial1" is open
port "cu.usbserial-FTELA9I5" is open
port "cu.usbserial-PX9A3C3B" is open
You can only free what you dynamically allocated. You never dynamically allocated anything for com, so passing it to free is an error. It's equivalent to free("com"); which attempts to free a string constant.

QApplication changing value of std::to_string

It seems that Qt changes the 'interpretation' of the returned string of std::to_string(double).
Example:
#include <iostream>
#include <QApplication>
#define VERSION 1.0
#define VSIZE 3
int main(int argc, char** argv) {
std::string version = std::to_string(VERSION).substr(0, VSIZE);
std::cout << version << std::endl; // everything fine
QApplication app(argc, argv);
std::cout << std::to_string(VERSION).substr(0, VSIZE); // no good
return 0;
}
The output is:
1.0
1,0
I think it's Qt because this is the thinnest example where this happens, and removing the QApplication declaration makes it work again. How can I fix this?