【问题标题】:Call Method from QT slot in static method在静态方法中从 QT 槽调用方法
【发布时间】:2020-04-07 15:54:02
【问题描述】:

我有一个静态方法,它显示一个列表(项目)并在项目中返回一个选定对象的数组。 我想添加一个复选框以沿某些参数重新加载列表。我们使用的是 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 很愚蠢,并且没有成功捕捉到复选框上的动作

【问题讨论】:

    标签: c++ qt static-methods


    【解决方案1】:

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

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

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

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

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

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

    对话框应该变成一个新的类,你的槽会去哪里:

    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 的时代,这段代码也会被认为是粗俗的——全局/单例的看似普遍的使用是令人畏惧的。我总是想知道为什么从事如此大规模项目的人不会查看他们支付的代码并且可供他们使用:Qt 3 包含 Qt Designer 的完整源代码,这可能是人们寻找灵感/辅导的地方.如今,Qt Creator 的代码库比 Designer 大得多(超过一个数量级),并且架构相当不错,因此大型项目可能会从那里获得灵感。

    【讨论】:

    • 感谢您的贡献,但它根本没有帮助。除了做不好的评论和上课之外,我看不到任何帮助。两天以来我一直在这,当然我看过项目,这是唯一使用此类代码的部分。这就是我发布这个的原因
    • @Yannick 我写的一切都是真的。我在您的代码中指出了三个错误(它们是枚举列表)。除非你解决所有三个问题,否则它没有工作的机会。代码根本无法拥有当前的形式,它需要进行根本性的更改,以便对话框成为自己的类。如果这是使用此代码的唯一部分,那么它应该消失 - 对于任何使用 Qt 的人来说,这都是不必要的奇怪和惊讶。 CMSUI_InputDialog 也应该是普通的QDialog 派生类,没有静态方法。至于上课:如果你知道怎么做,那你为什么要问?
    猜你喜欢
    • 2014-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多