功能需求描述:要求製作一個自定義控件CheckBoxList,控件中有N個複選框QCheckBox,當任何一個複選框反轉時,該控件發出信號,信號指示出:此時哪幾個複選框處於選中狀態。
解決方案:顯示出一列複選框,用QListWidget來幹最合適了,默認情況下QListWidget添加的條目item是純文字,而這裏我們要求添加的條目是複選框。
同理,也可以使用樹形控件QTreeWidget、表格控件QTableWidget來組織自定義控件。本文僅以列表形組織爲例了:
UI設計界面、把它應用在別的程序中的運行效果,分別如下所示:
爲了使這個自定義控件更加好用,還添加了全選、全不選、正則篩選等功能,這些功能都沒什麼難度。最關鍵的部分是要搞懂如何在QListWidget裏面添加QCheckBox。
其實也簡單,在ui中拖出一個或者用代碼new一個QListWidget,然後在窗口的構造函數中對QListWidget添加條目即可:
for(int i = 0; i < cnt; i++)
{
QListWidgetItem *item = new QListWidgetItem();
QCheckBox *checkBox= new QCheckBox ();
ui->listWidget->addItem(item);//在ListWidget中添加一個條目
ui->listWidget->setItemWidget(item, checkBox);//在這個條目中放置CheckBox
icheckBox->setText(QString("checkBox_%1").arg(i));
//把所有checkBox的信號都引向同一個槽
connect(checkBox, SIGNAL(stateChanged(int)), this, SLOT(anyStateChanged()));
}
/*任何一個checkBox被點擊時,共同的槽函數*/
void XXXXX::anyStateChanged()
{
//qDebug() << "one checkBox State Changed";
selectedItems.clear();
//遍歷所有的CheckBox,把所有選中的CheckBox索引號都記錄到QStringList selectedItems中
for(int i = 0; i < ui->listWidget->count(); i++)
{
QListWidgetItem *item = ui->listWidget->item(idx);//先獲取QListWidgetItem
QCheckBox *checkBox = static_cast<QCheckBox *>(ui->listWidget->itemWidget(item));//找到第i個Item對應的CheckBox
if(checkBox->isChecked())
selectedItems.append(i);
}
}
需要注意的是,任何一個CheckBox被點擊都會觸發anyStateChanged()這個槽函數,進行遍歷所有CheckBox,如果用戶點擊了全選,那豈不是在一瞬間要遍歷N多遍,這樣做太低效,我的做法是,點擊全選或者全不選時,用disConnect解除Click信號與anyStateChanged()槽的connect,然後自己構建編號的List並emit出去,然後再重新connect他們。
注意上面的ui->listWidget->setItemWidget(item, checkBox),其實我們不僅能向QLishWidget裏面放置CheckBox,任何QWidget都可以放,我們可以自定義一個QWidget,裏面包含好幾個基本控件,然後把這個含有多個基本控件的自定義的Widget一併放到QLishWidget的每一個item裏去。
我的一個項目的應用場景中,不僅要支持多選,還要實時顯示每一項的數值,效果如下:
代碼已上傳到CSDN,下載鏈接見評論