QT 實現動態添加按鈕

這幾天,在完成一個項目。項目需要實現在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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章