在静态方法中从 QT 槽调用方法

Call Method from QT slot in static method

我有一个显示列表(项目)的静态方法和return项目中选定对象的数组。 我想添加一个复选框以根据某些参数重新加载列表。我们正在使用 QT 3.3。

//// Static
int CMSUI_InputDialog::FittingList(QWidget* parent,
  const CString& Title,
  const CStringArray& Items,
  bool                  IsMultiSelect,
  int                       DefaultItem,
  bool                  OkIsDefault,
    CArray<int, int>& Selecteds)
{

 int ret = 0;
 Selecteds.RemoveAll();

 /// Create grid
 QDialog    dialog(parent, 0, true);
 dialog.setCaption(QString(Title));

 QGridLayout* pLayoutGrid = Init(&dialog, OkIsDefault);

 //Create checkBox
 QCheckBox* pCheckBox = new QCheckBox(&dialog, "m_pApply_Filter");
 pCheckBox->setText("Norm Filter");

 pLayoutGrid->addWidget(pCheckBox, 0, 0);

 QObject::connect(pCheckBox, SIGNAL(stateChanged(int)), &dialog, SLOT(checkboxClicked()));

 /// Create ListBox
 QListBox* pList = new QListBox(&dialog);
 pList->setMinimumSize(QSize(370, 90));

 pList->setSelectionMode(QListBox::Extended);

 // Load the list
 int Count = Items.GetSize();
 for (int i = 0; i < Count; i++)
 {
    QString QS(Items[i]);
    pList->insertItem(QS);
 }

 if (DefaultItem >= 0 && DefaultItem < Count)
    pList->setSelected(DefaultItem, true);

 pLayoutGrid->addWidget(pList, 1, 0);

 // Connect double clic on QDialog accept
 QObject::connect(pList, SIGNAL(doubleClicked(QListBoxItem*)), &dialog, SLOT(accept()));

 if (dialog.exec() == QDialog::Accepted)
 {
    for (int i = 0; i < Count; i++)
    {
        if (pList->isSelected(i))
            Selecteds.Add(i);
    }
    ret = 1;
  }

  return ret;
}

void CMSUI_InputDialog::checkboxClicked()
{
    //To do
}

checkboxClicked() 在 CMSUI_InputDialog.h 中声明为 slot

class CMSUI_InputDialog
{
protected :

    static QGridLayout* Init(QWidget* pParent, bool OkIsDefault);

public slots:
    void checkboxClicked();


public:
    /// CheckBox  + ListBox for fittings
    static int FittingList(QWidget* parent,
        const CString& Title,
        const CStringArray& Items,
        bool                    IsMultiSelect,
        int                     DefaultItem,
        bool                    OkIsDefault,
        CArray<int, int>& Selecteds);
};

我尝试了很多东西,但我对 QT 很笨,没有成功捕捉到复选框上的动作

就主要问题而言,这里几乎没有特定于 Qt 的内容:在普通 C++ 中都可以理解,不需要 Qt 知识。

  1. 您没有检查 connect 方法返回的结果:它 returns false 当它失败时。 connect 在你的情况下失败了,所以没有必要再进一步了。插槽不会被调用。原因是:dialog 只是一个 QDialog,而不是 CMSUI_InputDialog。您不能向现有 Qt 添加任何插槽 class.

  2. 插槽必须是 QObject 中的方法。您添加 "slot" 的 class 不是从 QObject 派生的。您需要创建这样一个 class(以替换您正在使用的 QDialog)。

  3. slots 是一个空的宏(展开为空),因此对编译没有影响。不过,它有一个目的:处理头文件的 moc(元对象编译器)会注意到该宏并将后续方法作为槽处理。 它不会那样做,除非你也有 Q_OBJECT macro within the class

首先,您需要将该对话框的选项分解为 FittingOptions 结构,以使代码易于管理。

struct FittingOptions {
  const CStringArray& items,
  bool                isMultiSelect,
  int                 defaultItem,
  bool                okIsDefault,
};

对话框应该变成一个新的 class,您的插槽将位于:

class FittingList : public QDialog {
  Q_OBJECT
  FittingOptions opt;
  CArray<int, int>* selecteds;

public:
  FittingList(QWidget *parent, const FittingOptions &options) :
    QDialog(parent), opt(options), selecteds(0)
  {
    // TODO: initialization code that creates widgets etc.
  }

  void setSelecteds(CArray<int, int> &selecteds)
  {
    this->selecteds = &selecteds;
  }

  // ...

public slots:
  void checkboxChanged() { /* TODO */ }
};

然后,将 FittingList 方法中的初始化代码放入构造函数中。将该方法更改为:

int CMSUI_InputDialog::FittingList(QWidget* parent,
  const CString& title,
  const CStringArray& items,
  bool                isMultiSelect,
  int                 defaultItem,
  bool                okIsDefault,
  CArray<int, int>&   selecteds)
{
   const FittingOptions options = { 
     items, isMultiSelect, defaultItem, okIsDefault
   };
   ::FittingList dialog(parent, options);
   dialog.setCaption(QString(title));
   dialog.setSelecteds(selecteds);

   if (dialog.exec() != QDialog::Accepted) return 0;
   return 1;
}

查看您项目中的其他示例,了解它们是如何解决此类问题的。按照今天的标准,这段代码相当陈旧,但据我所知,这是一项维护工作,所以你必须做更多同样的事情——因为我想你不会升级 Qt 版本。

注意:这显然与代码的原作者有关,与您无关。你还没有写过这些东西。 即使在 Qt 3 时代,这段代码也会被认为是粗鲁的——globals/singletons 看似普遍的使用是令人畏缩的。我总是想知道为什么从事如此大规模项目的人不会查看他们支付的代码并且可供他们使用:Qt 3 包含 Qt Designer 的完整源代码,这就是人们可能寻找的地方 inspiration/tutoring.如今,Qt Creator 的代码库比 Designer 大得多(超过一个数量级),而且架构相当不错,因此大型项目可能会从中汲取灵感。