QT 实现动态添加按钮

  • Post author:
  • Post category:其他


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



版权声明:本文为wangzhezhilu001原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。