这几天,在完成一个项目。项目需要实现在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