這幾天,在完成一個項目。項目需要實現在tablewidget裏面動態添加按鈕,且點擊按鈕消息與點擊tablewidget的整行效果相同。
思路如下:
1)tablewidget響應消息設置,並對應相應槽函數;
2)按鈕可以靈活添加和刪除到tablewidget到特定單元格里;同時,按鈕點擊事件的消息,和tablewidget相關聯;
3)按鈕消息觸發按鈕的槽函數,然後拋消息給tablewidget,隨後引發tablewidget的對應事件。
首先實現tablewidget的消息事件(槽函數):
private slots:
void on_tableWidget_Configure_itemDoubleClicked(QTableWidgetItem *item);
void on_tableWidget_Configure_cellDoubleClicked(int row, int column);
void on_tableWidget_Configure_cellClicked(int row, int column);
按鈕本身需要靈活添加和刪除,並和tablewidget進行關聯。
//按鈕綁定到一定單元格里
LinkButton *pBtn = new LinkButton(iRow, 0);
connect(pBtn, SIGNAL(getPointer(int, int)), this, SLOT(on_linkBtn_Clicked(int, int)));
ui->tableWidget_Configure->setCellWidget(iRow, 0, pBtn);
//單元格里刪除按鈕
LinkButton *pBtn = (LinkButton *)ui->tableWidget_Configure->cellWidget(iRow, 0);
delete pBtn;
但顯然,如果按鈕本身可以靈活得收發消息,必須是自己重寫但按鈕。按鈕繼承QPushButtton,重寫如下:
class LinkButton: public QPushButton
{
Q_OBJECT
public:
LinkButton(int iRow, int iCol);
virtual ~LinkButton();
signals:
void getPointer(int, int); //自己的信號
public slots:
void sendPointer(); //槽函數,用於發信息給tablewidget
private:
int m_iRow;
int m_iCol;
};
這個槽函數,關鍵是要發相應的消息給tablewidget,代碼如下:
void LinkButton::sendPointer()
{
emit getPointer(m_iRow, m_iCol);
}
當然,要想使該消息被對應的tablewiget接受,必須讓這個消息和對應的槽函數關聯。這正式上面的按鈕加入對應Cell裏前的綁定步驟:
//綁定按鈕與主窗口消息
connect(pBtn, SIGNAL(getPointer(int, int)), this, SLOT(on_linkBtn_Clicked(int, int)));
值得注意的是:本身發給的消息不是tablewiget,而是整個對話框。
實現整個對話框的槽函數,即可相應消息。
當然裏因爲要控制對tablewiget裏面對按鈕動態添加和刪除,故又添加一系列按鈕,對按鈕添加和刪除進行控制。具體實現如下:
class OperateButton: public QPushButton
{
Q_OBJECT
public:
OperateButton(int iRow, int iCol);
virtual ~OperateButton();
signals:
void getOperatePos(int, bool);
public slots:
void sendOperate();
private:
int m_iRow;
int m_iCol;
bool m_bDel;
};
該方法,通過發送消息給主窗口,讓主窗口實現對tablewidget的按鈕添加和刪除。
實現後總結:
1)信號和槽是QT不同實體間傳遞消息的方法;但消息的傳遞,應該用有一個統一中介,才能方便轉發到合理實體,本次實體的中介是對話框窗口;
2)可以實現按鈕的動態添加和刪除,注意防止內存泄露。
在實現完成之後,發現對話框關閉時,會發生程序崩潰。重寫對話框的的關閉事件,即closeEvent函數,把按鈕內存釋放掉,並把tablewidget的行數變爲0,程序不再崩潰。
重寫函數如下:
void TestBtnWigetDlg::closeEvent(QCloseEvent *)
{
for(int i = 0; i < ROW_MAX; i++)
{
delBtn(i, 0);
}
ui->tableWidget_Configure->setRowCount(0);
}
崩潰原因暫時未知,懷疑是tablewidge裏面的Cell釋放後(即Button被刪除)不可訪問,在對話框關閉時視圖清理tabelwidget而訪問到不該訪問到空間造成到,
整個程序詳見gitbub:https://github.com/diziqian/QTButtonWidgetTest