Use the QWidget
instead of QMainWindow
. The latter is not meant to be used directly with a layout like you're doing. Don't use QMainWindow
unless you explicitly need the features it offers (toolbars, dock areas, etc.). If you really want to use QMainWindow
, then Akos's excellent answer shows how to do it.
Any widget, even a simple QLabel
can be your "main" widget.
You also don't need all the complication of dynamically allocating the widgets.
Simply do:
class Window : public QWidget
{
Q_OBJECT
QGridLayout m_layout;
QLabel m_label;
QLineEdit m_lineEdit;
public:
explicit Window(QWidget *parent = 0);
};
Then the constructor reduces to:
Window::Window(QWidget *parent)
: QWidget(parent), m_layout(this), m_label(tr("Text"))
{
m_layout.addWidget(&m_label, 0, 0);
m_layout.addWidget(&m_lineEdit, 1, 0);
connect(&m_lineEdit, SIGNAL(textChanged(QString)),
&m_label, SLOT(setText(QString)));
}
To try things out, you may wish to put it all in a single main.cpp
file:
#include <QApplication>
#include <QLabel>
#include <QTextEdit>
class Window : public QWidget
{
Q_OBJECT
QGridLayout m_layout;
QLabel m_label;
QLineEdit m_lineEdit;
public:
explicit Window(QWidget *parent = 0) : QWidget(parent),
m_layout(this), m_label(tr("Text"))
{
m_layout.addWidget(&m_label, 0, 0);
m_layout.addWidget(&m_lineEdit, 1, 0);
connect(&m_lineEdit, SIGNAL(textChanged(QString)),
&m_label, SLOT(setText(QString)));
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Window window;
window.show();
return app.exec();
}
#include "main.moc"
Make sure that you re-run qmake on the project before you attempt to compile it.
For a given foo.cpp
file, you need to #include "foo.moc"
at the end when you want to run the .cpp
file through moc. You might want, for example, a private QObject
-derived class that lives in a .cpp
file and is used in that file. You don't have to separate the interface of this class into a separate header file, then. This was much more important in Qt 4 and pre-C++11, when you had no lambdas and had to put slots into dedicated classes. In Qt 5 you can connect a signal to a functor written in-place, so there's much less need for local helper object classes just to write a slot or two.
This approach is very useful when you're experimenting. Having the <1000 lines of code spread about three or more files is rather counterproductive in such cases. Short experiments are all about conciseness. Implementations go into class declarations a-la Java, you run the single main.cpp
file through moc and append the moc output at the end (via #include "main.moc"
). Default Qt Creator-generated templates are for "big" applications, not for experiments.
For inspiration, there's about 200 such mostly single-file examples on my stackoverflown answer repository :) Each example's folder has the SO question number appended at the end, to make it easy to look up the SO question for context.
If you're concerned about the interface headers being polluted with implementation details, the pimpl idiom comes to the rescue:
// window.h
#ifndef MY_WINDOW_H
#define MY_WINDOW_H
#include <QWidget>
#include <QScopedPointer>
// This only provides a public interface.
class WindowPrivate;
class Window : public QWidget {
Q_OBJECT
Q_DECLARE_PRIVATE(Window)
QScopedPointer<WindowPrivate> const d_ptr;
public:
explicit Window(QWidget *parent = 0);
~Window();
QString text() const;
};
#endif
// window.cpp
#include "window.h"
#include <QLabel>
#include <QLineEdit>
#include <QGridLayout>
class WindowPrivate {
Q_DISABLE_COPY
public:
explicit WindowPrivate(Window *);
QGridLayout layout;
QLabel label;
QLineEdit lineEdit;
};
Window::Window(QWidget * parent) : QWidget(parent), d_ptr(new WindowPrivate(this))
{
Q_D(Window);
// This code really belongs in WindowPrivate constructor.
// It is shown here to illustrate how the non-const pimpl is accessed.
connect(&d->lineEdit, SIGNAL(textChanged(QString)),
&d->label, SLOT(setText(QString)));
}
// Needed here since the ~WindowPrivate is not visible outside of this file.
Window::~Window() {}
QString Window::text() const {
Q_D(const Window);
// This is how you access const pimpl
return d->label.text();
}
WindowPrivate::WindowPrivate(Window * window) :
layout(window), label(tr("Text"))
{
layout.addWidget(label, 0, 0);
layout.addWidget(lineEdit, 1, 0);
}