c++ - 在静态方法中从 QT 槽调用方法
问题描述
我有一个静态方法,它显示一个列表(项目)并在项目中返回一个选定对象的数组。我想添加一个复选框以沿某些参数重新加载列表。我们使用的是 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 中声明为插槽
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 知识。
您没有检查该
connect
方法返回的结果:它false
在失败时返回。在你的情况下connect
失败了,所以没有必要再进一步了。插槽不会被调用。原因是:dialog
只是一个QDialog
,不是CMSUI_InputDialog
。您不能将任何插槽添加到现有的 Qt 类。插槽必须是
QObject
s 中的方法。您添加“插槽”的类不是从QObject
. 您需要创建这样的类(以替换QDialog
您正在使用的类)。slots
是一个空的宏(扩展为空),因此对编译没有影响。但是,它有一个目的:moc
处理头文件的(元对象编译器)会注意到该宏并将后续方法作为插槽处理。除非您在 class 中也有宏,否则它不会这样做Q_OBJECT
。
首先,您需要将该对话框的选项分解为一个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 大得多(超过一个数量级),并且架构相当不错,因此大型项目可能会从那里获得灵感。
推荐阅读
- excel - 如何使用 VBA 计算 Excel 表格中的列数?
- gstreamer - 带有幽灵垫的 Gstreamer“更改管道中的元素”示例
- android - 无法向 Mainactivity 添加操作,因为它不支持操作
- power-automate - 使用 OAuth 2.0 令牌的 Power Automate API 调用
- python - PIL如何调整图像大小以填充高度和宽度尺寸
- java - 将图像发送到端点时出现问题,错误“状态”:500,“错误”:“内部服务器错误”
- flutter - 即使我使用了 ListView.Separated,也无法分离列表数据
- powershell - 已分配变量时报告警告,但在使用时未使用
- reactjs - 如何在循环 map() 中将 framer-motion 与交叉点观察器一起使用?
- html - 尝试初始化 jQRangeSlider cdn 时未捕获的 TypeError