【问题标题】:Qt : instantiate object on click on PushButtonQt:单击 PushButton 实例化对象
【发布时间】:2017-06-03 20:33:31
【问题描述】:

我有一个名为 Cipher 的基类和许多子类,如 Xor、Caesar、Affine 等

我有一个按钮列表,每个按钮都可以在单击按钮时实例化一个不同的对象

对于 button1 我想实例化 child1 对于 button2 我想实例化 child2 等等

    std::vector<std::string> ciphers = {"Xor", "Caesar", "Affine", "AveMaria", "Autoclave", "Vigenere"};

for (std::vector<std::string>::iterator it = ciphers.begin(); it != ciphers.end(); it++)
    associative_buttons.push_back(std::make_pair(*it, new QPushButton (QString::fromStdString(*it), this)));

int y = 15;
QFont font ("Courier");
for (std::list<std::pair<std::string, QPushButton*> >::iterator it = associative_buttons.begin(); it != associative_buttons.end(); it++)
{
    (std::get<1>(*it))->setFont(font);
    (std::get<1>(*it))->setGeometry(40, 30, 160, 50);
    (std::get<1>(*it))->move(15, y);
    y += 50;

    QObject::connect(std::get<1>(*it), SIGNAL(clicked()), this, SLOT()); // my problem is here
}

有可能吗? 我有一个对象工厂以防万一

编辑:

我得到一个错误:win.cpp:73: erreur: cannot call member function 'QObject* QObject::sender() const' without object if (std::get(*it) == QApplication::sender())

正常吗? 我的 QApplication 没有在那里声明 ^

#include "win.h"

Win::Win() : QWidget()
{
    c = nullptr;

    std::vector<std::string> ciphers = {"Xor", "Caesar", "Affine", "AveMaria", "Autoclave", "Vigenere"};

    for (std::vector<std::string>::iterator it = ciphers.begin(); it != ciphers.end(); it++)
        associative_buttons.push_back(std::make_pair(*it, new QPushButton (QString::fromStdString(*it), this)));

    int y = 15;
    QFont font ("Courier");
    for (std::list<std::pair<std::string, QPushButton*> >::iterator it = associative_buttons.begin(); it != associative_buttons.end(); it++)
    {
        (std::get<1>(*it))->setFont(font);
        (std::get<1>(*it))->setGeometry(40, 30, 160, 50);
        (std::get<1>(*it))->move(15, y);
        y += 50;

        QObject::connect(std::get<1>(*it), SIGNAL(clicked()), qApp, SLOT(handleButtons()));
    }
}

Win::~Win()
{
    for (std::list<std::pair<std::string, QPushButton*> >::iterator it = associative_buttons.begin(); it != associative_buttons.end(); it++)
        it = associative_buttons.erase(it);
}

constexpr unsigned int str2int(const char* str, int h = 0)
{
    return !str[h] ? 5381 : (str2int(str, h + 1) * 33) ^ str[h];
}

void Win::CreateInstance(std::string name)
{
  Cipher * instance = nullptr;

  switch (str2int(name.c_str()))
  {
    case str2int("Xor") :
      instance = new Xor();
      break;
    case str2int("Caesar") :
      instance = new Caesar();
      break;
    case str2int("Vigenere") :
      instance = new Vigenere();
      break;
    case str2int("Affine") :
      instance = new Affine();
      break;
    case str2int("AveMaria") :
      instance = new AveMaria();
      break;
    case str2int("Autoclave") :
      instance = new Autoclave();
      break;
    default:
      break;
  }

  c = instance;
}

void Win::handleButtons()
{
    for (std::list<std::pair<std::string, QPushButton*> >::iterator it = associative_buttons.begin(); it != associative_buttons.end(); it++)
    {
        if (std::get<1>(*it) == QApplication::sender()) // error is here
            CreateInstance(std::get<0>(*it));
    }

    if (c != nullptr)
        c->run();
}

@ab.o2c

编辑:

我最终使用 QObject 而不是 QApplication 修复了它 如果有人需要,这里是代码

    #include "win.h"

Win::Win() : QWidget()
{
    c = nullptr;

    std::vector<std::string> ciphers = {"Xor", "Caesar", "Affine", "AveMaria", "Autoclave", "Vigenere"};

    for (std::vector<std::string>::iterator it = ciphers.begin(); it != ciphers.end(); it++)
        associative_buttons.push_back(std::make_pair(*it, new QPushButton (QString::fromStdString(*it), this)));

    int y = 15;
    QFont font ("Courier");
    for (std::list<std::pair<std::string, QPushButton*> >::iterator it = associative_buttons.begin(); it != associative_buttons.end(); it++)
    {
        (std::get<1>(*it))->setFont(font);
        (std::get<1>(*it))->setGeometry(40, 30, 160, 50);
        (std::get<1>(*it))->move(15, y);
        y += 50;

        QObject::connect(std::get<1>(*it), SIGNAL(clicked()), this, SLOT(handleButtons()));
    }
}

Win::~Win()
{
    for (std::list<std::pair<std::string, QPushButton*> >::iterator it = associative_buttons.begin(); it != associative_buttons.end(); it++)
        it = associative_buttons.erase(it);
}

constexpr unsigned int str2int(const char* str, int h = 0)
{
    return !str[h] ? 5381 : (str2int(str, h + 1) * 33) ^ str[h];
}

void Win::CreateInstance(std::string name)
{
  Cipher * instance = nullptr;

  switch (str2int(name.c_str()))
  {
    case str2int("Xor") :
      instance = new Xor();
      break;
    case str2int("Caesar") :
      instance = new Caesar();
      break;
    case str2int("Vigenere") :
      instance = new Vigenere();
      break;
    case str2int("Affine") :
      instance = new Affine();
      break;
    case str2int("AveMaria") :
      instance = new AveMaria();
      break;
    case str2int("Autoclave") :
      instance = new Autoclave();
      break;
    default:
      break;
  }

  c = instance;
}

void Win::handleButtons()
{
    for (std::list<std::pair<std::string, QPushButton*> >::iterator it = associative_buttons.begin(); it != associative_buttons.end(); it++)
    {
        if (std::get<1>(*it) == QObject::sender())
            CreateInstance(std::get<0>(*it));
    }

    if (c != nullptr)
        c->run();
}

【问题讨论】:

  • 您是否有理由不想为每个 Button 制作单独的插槽?
  • 是的实际上每个按钮都有一个内容字符串,显示在按钮上我想为每个按钮实例化一个不同的对象
  • 这就是按钮不同的原因?但是为什么不制作 slotButton1、slotButton2、... 并将每个 Button 与关联的插槽连接起来
  • 我试图找到一个“最好的”为什么而不是一个巨大的 if else if else if 或 switch case 语句
  • 在您的情况下,if else 将出现在您的插槽中,因为您需要确定哪个按钮是发件人:stackoverflow.com/questions/8692735/…

标签: c++ qt


【解决方案1】:

我认为你可以用 QSignalMapper 做你想做的事。它的目的是映射来自一堆对象的信号并将它们定向到单个插槽,但添加了一个参数来枚举它们来自哪个对象。我认为这正是你想要在这里做的。您只需创建映射器并为每个按钮分配每个按钮和唯一 ID。它避免了为每个按钮创建唯一插槽的需要。

它只有在原始信号没有任何参数的情况下才有效,“点击”信号也是如此,所以对你来说应该没问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-29
    相关资源
    最近更新 更多