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

3

我刚接触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个回答

8

QMainWindow必须有一个中央小部件,即使它只是一个占位符。同时请注意,它有自己的布局用于添加工具栏、菜单栏等 - 所以您可能想要为中央小部件设置布局(在您的代码中为mainLayout)。

有关详细信息,请查看QMainWindow类参考

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

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

感谢@Akos Bannerth提供的简单解决方案。 - ukll

5
请使用 QWidget 代替 QMainWindow。后者不适合与您正在执行的布局直接使用。除非您明确需要其提供的功能(工具栏、停靠区等),否则不要使用 QMainWindow。如果您真的想使用 QMainWindow,那么Akos 的优秀答案展示了如何做到这一点。
任何小部件,甚至是简单的 QLabel 都可以成为您的“主”小部件。
您也不需要动态分配小部件的所有复杂性。
只需执行以下操作:
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运行.cpp文件时,需要在末尾包含#include "foo.moc"。例如,您可能希望使用一个私有的基于QObject的类,该类存在于.cpp文件中并在该文件中使用。您不必将此类的接口分离到单独的头文件中。这在Qt 4和C++11之前更为重要,因为您没有lambda并且必须将slot放入专用类中。在Qt 5中,您可以将信号连接到原地编写的函数对象,因此几乎不需要本地辅助对象类来编写一个或两个slot。

这种方法在进行实验时非常有用。将小于1000行的代码分散到三个或更多文件中,在这种情况下相当低效。短期实验需要简洁明了。实现采用Java风格的类声明,通过moc运行单个main.cpp文件,并在末尾附加moc输出(通过#include "main.moc")。默认的Qt Creator生成的模板适用于“大型”应用程序,而不适用于实验。
如果需要灵感,我的stackoverflown答案仓库中有大约200个这样的主要是单个文件的示例:)每个示例的文件夹末尾都附有SO问题号,以便轻松查找上下文相关的SO问题。
如果您担心接口头文件被实现细节污染,那么pimpl习惯用法就来拯救了:
// 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);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接