Sometimes you need to create a very simple single file application in Qt4. However it's problematic since you are always doing the CPP/H separation, and then the main() is in another file...
Any ideas how to do this in a single file? As quick as dirty as possible.
This is an example that shows how to do this in a single file. Just throw this in a new directory, save it as "main.cpp" and then run qmake -project; qmake; make to compile.
#include <QtGui/QApplication>
#include <QtGui/QMainWindow>
#include <QtGui/QPushButton>
class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow(QWidget *parent = 0){
button = new QPushButton("Hello, world!", this);
}
private:
QPushButton *button;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
#include "main.moc"
Two tricks in this demo:
First is how to call "qmake -project" to create a *.pro file with the files in the current directory automagically. The target name by default is the name of the directory, so choose it wisely.
Second is to #include *.moc in the CPP file, to ask moc to preprocess the CPP files for QObject definitions.
If you need to build a quick prototype, using Python and PyQt4 is even more compact:
import sys
from PyQt4.QtGui import *
class MainWindow(QMainWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent)
self.button = QPushButton("Hello, world!", self)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
No need to call qmake or to bother with .moc files.
Related
I wrote a little program with a my own class within the main.cpp. Here the code:
#include <QApplication>
#include <QPushButton>
#include <QLabel>
class MyWidget : public QWidget {
//Q_OBJECT
public:
MyWidget(QWidget* parent = 0);
QLabel* label;
QString string;
signals:
public slots:
void setTextLabel();
};
void MyWidget::setTextLabel() {
label->setText("Test");
}
MyWidget::MyWidget(QWidget* parent)
: QWidget(parent) {
}
int main(int argc, char** argv) {
QApplication app(argc, argv);
MyWidget widget;
widget.show();
return app.exec();
}
it seems work but not "completely". My slot doens't work. I suppose i have to put Q_OBJECT. BUT, doing so, I got a list of errors, like this:
undefined reference to `vtable for MyWidget'
........................................
collect2: error: ld returned 1 exit status
make: *** [mywidget] Error 1
I can I manage that? Where the problem?
Signals and slots in Qt are managed through the moc: meta object compiler. Basically, the moc generates additional C++ code for each class containing the Q_OBJECT macro in order to implement effectively the signals and slots mechanisms. The additional code is then linked to the original class declaration.
The problem here is that your class is declared in main.cpp: this conflicts with how the moc is working with your code. You should declare your class in a separate header.
More about the moc
Edit: as hyde pointed, an alternative is to include in your cpp the file generated by the moc: Why is important to include “.moc” file at end of a Qt Source code file?
just append the line #include"main.moc" to your cpp source file should be enough.
More information:
Why is important to include ".moc" file at end of a Qt Source code file?
I am brand new to programming with Qt. I'm trying to do a simple subtraction of some values fed from an epicsQt widget called QELabel, which simply reads the value of an EPICS channel. I want to subtract values from two QELabels and print it to another QELabel. But, I'm getting 'undefined reference to' errors for these ->
MainWindow::on_qeLabel_dbValueChanged(QString const&) MainWindow::on_ShutterOpen_dbValueChanged(QString const&)
Here is the bit of mainwindow.cpp (I followed the example from this youtube video, especially after about the 15 minute mark)
void MainWindow::on_TopShutter_dbValueChanged(const QString &out)
{
double top,bottom,open;
top=ui->TopShutter->text().toDouble();
bottom=ui->BottomShutter->text().toDouble();
open=top-bottom
ui->ShutterOpen->setText(Qstring::number(open));
}
I'm using QTCreator, so I don't have the usual errors that I've been seeing in other forums. I have the slot declared in the header file, and MainWindow set as a Q_Object (this is the whole mainwindow.h file):
#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 slots:
void on_qelabel_dbValueChanged(const QString &out);
void on_ShutterOpen_dbValueChanged(const QString &out);
void on_TopShutter_dbValueChanged(const QString &out);
private:
Ui::MainWindow *ui;
};
#endif //MAINWINDOW_H
Because they are short, and for completeness, here is the main.cpp, and then the .pro
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
And the FirstWeatherAlarm.pro:
#-------------------------------------------------
QT += core gui xml
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = FirstWeatherAlarm
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp
LIBS += -L/usr/lib64/qt5/plugins/designer -lQEPlugin
INCLUDEPATH += /home/jchavez/epicsqt/3.1.0/framework/include
HEADERS += mainwindow.h
FORMS += mainwindow.ui
Have I got everything declared right at the start of all the files? What is missing so that my slots are not right? I created the slot in the gui, using the "right-click" on my QELabel, and selecting "Go to Slot", so I should think all the formatting would be correct. As I've been editing, I've also run qmake and make clean which are other answers I've seen on forums. But nothing is working.
The problem is with two slots:
MainWindow::on_qeLabel_dbValueChanged(QString const&)
MainWindow::on_ShutterOpen_dbValueChanged(QString const&)
They are declared in MainWindow.h file and used somewhere in your project (otherwise you won't get an error).
But they are not implemented in mainwindow.cpp. You should add implementation to this file and the error will go away.
You have implementation for
void MainWindow::on_TopShutter_dbValueChanged(const QString &out)
in mainwindow.cpp, you can add implementation for two more slots. Think about slot as a function. And read more about signals/slots.
I want to exec() a QDialog without GUI for my test - there's no need to show GUI.
In the main window, when I exec() a QDialog, it shows its GUI window. I connect a signal from thread in QDialog to a slot in QDialog, so QDialog.exec() is needed. QDialog.hide() is not working.
Is there any solution?
You should never exec() a dialog. This can lead to subtle bugs, because the exec() call can reenter code you don't plan on being reentered.
If you really insist on using exec(), then the simple solution is to post a CloseEvent to the dialog. The event will be processed once the dialog's event loop starts running.
MyDialog dialog;
QCoreApplication::postEvent(&dialog, new QCloseEvent());
dialog.exec();
This code is functionally equivalent to the following:
MyDialog dialog;
QMetaObject::invokeMethod(&dialog, "close", Qt::QueuedConnection);
dialog.exec();
An alternative, much safer way to accomplish this is not to use exec. Simply connect the dialog's accepted() and rejected() signals to slots in your code - after all, the dialog's acceptance or rejection happens asynchronously.
It's then easy enough simply not to show() the dialog in the test code path. You can also easily simulate the dialog being accepted or rejected by invoking either accept or reject slots.
I really don't understand exactly how you "connected" signals from a thread to dialog's slots, and so on. Feel free to paste the example below into your question, modify it to do the threaded "stuff", and show how it doesn't work. It'd also help to see how you implement the test harness.
The example below is all a single file, it'd help if you would keep it that way when producing a test case that illustrates your problem.
// main.cpp
#include <QApplication>
#include <QDialog>
#include <QLabel>
#include <QGridLayout>
#include <QPushButton>
#include <QDialogButtonBox>
class MyDialog : public QDialog {
QGridLayout m_layout;
QDialogButtonBox m_box;
public:
MyDialog(QWidget * parent = 0) : QDialog(parent), m_layout(this),
m_box(QDialogButtonBox::Ok | QDialogButtonBox::Cancel)
{
m_layout.addWidget(&m_box);
connect(&m_box, SIGNAL(accepted()), SLOT(accept()));
connect(&m_box, SIGNAL(rejected()), SLOT(reject()));
}
};
class MyGui : public QWidget {
Q_OBJECT
QGridLayout m_layout;
QLabel m_label;
QPushButton m_button;
MyDialog m_dialog;
Q_SLOT void on_button_clicked() {
m_dialog.show();
}
Q_SLOT void on_dialog_accepted() {
m_label.setText("The dialog was accepted");
}
Q_SLOT void on_dialog_rejected() {
m_label.setText("The dialog was rejected");
}
public:
MyGui() : m_layout(this), m_button("Show Dialog"), m_dialog(this) {
m_button.setObjectName("button");
m_dialog.setObjectName("dialog");
m_layout.addWidget(&m_label);
m_layout.addWidget(&m_button);
QMetaObject::connectSlotsByName(this);
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MyGui gui;
gui.show();
return app.exec();
}
#include "main.moc"
At Qt/C++ there is QT_DEBUG define macro to know when it is compiled at debug or release.
Is there any method to know if is the application running in debug o release mode inside a QML file?
You can use context properties (or QQmlApplicationEngine::setInitialProperties() since Qt 5.14) to expose C++ objects to QML:
#include <QtGui/QGuiApplication>
#include <QQmlContext>
#include <QQuickView>
#include "qtquick2applicationviewer.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QtQuick2ApplicationViewer viewer;
#ifdef QT_DEBUG
viewer.rootContext()->setContextProperty("debug", true);
#else
viewer.rootContext()->setContextProperty("debug", false);
#endif
viewer.setMainQmlFile(QStringLiteral("qml/quick/main.qml"));
viewer.showExpanded();
return app.exec();
}
main.qml:
import QtQuick 2.2
Item {
id: scene
width: 360
height: 360
Text {
anchors.centerIn: parent
text: debug
}
}
It's not possible to determine this purely from within QML.
You need to know it in runtime or in compile time? Macros are used in compile time, QML is executed in runtime, so there are no difference for compiled application between "debug" and "release".
Solution:
Create a class with const property declared in next way:
class IsDebug : public QObject
{
QOBJECT
Q_PROPERTY( IsDebug READ IsCompiledInDebug ) // Mb some extra arguments for QML access
public:
bool IsCompiledInDebug() const { return m_isDebugBuild; }
IsDebug()
#ifdef QT_DEBUG
: m_isDebugBuild( true )
#else
: m_isDebugBuild( false )
#endif
{}
private:
const bool m_isDebugBuild;
}
I can't seem to figure out what went wrong so I'm here to ask you. I have made a simple class called BOBSNetworkSessionManager defined below. It is a simple class that inherits the QOBject so that I can use signals and slots but it does not have a dialog or any kind of window associated with it. It will eventually call a log in dialog and use the credentials to connect to a tcp server that I have created. This class serves as a layer to manage the connection state of the program because it will only run properly when connected to the server and when being used within 15 minutes without break due to p.c.i. compliance. If these conditions are not true this class will lock the window and force a new login. As of right now I just try to arbitrarily open the main window as though credentials had passed and i wasbconnected to the server. The problem is when I open the mainwindow it disapears right away. I cannot seem to figure out why it is diappearing. I have included all of my files.
BOBSDCNetworkSessionManager .h header file
#ifndef BOBSDCNETWORKSESSIONMANAGER_H
#define BOBSDCNETWORKSESSIONMANAGER_H
#include <QObject>
#include <QSettings>
class BOBSDCNetworkSessionManager : public QObject
{
Q_OBJECT
public:
explicit BOBSDCNetworkSessionManager(QObject *parent = 0);
protected:
void destroyed(QObject *);
signals:
public slots:
private:
void readSettings();
void writeSettings();
QSettings networkSettings;
};
#endif // BOBSDCNETWORKSESSIONMANAGER_H
BOBSDCNetworkSessionManager Implementation .cpp file
#include "bobsdcnetworksessionmanager.h"
#include "bobsmainwindow.h"
BOBSDCNetworkSessionManager::BOBSDCNetworkSessionManager(QObject *parent) :
QObject(parent)
{
BOBSMainWindow w;
w.show();
}
Main.cpp file
#include "bobsdcnetworksessionmanager.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
a.setApplicationName("Enterprise Management Suite");
a.setApplicationVersion("Beta Version: 0.0.0.01");
a.setOrganizationName("Enigma Web Consulting");
a.setOrganizationDomain("http://www.EnigmaWebCo.com");
BOBSDCNetworkSessionManager netMgr;
return a.exec();
}
The problem is here:
{
BOBSMainWindow w;
w.show();
}
w.show() is not a blocking call. So you're creating a window, showing it, and then it immediately is destructed when it goes out of scope. You should either declare w as a member variable or construct it on the heap:
BOBSMainWindow *w = new BOBSMainWindow(this);