Just a Qt Gui Application with QDialog as the Base Class, the simplest type you can expect.
I've programmed on Qt for several times but this is the first time I meet this problem...
I've added minimal code to the program, and here's the code in dialog.h (which is mostly automatically generated)
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QPixmap>
#include "bmp.h"
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
private slots:
void on_openButton_clicked();
private:
Ui::Dialog *ui;
BMP srcImage;
QImage compressedImage[3];
};
#endif // DIALOG_H
While I edit, the "public:" is underlined and says "unexpected token '('". When I try to build the program, it says in the line "Q_OBJECT", "error: expected ',' or '...' before numeric constant". I'm sure I've defined nothing related to it (to be exact, I defined an N and an n in file bmp.h, both are int).
Any idea of what's wrong here?
I think I've figured it out myself.
I included some
#pragma pack(push)
#pragma pack(1)
//...
#pragma pack(pop)
in file "bmp.h". When I move the line
#include "bmp.h"
into file "dialog.cpp", everything works well
Related
I need some help understanding how to access the QT GUI ui from another class/another cpp file.
Background: I am working on a project that consists of many cpp and hpp files. I am not the original author. This project is to control a USRP to receive/send data....with various parameters. Originally, you had to manually change parameter values inside several cpp files (i..e start frequency, steps, duration of receive, etc). Then re-compile and then run the executable. I wrote a simple Qt GUI interface in the main.cpp function where the users would enter in the GUI basic usrp receive parameters. Then the GUI interface would pass these values back into the uspr function that would actually execute the USRP functionality. This part is actually working great and I am happy (my first GUI!, Yay!)
One thing that I would like to do is to also display the current frequency in the main GUI window via the LCDNumber widget. This frequency is managed by another class, in another cpp file.
Here is what I tried:
Attempt #1: Make the MainWindow ui publicly available int the class/cpp file where the Frequency is established:
freq_transmit.cpp:
......
#include "mainwindow.hpp"
#include "ui_mainwindow.hpp"
.....
void Receiver::run()
{
//bunch of lines of code about USRP stuff
.....
rxCenterFreq // <---variable that holds the current frequency (which changes every second)
ui->lcdnumber->display(rxCenterFreq); // <-- -compiler error: ui not declared in this scope
............
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtCore>
#include <QCoreApplication>
#include <QPalette>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
Ui::MainWindow *ui;
QPalette temp_red;
QPalette temp_green;
private slots:
void on_button_CalcSchedule_clicked();
void on_button_Reset_clicked();
void execute_run_usrp();
void on_button_QUIT_clicked();
void on_AutoSchedulerCheckBox_stateChanged(int arg1);
void on_button_manul_CalcSchedule_clicked();
void on_button_EXECUTE_clicked();
void on_button_SeeSchedule_clicked();
void on_button_STOP_clicked();
void function_test();
public slots:
void updateTXFreq(double a);
private:
void reset_sweep_values();
std::string calc_schedule_start_time(int minute_cadence);
void calc_cadence();
double calc_sweep_duration();
int nearest_cadence(int numToRound, int multiple);
signals:
void send_start_schedule(std::string, double, int, int);
};
#endif // MAINWINDOW_H
Attempt #2: Use Qt CONNECT functionality:
Step 1: generate a SIGNAL / emit function in the freq_transmit.hpp header:
....
signals:
void sendTXFreq(double a);
Step 2: Enter this emit signal in the freq_transmit.cpp file where the Frequency is being generated:
freq_transmit.cpp:
......
#include "mainwindow.hpp"
#include "ui_mainwindow.hpp"
.....
void Receiver::run()
{
//bunch of lines of code about USRP stuff
.....
emit sendTXFreq(rxCenterFreq); // emit signal to QT
....
Step 3: Declare a SLOT in mainwindow.h to accept emitted signal
mainwindow.hpp:
...
public slots:
void updateTXFreq(double a);
Step 4: Implementation:
mainwindow.cpp:
....
void MainWindow::updateTXFreq(double a)
{
ui->lcdnumber->display(a);
}
connect(&Receiver, &Receiver::sendTXFreq, this, &MainWindow::updateTXFreq); // <-- error: expected primary expression before ','
which is the comma after "&Receiver", which is a class that has various functions in it, including the Receiver::run() where Frequency is generated.`
Long story short, I am trying to have the generated frequency linked to a LCDNumber widget so that it shows on the GUI the value of frequency as the USRP code runs.
PS: I am not an expert C++ coder, I am just now learning about classes and QT GUI. Somebody mentioned that I should "create a pointer of my MainWindow in the freq_transmit.cpp file" so that then I can accesss ui elements direclty in that class, but I thought I tried that with ui->lcdnumber->display(rxCenterFreq);
Any guidance much appreciated and thank you!
In the code pieces below, there are //HERE tagged comments.
In this regions, you see the same namespace declarations. In the first declaration, ShapeChanging class is forward declared. And in the second part, ShapeChanging class is derived from another class. So, it is defined in a different form than its declaration form?
I did not know that language rule. Can anyone explain it?
First: Header file of my widget
#ifndef SHAPECHANGING_H
#define SHAPECHANGING_H
#include <QDialog>
//HERE
namespace Ui {
class ShapeChanging;
}
class ShapeChanging : public QDialog
{
Q_OBJECT
public:
explicit ShapeChanging(QWidget *parent = 0);
~ShapeChanging();
private:
Ui::ShapeChanging *ui;
};
#endif // SHAPECHANGING_H
Second: the file generated by uic
#ifndef UI_SHAPECHANGING_H
#define UI_SHAPECHANGING_H
#include <QtCore/QVariant>
...
QT_BEGIN_NAMESPACE
class Ui_ShapeChanging
{
public:
QVBoxLayout *verticalLayout_2;
QVBoxLayout *verticalLayout;
...
};
//HERE
namespace Ui {
class ShapeChanging: public Ui_ShapeChanging {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_SHAPECHANGING_H
Thanks.
QT_BEGIN_NAMESPACE / QT_END_NAMESPACE is a macro that expands if Qt was compiled with custom namespace (which will not occur in case you downloaded it from Qt website). This option is useful if you are compiling Qt to be used with library that have name collisions with Qt - you can read more about it here: http://wiki.qt.io/Qt_In_Namespace.
For your second question, I think they just wanted to group all classes generated by UIC into single namespace (same thing is discussed here Qt Ui namespace). I'm not sure what is the rationale with two classes, maybe there are some historical reasons or it was easier to write generator template for it this way.
Only thing I can really thing about is that since Qt is been around forever it was also targeting compilers without proper namespace support so they wanted to have Ui namespace as optional thing that can be easily turned off.
This is about a Qt 5.3.2 project buildt using CMake.
I have designed a QMainWindow using the Qt Designer, leading
to main.ui.
CMakeLists.txt (the almost complete thing may be
found here where I already posted it for a different question:
Linking and UIC order in a CMake Qt project )
already takes care of calling UIC so I have my hands on ui_main.h.
ui_main.h offers the class Ui::MainWindow with the plain form information
where all the buttons and stuff should be and the method *void setupUi(QMainWindow MainWindow).
Now my workflow (is it even a feasible one?) goes like this:
I build a totally new header file Form_main.h:
// Form_main.h
[..]
class Form_main : public MainWindow, public QMainWindow
{
Q_OBJECT
privat slots:
void on_some_event();
[..]
};
The class uses said auto-generated MainWindow::setupUi(this) to 'get in shape' and QMainWindow to be, well, a QMainWindow with all that stands for.
But now I am in a dilemma: Either I remove the Q_OBJECT macro call leading to connect(..) no longer recognizing that Form_main has signal slots, or
I keep the Q_OBJECT leading to the infamous
undefined reference to `vtable for display::Form_main'
error while linking the project.
Now, there have been, in fact, people with similar issues.
Naming some links:
http://michael-stengel.com/blog/?p=103
Qt Linker Error: "undefined reference to vtable"
Undefined reference to vtable... Q_OBJECT macro
Qt vtable error
A hint I got from the last one: "MOC must generate code for ui_main.h and the generated code must be compiled and linked."
In any case, these answers all seem to boil down to 'running qmake again'. Well, I use CMake all the way wanting my project to configure and compile after exactly
cmake .
make
What I did try was deleting everything in and below the build directory
(including every auto-generated file) and then running cmake . && make;.
Sadly that did not help. I am afraid this is my second noob question today... would you bear with me once more?
=== AFTER TRYING GREENWAYS ANSWER I PROVIDE MORE DETAILS. ===
Here is the autogenerated ui_main.h
/********************************************************************************
** Form generated from reading UI file 'main.ui'
**
** Created by: Qt User Interface Compiler version 5.3.2
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef UI_MAIN_H
#define UI_MAIN_H
#include <QtCore/QVariant>
#include <QtWidgets/QAction>
[.. more Widget Includes ..]
QT_BEGIN_NAMESPACE
class Ui_MainWindow
{
public:
QAction *action_exit;
[.. more sub widgets like that .. ]
void setupUi(QMainWindow *MainWindow)
{
[ .. Setting up the form. Harmless code. .. ]
} // setupUi
void retranslateUi(QMainWindow *MainWindow)
{
[ .. completely harmless .. ]
} // retranslateUi
};
namespace Ui {
class MainWindow: public Ui_MainWindow {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_MAIN_H
Reading all this and incorporating your post right now I am at
// form_main.h
#ifndef MHK_FORM_MAIN_H
#define MHK_FORM_MAIN_H
#include <QMainWindow>
#include "ui_main.h"
[..]
namespace Ui { class MainWindow; }
namespace display
{
class Form_main : public QMainWindow
{
Q_OBJECT
private:
ostream* stdout;
ostream* stderr;
Ui::MainWindow* uiMainWindow;
/** Called by the constructor. Sets up event connections and other
* preliminary stuff the qt Designer is overtasked with. */
void setup_form();
[..]
public:
explicit Form_main(QWidget* parent = 0);
~Form_main();
private slots:
void exit_program();
};
}
#endif
And my cpp
// form_main.cpp
#include "ui_main.h"
#include "form_main.h"
[..]
using namespace Ui;
namespace display
{
void Form_main::setup_form()
{
QObject::connect(uiMainWindow->action_exit, SIGNAL(triggered()), this, SLOT(exit_program()));
[..]
}
Form_main::Form_main(QWidget* parent) : QMainWindow(parent)
{
uiMainWindow = new Ui::MainWindow();
uiMainWindow->setupUi(this);
[..]
#if defined(Q_OS_SYMBIAN)
this->showMaximized();
#else
this->show();
#endif
}
Form_main::~Form_main()
{
delete uiMainWindow;
}
[..]
Form_main::exit_program()
{
this->close();
(*stdout) << "Thanks for playing " << getProgramName() << endl;
}
}
Ok. I see (partly) the problem. Just create a widget class like this:
.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
.cpp
#include "MainWindow.h"
#include "ui_MainWindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
This is how the QtCreator creates ui-Widgets. "ui_MainWindow.h" is your generated .h file.
Thanks for all your help! However, the problem was in CMakeLists.txt after all. The comment of Chris Morlier on Undefined reference to vtable pointed me to the solution.
The pertinent passage goes:
For Qt users: you can get this same error if you forget to moc a header
I simply had to add the header form_main.h into this line:
QT5_WRAP_CPP(qt_H_MOC ${qt_H} "${DIR_SRC}/include/form_main.h")
I'm a newbie in Qt and not that much experienced in C++ either.
I created simple Qt GUI app, but then I had to add the mousepressevent function on a QLabel type object, so I created the class which has the header file with following code:
#ifndef IMAGEACTION_H
#define IMAGEACTION_H
#include <QLabel>
#include <QMouseEvent>
#include <QDebug>
#include <QEvent>
class imageaction : public QLabel
{
Q_OBJECT
public:
explicit imageaction(QWidget *parent = 0);
void mousePressEvent(QMouseEvent *ev);
signals:
void Mouse_Pressed();
public slots:
};
#endif // IMAGEACTION_H
The .cpp file has the following code:
#include "imageaction.h"
imageaction::imageaction(QWidget *parent) :
QLabel(parent)
{
}
void imageaction::mousePressEvent(QMouseEvent *ev)
{
emit Mouse_Pressed();
}
In the mainwindow.cpp file added the line #include "imageaction.h" to include the header file and in the .pro file it's the following lines are also added:
SOURCES += main.cpp\
mainwindow.cpp \
imageaction.cpp
HEADERS += mainwindow.h \
imageaction.h
But the program always gives the following error:
C1083: Cannot open include file:'imageaction.h': No such file or directory.
Could you say where I'm making the mistake? To make this class I followed this video
I think, "C1083: Cannot open include file:'imageaction.h': No such file or directory" error from your ui_*.h file. If that is the case, your issue regading promoting imageaction widget.
This may work
1. while promoting imageaction widget, uncheck "globalinclude".
or
2. Update pro file with "INCLUDEPATH += path where mywidget.h"
Please check for more info Promoting Widget
I am running QT Creator on a Linux Ubuntu 9.10 machine. I just got started with QT Creator, and I was going through the tutorials when this error popped up while I was trying to build my project: "ISO C++ forbids declaration of 'QPushButton' with no type". This problem appears in my header file:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtGui/QWidget>
namespace Ui
{
class MainWindow;
}
class MainWindow : public QWidget
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void addContact();
void submitContact();
void cancel();
private:
Ui::MainWindow *ui;
QPushButton *addButton;
QPushButton *submitButton;
QPushButton *cancelButton;
QLineEdit *nameLine;
QTextEdit *addressText;
QMap<QString, QString> contacts;
QString oldName;
QString oldAddress;
};
#endif // MAINWINDOW_H
I think you are simply missing the appropriate header file. Can you try
#include <QtGui/QtGui>
instead, or if you prefer
#include <QtGui/QPushButton>
Actually, forward declaration would be enough, instead of the include:
class QPushButton;
Always prefer forward declarations in headers, and do the include in the .cpp
(faster and less recompilations in larger projects).
You are missing this:
#include <QtGui>
You might also want to check the .pro file.
Do you have an entry like "QT = ..." somewhere? If so, try changing that to "QT += ...". Qt's Core and GUI module are default settings for the QT variable, but CAN be overwritten, which will lead to compiler and/or linker errors.