qt点击按钮本身,来删除自身

本文档展示了一个使用Qt实现的功能,包括:点击添加按钮增加班级和学生信息行,按钮文字在添加和删除间切换,点击删除按钮删除相应行,选择班级自动更新学生列表,并在控件过多时显示垂直滚动条。主要涉及QDialog、QSS样式、QPushButton、QComboBox等组件的使用,以及信号和槽的连接。代码中包含了结构清晰的类定义和事件处理方法。
摘要由CSDN通过智能技术生成

引言

实现下面这样一个功能,点击界面的添加按钮,增加一行班级和学生的信息,刚才被点击行的按钮上的文字由添加变为删除,按钮文字为删除,点击的时候可以删除被点击行的所有控件,选中那个班级后会自动更新对应班级的学生列表,当添加的控件行太多,会自动出现垂直滚动条。
在这里插入图片描述

实现

下面附上完整的代码,该程序,采用了样式来设置了控件的外观,qss文件一起附上。
程序的编译环境:msvc2017 64bit,使用的QtCreate5.13.2。
程序的结构:
在这里插入图片描述
创建基于QDialog的项目,然后向其中添加文件,其它不多说,下面看具体实现。
main.cpp

#include "instructioneditdialog.h"

#include <QApplication>
#include <QFile>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QFile file(":/new/prefix1/myStyle.qss");
    if (file.open(QIODevice::ReadOnly)) {
        QString strText = file.readAll();
        a.setStyleSheet(strText);
        file.close();
    }

    InstructionEditDialog w;
    w.show();
    return a.exec();
}

defineData.h

#ifndef DEFINEDATA_H
#define DEFINEDATA_H
#include <QString>

typedef struct schoolSituation
{
    QString className;//屏幕组号
    QString studentsName;//场景id
}ST_SCHOOL;
typedef ST_SCHOOL stuSchoolSituation;

#endif // DEFINEDATA_H

deleteaddbtn.h

#ifndef DELETEADDBTN_H
#define DELETEADDBTN_H

#include <QPushButton>

/*****************************
        功能描述:
        1.按钮文字为添加,发送添加命令行,
        2.按钮文字为删除,发送删除命令行。
*******************************/

class DeleteAddBtn : public QPushButton
{
Q_OBJECT
public:
    explicit DeleteAddBtn(int id, QWidget *parent = nullptr);
    ~DeleteAddBtn();
protected:
    void mousePressEvent(QMouseEvent *event);//点击添加文字的按钮,发送添加指令信号,点击删除按钮,发送删除被点击行的控件信号
    void paintEvent(QPaintEvent *event);//设置样式
signals:
    void sigAddConstructionCtrl();//添加命令行控件
    void sigDelConstructionCtrl(int &id);//删除被点击行的命令行控件,id-被点击按钮的id
private:
    int         m_id;//按钮的id
};

#endif // DELETEADDBTN_H

deleteaddbtn.cpp

#include "deleteaddbtn.h"
#include <QMouseEvent>
#include <QStyleOption>
#include <QPainter>

DeleteAddBtn::DeleteAddBtn(int id,QWidget *parent)
:QPushButton(parent)
{
    m_id = id;
    setAttribute(Qt::WA_StyledBackground);//设置样式生效
}

DeleteAddBtn::~DeleteAddBtn()
{

}

void DeleteAddBtn::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        if (text() == QStringLiteral("添加")) {
            setText(QStringLiteral("删除"));
            emit sigAddConstructionCtrl();
        }else if (text() == QStringLiteral("删除")) {
            emit sigDelConstructionCtrl(m_id);
        }
    }

//    QPushButton::mousePressEvent(event);//删除所在行控件后,会继续回到此处,但是此时该类已经被析构了
}

void DeleteAddBtn::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);

    QStyleOption opt;
    opt.init(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);

    QPushButton::paintEvent(event);
}

specificorderform.h

#ifndef SPECIFICORDERFORM_H
#define SPECIFICORDERFORM_H

#include "defineData.h"
#include <QWidget>
#include <QMap>

/*******************************
      功能描述:
      1.设置班级下拉列表为指定的列表,
      2.根据班级列表中选中的值,设置学生的列表,
      2.设置combox默认初始选中值,
      3.获取combox选中的值。
********************************/

namespace Ui {
class SpecificOrderForm;
}

class SpecificOrderForm : public QWidget
{
    Q_OBJECT

public:
    explicit SpecificOrderForm(QWidget *parent = nullptr);
    ~SpecificOrderForm();
    stuSchoolSituation getOrderChoosedText();//获取指令选中的sid,sceneId
protected:
    void initComboBoxList();//初始化下拉列表的参数
    void setComboxList();//设置下拉列表
private slots:
    void on_classComboBox_currentTextChanged(const QString &arg1);//sid选中后,sceneid列表对应调整(sid没有变,sceneid也不变其列表)

private:
    Ui::SpecificOrderForm *ui;
    QStringList                     m_studentStrList;//场景id列表
    QMap<QString,QStringList>       m_classStudentsMap;//sid和scenid映射表
};

#endif // SPECIFICORDERFORM_H

specificorderform.cpp

#include "specificorderform.h"
#include "ui_specificorderform.h"
#include <QStyledItemDelegate>
#include <QList>

SpecificOrderForm::SpecificOrderForm(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::SpecificOrderForm)
{
    ui->setupUi(this);

    initComboBoxList();
    setComboxList();
    QStyledItemDelegate *delegate = new QStyledItemDelegate();//下拉项的高度起作用,似乎没有作用
    ui->classComboBox->setItemDelegate(delegate);
    ui->studentComboBox->setItemDelegate(delegate);
    setWindowFlags(Qt::FramelessWindowHint);
    setAttribute(Qt::WA_TranslucentBackground);
}

SpecificOrderForm::~SpecificOrderForm()
{
    delete ui;
}

stuSchoolSituation SpecificOrderForm::getOrderChoosedText()
{
    stuSchoolSituation tempClass;
    tempClass.className = ui->classComboBox->currentText();
    tempClass.studentsName = ui->studentComboBox->currentText();
    return tempClass;
}

void SpecificOrderForm::initComboBoxList()
{
    QStringList students;
    students.append(QStringLiteral("胡姬"));
    students.append(QStringLiteral("张三"));
    students.append(QStringLiteral("李虎"));
    students.append(QStringLiteral("王宁"));
    students.append(QStringLiteral("紫荆"));
    students.append(QStringLiteral("梅斯卡通"));
    m_classStudentsMap.insert(QStringLiteral("一班"),students);

    students.clear();
    students.append(QStringLiteral("胡微姬"));
    students.append(QStringLiteral("张上三"));
    students.append(QStringLiteral("李虎上"));
    students.append(QStringLiteral("王宁"));
    students.append(QStringLiteral("紫荆史蒂夫"));
    students.append(QStringLiteral("梅斯卡通"));
    m_classStudentsMap.insert(QStringLiteral("二班"),students);

    students.clear();
    students.append(QStringLiteral("阿叔"));
    students.append(QStringLiteral("神盾局弟"));
    students.append(QStringLiteral("电视剧"));
    students.append(QStringLiteral("四道口"));
    students.append(QStringLiteral("圣诞节"));
    students.append(QStringLiteral("可颂"));
    m_classStudentsMap.insert(QStringLiteral("三班"),students);
}

void SpecificOrderForm::setComboxList()
{   
    QStringList classStrList;
    QList<QString> classList = m_classStudentsMap.keys();
    for (int j = 0 ; j < classList.size() ; ++j) {
        QString strClass = classList[j];
        classStrList.append(strClass);
    }
    ui->classComboBox->addItems(classStrList);
    if (classStrList.size() != 0) {
        ui->classComboBox->setCurrentText(classStrList.at(0));
    }
}

void SpecificOrderForm::on_classComboBox_currentTextChanged(const QString &arg1)
{
    if (m_studentStrList.size() != 0) {
        m_studentStrList.clear();
        ui->studentComboBox->clear();
    }

    QMap<QString,QStringList>::iterator it;
    for (it = m_classStudentsMap.begin() ; it != m_classStudentsMap.end() ;++it) {
        if (arg1 == it.key()) {
            m_studentStrList = it.value();
        }
    }
    ui->studentComboBox->addItems(m_studentStrList);
    if (m_studentStrList.size() != 0) {
        ui->studentComboBox->setCurrentText(m_studentStrList.at(0));
    }
}

instructioneditdialog.h

#ifndef INSTRUCTIONEDITDIALOG_H
#define INSTRUCTIONEDITDIALOG_H
#include "specificorderform.h"
#include "deleteaddbtn.h"
#include <QDialog>
#include <QQueue>
#include <QMap>
#include <QVBoxLayout>

/*****************************
        功能描述:
        1.添加命令行控件,
        2.删除命令行,
        3.获取编辑的按钮名字和选中的命令集,
        4.记录并更新创建的指令行控件的id,
        5.调整命令行控件的布局,“太多”增加滚动条,
        6.设置按钮的样式。
*******************************/
typedef struct cmdCtrl
{
    SpecificOrderForm *order;//指令
    DeleteAddBtn      *btn;//指令后的按钮
}ST_CMDCTRL;
typedef ST_CMDCTRL stuCmdCtrl;

namespace Ui {
class InstructionEditDialog;
}

class InstructionEditDialog : public QDialog
{
    Q_OBJECT

public:
    explicit InstructionEditDialog(QWidget *parent = nullptr);
    ~InstructionEditDialog();

protected:
    void setVBlayout();//设置滚动区域的垂直布局
    void createCommandLine();//创建命令行
    void adjustLayoutHeight(int num);//调整布局的高度
    void setPushBtnStyle(DeleteAddBtn *delBtn);//设置添加/删除按钮的样式
private slots:
    void on_confirmBtn_clicked();//获取名称和被添加的指令
    void on_cancelBtn_clicked();//清空行编辑器,窗口关闭
    void onDelConstructionCtrl(int &id);//删除对应id的命令行控件
signals:
    void sigNameInstructionSet(QString &name,QList<stuSchoolSituation> &cmdSet);//发送按钮名称,sid和sceneid的指令集
private:
    Ui::InstructionEditDialog *ui;
    SpecificOrderForm           *m_orderForm;//命令行控件
    DeleteAddBtn                *m_pushBtn;//删除添加按钮
    QQueue<int>                 m_deletedId;//保存删除的指令行id,当其中不为空,创建指令行从队列中取id,直到为空重新从上一次的id增加
    int                         m_lastId;//保存上一次的id
    int                         m_id;//创建指令行的id,也为按钮id
    int                         m_count;//记录当前的指令行数目
    const int                   m_vSpacing;//控件间垂直间距
    bool                        m_isRecount;//指令行按钮的id是否重新计数
    QVBoxLayout                 *m_vLayout;//滚动区域的垂直布局
    QMap<int,stuCmdCtrl>        m_orderMap;//保存指令控件,键-id,值-id对应的指令和按钮
};
#endif // INSTRUCTIONEDITDIALOG_H

instructioneditdialog.cpp

#include "instructioneditdialog.h"
#include "ui_instructioneditdialog.h"

InstructionEditDialog::InstructionEditDialog(QWidget *parent) :
    QDialog(parent),m_vSpacing(5),
    ui(new Ui::InstructionEditDialog)
{
    ui->setupUi(this);

    m_id = 0;
    m_count = 0;
    m_lastId = 0;
    m_isRecount = false;
    setVBlayout();
    createCommandLine();
    setWindowFlag(Qt::FramelessWindowHint);
    setAttribute(Qt::WA_TranslucentBackground);
}

InstructionEditDialog::~InstructionEditDialog()
{
    delete ui;
}

void InstructionEditDialog::setVBlayout()
{
    QWidget *widget = ui->scrollAreaWidgetContents;
    m_vLayout = new QVBoxLayout(widget);
    m_vLayout->setSpacing(m_vSpacing);
    m_vLayout->setContentsMargins(5,5,5,5);
}

void InstructionEditDialog::adjustLayoutHeight(int num)
{
    int height = num * 30 + (num + 1) * m_vSpacing;//30为每行控件的高度
    ui->scrollAreaWidgetContents->setFixedHeight(height);
}

void InstructionEditDialog::setPushBtnStyle(DeleteAddBtn *delBtn)
{
    QString strStyle;
    strStyle = "DeleteAddBtn{background-color:#040f60;color:#FFFFFF;"
               "font-size: 18px;font-family: Microsoft YaHei;}"
               "DeleteAddBtn:pressed{background-color:#071fbd;}";
    delBtn->setStyleSheet(strStyle);
}

void InstructionEditDialog::createCommandLine()
{
    ++m_count;
    if (m_deletedId.size() != 0) {
        m_id = m_deletedId.front();//first()
        m_deletedId.removeFirst();
        if (m_deletedId.count() == 0) {
            m_isRecount = true;
        }
    }else {
        if (m_isRecount) {
            m_id = m_lastId;
        }
        ++m_id;
        m_lastId = m_id;
    }
    m_orderForm = new SpecificOrderForm(ui->scrollAreaWidgetContents);
    m_pushBtn = new DeleteAddBtn(m_id,ui->scrollAreaWidgetContents);
    m_pushBtn->setText(QStringLiteral("添加"));
    setPushBtnStyle(m_pushBtn);
    connect(m_pushBtn,&DeleteAddBtn::sigAddConstructionCtrl,this,&InstructionEditDialog::createCommandLine);
    connect(m_pushBtn,&DeleteAddBtn::sigDelConstructionCtrl,this,&InstructionEditDialog::onDelConstructionCtrl);
    QHBoxLayout *layout = new QHBoxLayout;
    layout->addWidget(m_orderForm);
    layout->addWidget(m_pushBtn);
    m_vLayout->addLayout(layout);
    adjustLayoutHeight(m_count);

    stuCmdCtrl tempOrder;
    tempOrder.order = m_orderForm;
    tempOrder.btn = m_pushBtn;
    m_orderMap.insert(m_id,tempOrder);
}

void InstructionEditDialog::on_confirmBtn_clicked()
{
    QString strName = ui->namelineEdit->text();

    QList<stuSchoolSituation> sidSceneList;
    QMap<int,stuCmdCtrl>::iterator it;
    for (it = m_orderMap.begin() ; it != m_orderMap.end() ; ++it) {
        stuCmdCtrl tempCtrl = it.value();
        stuSchoolSituation tempSidMap = tempCtrl.order->getOrderChoosedText();
        sidSceneList.append(tempSidMap);
    }
    emit sigNameInstructionSet(strName,sidSceneList);

    accept();
}

void InstructionEditDialog::on_cancelBtn_clicked()
{
    ui->namelineEdit->clear();
    reject();
}

void InstructionEditDialog::onDelConstructionCtrl(int &id)
{
    if (m_deletedId.size() == 0) {
        m_isRecount = false;
    }
    QMap<int,stuCmdCtrl>::iterator it;
    for (it = m_orderMap.begin() ; it != m_orderMap.end() ; ++it) {
        if (id == it.key()) {
            m_deletedId.append(id);//删除后添加会出现id已被释放
            stuCmdCtrl tempCtrl;
            tempCtrl = it.value();
            delete tempCtrl.order;
            delete tempCtrl.btn;
            m_orderMap.erase(it);
            break;
        }
    }

    --m_count;
    adjustLayoutHeight(m_count);
}


instructioneditdialog.ui
在这里插入图片描述
specificorderform.ui
在这里插入图片描述
下面是样式文件:

/*学生情况编辑框背景*/
QWidget#SpecificOrderForm
{
	background-color:transparent;
	border:none;
}

/*指令行指令标签*/
QWidget#SpecificOrderForm>QLabel#label,QLabel#label_2,QLabel#label_3
{
	font-size: 18px;
	font-family: Microsoft YaHei;
	font-weight: 400;
	color: #FFFFFF;
}

/*班级和学生列表*/
QWidget#SpecificOrderForm>QComboBox#classComboBox,QComboBox#studentComboBox
{
	background-color: #121650;
	border:2px solid #0b54f0;
	font-size: 14px;
	font-family: Microsoft YaHei;
	font-weight: 400;
	color: #FFFFFF;
}

/*下拉列表框*/
QWidget#SpecificOrderForm>QComboBox QAbstractItemView
{
	background-color:#55557f;
	outline: 1px solid #ffaa7f;   /*选定项的虚框*/
	selection-background-color:#121650;
	color:#FFFFFF; 
}

/*下拉列表想的高度*/
QWidget#SpecificOrderForm>QComboBox QAbstractItemView::item
{
	height: 20px;
}

/*选中项*/
QWidget#SpecificOrderForm>QComboBox QAbstractItemView::item:selected
{
	background-color:#3c3cb6;
}

/*指令编辑框*/
QDialog#InstructionEditDialog>QWidget#widget
{
	background-color:#062977;
	border:2px solid #0b54f0;
}

/*按钮名称标签*/
QWidget#widget>QLabel#label
{
	font-size: 18px;
	font-family: Microsoft YaHei;
	font-weight: 400;
	color: #FFFFFF;
}

/*按钮名称*/
QWidget#widget>QLineEdit#namelineEdit
{
	background-color:transparent;
	border-radius:2px;
	border:2px solid #0b54f0;
	font-size: 16px;
	font-family: Microsoft YaHei;
	font-weight: 400;
	color: #FFFFFF;
}

/*滚动区域*/
QWidget#widget>QScrollArea#scrollArea
{
	border:none;
	background-color:transparent;
}

/*滚动区域的垂直滚动条的主体,滑道*/
QWidget#widget>QScrollArea#scrollArea QScrollBar:vertical
{
	width: 10px;/*滚动条宽度*/
	background-color: transparent;
	border-radius: 5px;
	margin:0px,0px,0px,0px;
	padding-top:0px;/*上、下箭头预留位置*/
	padding-bottom:0px;	
	border:none;
}

/*上箭头背景*/
QWidget#widget>QScrollArea#scrollArea QScrollBar::add-line:vertical
{
	background-color:transparent;
}

/*下箭头背景*/
QWidget#widget>QScrollArea#scrollArea QScrollBar::sub-line:vertical
{
	background-color:transparent;
}

/*滑块下拉后,滑块上面的背景*/
QWidget#widget>QScrollArea#scrollArea QScrollBar::add-page:vertical
{
	background-color:transparent;
}

/*滑块上拉后,滑块下面的背景*/
QWidget#widget>QScrollArea#scrollArea QScrollBar::sub-page:vertical
{
	background-color:transparent;
}

/*滚动区域的滚动条的滑块*/
QWidget#widget>QScrollArea#scrollArea QScrollBar::handle:vertical
{
	background-color: #5FC6DD;
	opacity: 0.5;
	border-radius: 5px;
	width:10px;
	min-height:20;
}

/*鼠标滑过滚动条*/
QWidget#widget>QScrollArea#scrollArea QScrollBar::handle:vertical:hover
{
	background-color: #00FBFF;
	opacity: 0.5;
	border-radius: 5px;
}

/*滚动区域窗口*/
QScrollArea#scrollArea QWidget#scrollAreaWidgetContents
{
	background-color:transparent;
	border:none;
}

/*确定,取消按钮*/
QWidget#widget>QPushButton
{
	background-color:transparent;
	border: 1px solid #FFFFFF;
	border-radius: 6px;
	font-size: 14px;
	font-family: Microsoft YaHei;
	font-weight: 400;
	color: #FFFFFF;
}

/*点击确定,取消按钮*/
QWidget#widget>QPushButton:pressed
{
	background-color: #00FBFF;
	opacity: 0.9;
	border-radius: 6px;
	font-size: 14px;
	font-family: Microsoft YaHei;
	font-weight: 400;
	color: #000337;
}

以上便是完整的代码。其中需要记录一下便是,当按钮被点击后,发送删除信号,来删除包含滋生在内的控件,因为是在鼠标点击事件中发送的删除控件信号,槽函数接收到信号删除控件之后,其中包含发送删除信号的按钮,然后继续返回到被删按钮的鼠标点击事件中,继续往下执行代码,这里将QPushButton::mousePressEvent(event);这句注释掉,因为按钮此时已被释放了,执行这句后程序会崩溃。当然这里这么解释可能不是很准确,但是确实和发送删除信号的按钮已经被删除有关。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肩上风骋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值