基本Qt应用程序(QMainWindow)中未显示小部件

时间:2014-07-28 17:53:28

标签: qt user-interface qwidget qmainwindow

我是Qt的新手,我正在用简单的例子做一些练习。

我只是想用一个简单的应用程序来测试我的知识,通过编码,用户在QLineEdit小部件中键入文本,文本将显示在QLabel中。没有必要使它有用。我只是想试试。

在编译应用程序时,我没有错误。但是,打开窗口时,QLabel和QLineEdit小部件不可见。

我的代码在这里:

window.h中

#ifndef WINDOW_H
#define WINDOW_H

#include <QMainWindow>

class QGridLayout;
class QLabel;
class QLineEdit;

class Window : public QMainWindow
{
    Q_OBJECT

public:
    explicit Window(QWidget *parent = 0);

private:
    QGridLayout *mainLayout;
    QLabel *label;
    QLineEdit *lineEdit;
};

#endif // WINDOW_H

Window.cpp

#include "Window.h"
#include <QGridLayout>
#include <QLineEdit>
#include <QLabel>

Window::Window(QWidget *parent)
    : QMainWindow(parent)
{
    mainLayout = new QGridLayout;
    label = new QLabel(tr("Text"));
    lineEdit = new QLineEdit;

    mainLayout->addWidget(label, 0, 0);
    mainLayout->addWidget(lineEdit, 1, 0);
    setLayout(mainLayout);

    connect(lineEdit, SIGNAL(textChanged(QString)),
            label, SLOT(setText(QString)));
}

的main.cpp

#include <QApplication>
#include "Window.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    Window window;
    window.show();

    return app.exec();
}

我在代码中找不到任何错误。

提前谢谢。

2 个答案:

答案 0 :(得分:8)

QMainWindow必须有一个中央窗口小部件,即使它只是一个占位符。另请注意,它有自己的布局用于添加工具栏,菜单栏等 - 所以您可能希望为中央窗口小部件设置布局(mainLayout)。

查看QMainWindow class reference了解详情。

要使您的窗口小部件在主窗口中可见,您可以像这样修改构造函数:

Window.cpp

#include "Window.h"
#include <QGridLayout>
#include <QLineEdit>
#include <QLabel>

Window::Window(QWidget *parent)
    : QMainWindow(parent)
{
    QWidget* someWidget = new QWidget(this);
    mainLayout = new QGridLayout;
    label = new QLabel(tr("Text"));
    lineEdit = new QLineEdit;

    mainLayout->addWidget(label, 0, 0);
    mainLayout->addWidget(lineEdit, 1, 0);
    someWidget->setLayout(mainLayout);

    connect(lineEdit, SIGNAL(textChanged(QString)),
             label, SLOT(setText(QString)));

    setCentralWidget(someWidget);
}

答案 1 :(得分:5)

使用QWidget代替QMainWindow。后者并不意味着直接使用像你一样的布局。除非您明确需要它提供的功能(工具栏,停靠区域等),否则不要使用QMainWindow。如果您确实想使用QMainWindow,那么Akos's excellent answer会显示如何执行此操作。

任何小部件,即使是简单的QLabel也可以是您的&#34; main&#34;窗口小部件。

您也不需要动态分配小部件的所有复杂功能。

简单地说:

class Window : public QWidget
{
   Q_OBJECT
   QGridLayout m_layout;
   QLabel m_label;
   QLineEdit m_lineEdit;
public:
   explicit Window(QWidget *parent = 0);
};

然后构造函数缩减为:

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)));
}

要尝试一下,您可能希望将其全部放在一个main.cpp文件中:

#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"

确保在尝试编译之前在项目上重新运行qmake。

对于给定的foo.cpp文件,当您想通过moc运行#include "foo.moc"文件时,最后需要.cpp。例如,您可能希望私有QObject派生类存在于.cpp文件中并在该文件中使用。然后,您不必将此类的接口分成单独的头文件。这在Qt 4和pre-C ++ 11中更为重要,当时你没有lambdas并且不得不将插槽放入专用类中。在Qt 5中,您可以将信号连接到就地编写的仿函数,因此只需编写一两个插槽就不需要本地帮助程序对象类。

这种方法在您进行实验时非常有用。在这种情况下,将&lt; 1000行代码扩展到三个或更多文件是相当适得其反的。简短的实验都是关于简洁性的。实现进入类声明a-la Java,通过moc运行单个main.cpp文件并在末尾附加moc输出(通过#include "main.moc")。默认Qt Creator生成的模板适用于&#34; big&#34;应用,而非实验。

为了获得灵感,我的stackoverflown answer repository上大约有200个这样的大多数单个文件示例:)每个示例的文件夹都在最后附加了SO问题编号,以便于查找上下文的SO问题。

如果您担心接口标头被实施细节污染,pimpl idiom就会出现问题:

// 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);
}