【问题标题】:Qt no such slot for methodQt没有这样的方法槽
【发布时间】:2019-10-08 08:50:55
【问题描述】:

我正在尝试学习 Qt(使用 CMake/c++)。这是我写的一段代码。我正在尝试使用连接功能。没有编译错误。我还使用以下命令重新生成 moc 文件。

moc -o moc_SimulationRunner.cpp SimulationRunner.h

但是我在运行我的项目时仍然收到此错误:

QObject::connect: No such slot SimulationRunner::_OpenFileDialog(file_address)

我的头文件是:

class SimulationRunner : public QWidget
  {
  Q_OBJECT

  public:
    explicit SimulationRunner(QWidget *parent = nullptr);

  private:
    QGroupBox *createFirstExclusiveGroup();

  private slots:
    bool _OpenFileDialog(QLineEdit* i_line_edit, std::string = "");

  };

我的 cpp 文件是:

QGroupBox *SimulationRunner::createFirstExclusiveGroup()
  {
  QGridLayout *grid = new QGridLayout;
  ....

  QLineEdit *file_address= new QLineEdit();
  file_address->setPlaceholderText("File address");

  QPushButton *file_address_button = new QPushButton("Browse...");
  file_address_button ->setFixedWidth(75);

  grid->addWidget(file_address, 0, 0, 1, 1);
  grid->addWidget(file_address_button , 1, 1, 1, 1);

  group_box->setLayout(grid);

  QObject::connect(file_address_button , SIGNAL(clicked()), this, SLOT(_OpenFileDialog(file_address)));
  return group_box;
  }

bool SimulationRunner::_OpenFileDialog(QLineEdit* i_line_edit, std::string /* = "" */)
  {
  if (!i_line_edit)
    return false;

  QString filename = QFileDialog::getOpenFileName(
    this,
    "Open Document",
    QDir::currentPath(),
    "All files (*.*) ;; Document files (*.doc *.rtf);; PNG files (*.png)");

  if (!filename.isNull())
    {
    qDebug() << "selected file path : " << filename.toUtf8();
    }

  i_line_edit->setText(filename);
  return true;
  }

【问题讨论】:

标签: c++ qt qt-creator


【解决方案1】:

信号和槽的参数(签名)必须匹配。

如果您使用old string-based Syntax,您必须在 SIGNAL() 和 SLOT() 宏中定义参数。所以你可以像这样连接:

QObject::connect(file_address_button, SIGNAL(clicked(bool)), this, SLOT(_ExampleSlotFunction(bool)));

您无法连接到具有更多或不同参数的插槽。但是,您可以连接到具有较少参数的插槽,例如像这样:

QObject::connect(file_address_button, SIGNAL(clicked(bool)), this, SLOT(_AnotherExampleSlotFunction()));

如果您使用new QT5 Syntax(建议使用它,因为它应该在编译时已经警告您)您不需要自己指定参数:

QObject::connect(file_address_button, &QPushButton::clicked, this, &ExampleClass::_ExampleSlotFunction);
QObject::connect(file_address_button, &QPushButton::clicked, this, &ExampleClass::_AnotherExampleSlotFunction);

QT5 / C++11 解决方法
要传递不同的参数,您可以将 lambda 函数连接到信号,在该信号中调用插槽或函数。所以要通过你的QLineEdit

QObject::connect(
    file_address_button, &QPushButton::clicked,
    this, [file_address]() { _OpenFileDialog(file_address); }
);

进一步说明:
New Syntax
Default Arguments

【讨论】:

  • 感谢您的回答。但是我仍然遇到同样的错误: QObject::connect(MatAMX_address_button, SIGNAL(clicked()), this, SLOT(_OpenFileDialog(file_address, "")));
  • @H'H slot 和 signal 的签名(参数)仍然不匹配。对于 QPushButton::clicked() 信号 (doc.qt.io/qt-5/qabstractbutton.html#clicked),您只能连接带有布尔参数或根本没有参数的插槽。我通过连接一个 lambda 函数来更新答案。
【解决方案2】:

您误解了连接中参数的含义。

您的插槽的签名

OpenFileDialog(QLineEdit*, std::string);

你的连接的签名

OpenFileDialog(QLineEdit*)

这就是您收到警告的原因。您不是在调用函数(因此可以使用默认参数解析),而是指向一个函数,因此签名必须相同。

提示:除非您必须使用 Qt4,否则请使用 Qt5 连接语法:

QObject::connect(file_address_button, &QPushButton::clicked, this, &SimulationRunner::OpenFileDialog);

针对您的具体情况:

如果你总是在你的插槽中传递file_address,那么只需从插槽中删除参数并直接在正文中使用它。

否则,如果您使用的是 Qt4,唯一的解决方法是在没有对象的情况下使用调用创建一个额外的插槽。

Qt4方式:

private slots:
void _dummySlot(){
   _OpenFileDialog(file_address);
}

  QObject::connect(file_address_button , SIGNAL(clicked()), this, SLOT(_dummySlot()));

Qt5方式,使用lambda:

    QObject::connect(file_address_button, &QPushButton::clicked, this, [this](){
        _OpenFileDialog(address_name);
    });

【讨论】:

  • 感谢您的回答。但是我仍然遇到同样的错误: QObject::connect(MatAMX_address_button, SIGNAL(clicked()), this, SLOT(_OpenFileDialog(file_address, "")));
  • 还是同样的错误:QObject::connect: No such slot SimulationRunner::_OpenFileDialog(file_address, std::string(""))
  • SIGNAL 和 slot 必须具有相同的签名:所以 _OpenFileDialog 应该是 ()。如果需要传递参数,请使用 lambda。
  • @H'H 我的错,你不能在槽内传递参数
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-07
相关资源
最近更新 更多