qt tablewidget滚动、插入控件、跳转行等(有更新)

一、前言

记录、备忘、分享

二、环境

win10,qt5.7

三、正文

1.滚动(必看)

表格初始化加入

    //表格滚动部分实现函数:初始化函数+以下俩函数+ (QObject *obj, QEvent *event)
    if(push)tab->viewport()->installEventFilter(this);//对此对象安装事件过滤器
    if(push)tab->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);//设置滚动模式按照像素滑动,做表格滑动时使用

事件加入 

//滑动表格实现函数
bool sysmain::eventFilter(QObject *obj, QEvent *event)
{
    static int press_y   = 0;
    static int move_y    = -1;
    static int release_y = 0;
    static QDateTime pressDateTime;
    static QPropertyAnimation *animation = new QPropertyAnimation();
    //qDebug()<<obj->objectName()<<event->type();
    if("qt_scrollarea_viewport" != obj->objectName())
        return false;
    int scrollV_max = m_scrollBarV->maximum ();
    int scrollV_min = m_scrollBarV->minimum ();
    //根据鼠标的动作——按下、放开、拖动,执行相应的操作
    if(event->type() == QEvent::MouseButtonPress){
        //记录按下的时间、坐标
        pressDateTime = QDateTime::currentDateTime();
        move_y  = QCursor::pos().y();
        press_y = move_y;
        animation->stop();
    }
    else if(event->type() == QEvent::MouseButtonRelease){
        //鼠标放开,根据鼠标拖动的垂直距离和持续时间,设置窗口滚动快慢程度和距离
        if(animation->targetObject() != m_scrollBarV){
            animation->setTargetObject(m_scrollBarV);
            animation->setPropertyName("value");
        }
        move_y = -1;
        release_y = QCursor::pos().y();
        QObject *parent_obj = obj->parent();
        if(parent_obj != 0 || parent_obj->inherits("QAbstractItemView"))
            QTimer::singleShot(150, (QAbstractItemView *)parent_obj, SLOT(clearSelection()));
        int endValue;
        int pageStep;
        if(release_y - press_y != 0 && qAbs(release_y - press_y) > 45){
            int mseconds = pressDateTime.msecsTo(QDateTime::currentDateTime());
            int limit = 440;
            pageStep = 240;//scrollBarV->pageStep();
            if(mseconds > limit)//滑动的时间大于某个值的时候,不再滚动(通过增加分母)
                mseconds = mseconds + (mseconds - limit) * 20;
            if(release_y - press_y > 0){
                endValue = m_scrollBarV->value()- pageStep * (200.0 / mseconds);//.0避免避免强制转换为整形
                if(scrollV_min > endValue)endValue = scrollV_min;
            }
            else if(release_y - press_y < 0){
                    endValue = m_scrollBarV->value() + pageStep * (200.0 / mseconds);
                    if(endValue > scrollV_max)
                        endValue = scrollV_max;
            }
            if(mseconds > limit)mseconds = 0;//滑动的时间大于某个值的时候,滚动距离变小,减小滑动的时间
            animation->setDuration(mseconds+550);
            animation->setEndValue(endValue);
            animation->setEasingCurve(QEasingCurve::OutQuad);
            animation->start();
            return true;
        }
    }
    else if(event->type() == QEvent::MouseMove && move_y >= 0){
        //窗口跟着鼠标移动
        int move_distance = QCursor::pos().y() - move_y;
        int endValue = m_scrollBarV->value() - move_distance;
        if(scrollV_min > endValue)endValue = scrollV_min;
        if(endValue > scrollV_max)endValue = scrollV_max;
        m_scrollBarV->setValue(endValue);
        move_y = QCursor::pos().y();
    }
    return false;
}

20220817更新,遇到表格在顶部,然后鼠标拖拽到表格顶部y坐标以上,表格瞬间滑倒最底下,反之一样,会滑倒最顶上,影响使用效果,再有就是linux下兼容性问题,更新eventfilter如下

//滑动表格实现函数
bool wurenJKGL_Terminal::eventFilter(QObject *obj, QEvent *event)
{
    static signed int press_y   = 0;
    static signed int move_y    = -1;
    static signed int release_y = 0;
    static QDateTime pressDateTime;
    static QPropertyAnimation *animation = new QPropertyAnimation();
//    qDebug()<<obj->objectName()<<event->type();
    if("qt_scrollarea_viewport" != obj->objectName())
        return false;
    int scrollV_max = m_scrollBarV->maximum ();//获取当前滚动控件的最大进度条值
    int scrollV_min = m_scrollBarV->minimum ();//获取当前滚动控件的最小进度条值,基本是0
#ifdef WINDOWS
    int global_y=QCursor::pos().y();//相对于正屏幕的y坐标,window下此方法即可获取
#else
    QMouseEvent *event1 = (QMouseEvent *)event;
    int global_y=event1->globalPos().y();//相对于正屏幕的y坐标,linux下用此方法获取
#endif
    //根据鼠标的动作——按下、放开、拖动,执行相应的操作
    if(event->type() == QEvent::MouseButtonPress){//记录按下的时间、坐标
        pressDateTime = QDateTime::currentDateTime();
        move_y  = global_y;
        press_y = move_y;
        animation->stop();
    }
    else if(event->type() == QEvent::MouseButtonRelease){//鼠标放开,根据鼠标拖动的垂直距离和持续时间,设置窗口滚动快慢程度和距离
        if(animation->targetObject() != m_scrollBarV){
            animation->setTargetObject(m_scrollBarV);
            animation->setPropertyName("value");
        }
        move_y = -1;
        release_y = global_y;
        QObject *parent_obj = obj->parent();
        if(parent_obj != 0 || parent_obj->inherits("QAbstractItemView"))
            QTimer::singleShot(150, (QAbstractItemView *)parent_obj, SLOT(clearSelection()));
        int endValue;
        int pageStep;
        if(release_y - press_y != 0 && qAbs(release_y - press_y) > 45){
            int mseconds = pressDateTime.msecsTo(QDateTime::currentDateTime());
            int limit = 440;
            pageStep = 240;//scrollBarV->pageStep();
            if(mseconds > limit)//滑动的时间大于某个值的时候,不再滚动(通过增加分母)
                mseconds = mseconds + (mseconds - limit) * 20;
            if(release_y - press_y > 0){
                endValue = m_scrollBarV->value()- pageStep * (200.0 / mseconds);//.0避免避免强制转换为整形
                if(scrollV_min > endValue)endValue = scrollV_min;
            }
            else if(release_y - press_y < 0){
                    endValue = m_scrollBarV->value() + pageStep * (200.0 / mseconds);
                    if(endValue > scrollV_max)
                        endValue = scrollV_max;
            }
            if(mseconds > limit)mseconds = 0;//滑动的时间大于某个值的时候,滚动距离变小,减小滑动的时间
            animation->setDuration(mseconds+550);
            animation->setEndValue(endValue);
            animation->setEasingCurve(QEasingCurve::OutQuad);
            animation->start();
            return true;
        }
    }
    else if(event->type() == QEvent::MouseMove && move_y >= 0){//窗口跟着鼠标移动
        int move_distance = global_y - move_y;
        int endValue = m_scrollBarV->value() - move_distance;
        if(scrollV_min > endValue)endValue = scrollV_min;
        if(endValue > scrollV_max)endValue = scrollV_max;
        m_scrollBarV->setValue(endValue);
        move_y = global_y;
    }
    return false;
}

重点:表格控件的属性设置中,一定把第一个框选去掉,否则就会出现上面说的现象。

 再有就是有个新方法,不用增加这么多函数和eventfilter,在初始化加入下面这句即可

    QScroller::grabGesture(ui->tableWidget_signal_fault, QScroller::LeftMouseButtonGesture);//触摸屏滑动
    QScroller::grabGesture(ui->tableWidget_function, QScroller::LeftMouseButtonGesture);//触摸屏滑动
    QScroller::grabGesture(ui->tableWidget_repair, QScroller::LeftMouseButtonGesture);//触摸屏滑动

缺点是表格会划过头,拖拽住移动的话,表格在刷新,会导致y坐标异常,此方法适用于不动态刷新的界面。

更新结束。


头文件加入

protected:
    bool eventFilter(QObject *obj, QEvent *event);
private:
    QScrollBar *m_scrollBarV;//表格滚动实现

 qss加入(选择性加入)(可以不加)


QTextEdit{/*设置常规*/
color: rgb(255, 255, 255);
	border-image: url(:/PIC/icon/透明.png);
}
QScrollBar:vertical {/*设置滚动条背景*/
      border: none;
 	  background-color: rgb(42,63,22);
      width: 3px;
  }
 QScrollBar::handle:vertical {/*设置滑动条*/
	 border: none;
     border-radius:2px;
      background: rgb(120, 120, 120);
  }
QScrollBar::sub-line:vertical {
      border: none;
      height: 0px;
      subcontrol-position: top;
      subcontrol-origin: margin;
  }
QScrollBar::add-line:vertical {
      border: none;
      height: 0px;
      subcontrol-position: bottom;
      subcontrol-origin: margin;
  }
  QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical {
	border:none;
      width: 0px;
      height: 0px;
  }
  QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
      background: none;
  }

2.插入控件(可以不看)

以用户信息显示为例,表格初始化省略

//更新用户信息
void sysmain::refuse_tableWidget_page5_user(QTableWidget *TableWidget)
{
    Data_user.usernamelist.clear();//清空用户账号
    Data_user.userpswdlist.clear();//清空用户密码
    Data_user.userroot.clear();//清空用户权限
    Data_user.usernote.clear();//清空用户备注
    QSqlQuery qry(db);
    if(qry.exec("select * from Sys_user")){
          for(int i=0;qry.next()&&i<1000;i++){
              Data_user.usernamelist.append(qry.value(0).toString());//赋值用户账号
              Data_user.userpswdlist.append(qry.value(1).toString());//赋值用户密码
              Data_user.userroot.append(qry.value(2).toBool());//赋值用户权限
              Data_user.usernote.append(qry.value(3).toString());//赋值用户备注
          }
    }
    TableWidget->clearContents();//清空内容
    TableWidget->setRowCount(Data_user.usernamelist.size());//设置表格行数
    //删除上次表格的复选框控件
    QList<QCheckBox*> checkList = TableWidget->findChildren<QCheckBox*>();
    for(int i=0;i<checkList.size();i++)delete checkList[i];
    //删除上次表格的按键控件
    QList<QPushButton*> btnList = TableWidget->findChildren<QPushButton*>();
    for(int i=0;i<btnList.size();i++)delete btnList[i];
    for(int i=0;i<Data_user.usernamelist.size();i++){  //刷新信号列表
        //表格插入复选框
        QCheckBox *lineid=new QCheckBox;
        lineid->setObjectName(tr("QCheckBox_user_%1").arg(i+1));
        TableWidget->setCellWidget(i,0,lineid);//插入按键到表格指定行列
        lineid->setText(QString("%1").arg(i+1,2,10,QChar('0')));//设置文本
        lineid->setStyleSheet(QCheckBoxstyle);//设置风格
        lineid->setFont(QFont("隶书", 12, QFont::Bold));//设置文字
        lineid->setAutoExclusive(true);//设置只有一个复选框可以选择,其他的自动失效
        TableWidget->setItem(i,1,new QTableWidgetItem(Data_user.usernamelist.at(i)));//更新账号
        TableWidget->item(i,1)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);//数据居中
        TableWidget->setItem(i,2,new QTableWidgetItem(Data_user.userpswdlist.at(i)));//更新密码
        TableWidget->item(i,2)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);//数据居中
        if(Data_user.userroot.at(i))
            TableWidget->setItem(i,3,new QTableWidgetItem("是"));//更新管理员
        else
            TableWidget->setItem(i,3,new QTableWidgetItem("否"));//更新管理员
        TableWidget->item(i,3)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);//数据居中
        QPushButton *aaa=new QPushButton;
        aaa->setObjectName(tr("btn_page5_usertable_1_%1").arg(i+1));
        TableWidget->setCellWidget(i,4,aaa);//插入按键到表格指定行列
        aaa->setText("备注信息");//设置文本
        QString styles=btnwhite+btnstyle;styles.replace("12pt","16pt");
        aaa->setStyleSheet(styles);//设置风格,加大字号
        connect(aaa,&QPushButton::clicked,[=](){//绑定按键点击回调槽函数
            MessageBox5_3 * box = new MessageBox5_3();
            box->show();
            box->setAttribute(Qt::WA_DeleteOnClose);//若是关闭界面,则彻底释放资源
            connect(this,SIGNAL(sendtext(QString,QString,int)),box,SLOT(receivetext(QString,QString,int)));
            emit sendtext(Data_user.usernote.at(i),"",0);
        });
        TableWidget->setRowHeight(i,50);//设置行高
    }
//    TableWidget->resizeRowsToContents();//根据单元格内容自动换行
}
//人员删除
void sysmain::on_btn_page5_user_delete_clicked()
{
    int checkid=0;
    QList<QCheckBox*> checkList = ui->tableWidget_page5_user->findChildren<QCheckBox*>();
    for(int i=0;i<checkList.size();i++){//遍历寻找是否有选中
        if(checkList.at(i)->isChecked()){//如果找到选中,则跳出循环
            checkid=checkList.at(i)->objectName().replace("QCheckBox_user_","").toInt();//替换控件名称转换为表格所在的行
            break;//跳出寻找
        }
    }
    if(checkid>0){//有选中的行
        if(Data_user.usernamelist.at(checkid-1)==Data_user.now_username){
            MessageBox1 * box = new MessageBox1();
            box->show();
            box->setAttribute(Qt::WA_DeleteOnClose);//若是关闭界面,则彻底释放资源
            connect(this,SIGNAL(sendtext(QString)),box,SLOT(receivetext(QString)));
            emit sendtext("不可以删除当前登录用户!");
        }
        else{
            MessageBox2 * box = new MessageBox2();
            box->show();
            box->setAttribute(Qt::WA_DeleteOnClose);//若是关闭界面,则彻底释放资源
            connect(this,SIGNAL(sendtext(QString)),box,SLOT(receivetext(QString)));
            emit sendtext(tr("提示!\r\n是否确认删除用户:%1").arg(Data_user.usernamelist.at(checkid-1)));
            if(box->exec()){//确认选择
                QSqlQuery qry(db);
                qry.exec(tr("delete from Sys_user where name = '%1'").arg(Data_user.usernamelist.at(checkid-1)));
                qry.prepare("vacuum");//删除成功之后释放内存碎片
                qry.exec();
                refuse_tableWidget_page5_user(ui->tableWidget_page5_user);//更新全部用户信息
                MessageBox1 * box = new MessageBox1();
                box->show();
                box->setAttribute(Qt::WA_DeleteOnClose);//若是关闭界面,则彻底释放资源
                connect(this,SIGNAL(sendtext(QString)),box,SLOT(receivetext(QString)));
                emit sendtext("删除用户成功!");
            }
        }
    }
    else{
        MessageBox1 * box = new MessageBox1();
        box->show();
        box->setAttribute(Qt::WA_DeleteOnClose);//若是关闭界面,则彻底释放资源
        connect(this,SIGNAL(sendtext(QString)),box,SLOT(receivetext(QString)));
        emit sendtext("请选择要删除的用户列表序号!");
    }
}
//人员修改
void sysmain::on_btn_page5_user_change_clicked()
{
    int checkid=0;
    QList<QCheckBox*> checkList = ui->tableWidget_page5_user->findChildren<QCheckBox*>();
    for(int i=0;i<checkList.size();i++){//遍历寻找是否有选中
        if(checkList.at(i)->isChecked()){//如果找到选中,则跳出循环
            checkid=checkList.at(i)->objectName().replace("QCheckBox_user_","").toInt();//替换控件名称转换为表格所在的行
            break;//跳出寻找
        }
    }
    if(checkid>0){//有选中的行
        MessageBox7 * box = new MessageBox7();
        box->show();
        box->setAttribute(Qt::WA_DeleteOnClose);//若是关闭界面,则彻底释放资源
        connect(this,SIGNAL(sendtext(QString,QString,bool,QString,QStringList)),box,SLOT(receivetext(QString,QString,bool,QString,QStringList)));
        QString change_username=Data_user.usernamelist.at(checkid-1);//赋值选中用户名称
        QString change_userpassword=Data_user.userpswdlist.at(checkid-1);//赋值选中用户密码
        bool change_userroot=Data_user.userroot.at(checkid-1);//赋值选中用户权限
        QString change_usernote=Data_user.usernote.at(checkid-1);//赋值选中用户备注
        emit sendtext(change_username,change_userpassword,change_userroot,change_usernote,Data_user.usernamelist);
        connect(box,&MessageBox7::sendtext,[=](QString res1,QString res2,bool res3,QString res4){
//            qDebug()<<res1<<res2<<res3<<res4;
            //判断修改的用户是否为当前用户
            int err_flag=0;//错误编号
            if(change_username==Data_user.now_username){
                if(res3==0){
                    res3=1;
                    err_flag=1;//降低本身权限,可能导致没有账号能进入管理员系统
                }
                //赋值登录信息到当前用户信息缓存
                Data_user.now_username=res1;//当前用户
                Data_user.now_password=res2;//当前密码
                Data_user.now_root=res3;//赋值权限
                Data_user.now_noted=res4;//赋值备注
                //存储当前登录界面配置信息到数据库
                QSqlQuery qry(db);//数据库保存
                qry.exec(QString("UPDATE Sys_userlast set username='%1',userpassword='%2' where id = 1;").arg(res1).arg(res2));
                //刷新当前用户名称
                ui->lab_name->setText(Data_user.now_username);/后续设置label滚动,显示不全自动滚动显示全
            }
            QSqlQuery qry(db);//数据库保存
            qry.exec(QString("UPDATE Sys_user set name='%1',password='%2',root='%3' ,note='%4'where name = '%5';").arg(res1).arg(res2).arg(res3).arg(res4).arg(change_username));
            refuse_tableWidget_page5_user(ui->tableWidget_page5_user);//更新全部用户信息
            MessageBox1 * box = new MessageBox1();
            box->show();
            box->setAttribute(Qt::WA_DeleteOnClose);//若是关闭界面,则彻底释放资源
            connect(this,SIGNAL(sendtext(QString)),box,SLOT(receivetext(QString)));
            if(err_flag==1)
                emit sendtext("用户信息修改成功!\r\n(不可修改自身权限,已自动恢复)");
            else
                emit sendtext("用户信息修改成功!");
        });
    }
    else{
        MessageBox1 * box = new MessageBox1();
        box->show();
        box->setAttribute(Qt::WA_DeleteOnClose);//若是关闭界面,则彻底释放资源
        connect(this,SIGNAL(sendtext(QString)),box,SLOT(receivetext(QString)));
        emit sendtext("请选择要修改的用户列表序号!");
    }
}

3.跳转行,前提是现别开启滚动,等跳转完行之后,在执行4、5行代码,开启滚动效果,否则无法跳转行。(可以不看)

    TableWidget->setVerticalScrollMode(QAbstractItemView::ScrollMode::ScrollPerPixel);
    TableWidget->verticalScrollBar()->setSingleStep(2);
    TableWidget->verticalScrollBar()->setSliderPosition(show_line*30);//跳转行到指定位置
    TableWidget->viewport()->installEventFilter(this);//对此对象安装事件过滤器
    TableWidget->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);//设置滚动模式按照像素滑动,做表格滑动时使用

4. 多个表格切换(必看)

有多个表格都需要滚动效果是,之开启一个eventfilter和m_scrollBarV,就需要在初始化加入以下代码,进行界面切换时,使用哪一个表格滚动效果之前,加入对应的m_scrollBarV绑定。

    QPushButton *groupmenu[4]={ui->btn_ztjc,ui->btn_gzzd,ui->btn_gnpg,ui->btn_wxjy};
    for(int i=0;i<4;i++){
        connect(groupmenu[i],&QPushButton::clicked,[=](){//点击菜单栏按键
            for(int j=0;j<4;j++)groupmenu[j]->setChecked(false);
            groupmenu[i]->setChecked(true);
            m_menu=i;
            m_si_ft_information=false;//选择的信号或故障详细信息,true在详细信息界面内,false在列表信息界面内
            if(m_menu==0||m_menu==1)m_scrollBarV = ui->tableWidget_signal_fault->verticalScrollBar();//绑定表格滑动效果//信号和故障列表
            else if(m_menu==2)m_scrollBarV = ui->tableWidget_function->verticalScrollBar();//绑定表格滑动效果//功能列表
            else if(m_menu==3)m_scrollBarV = ui->tableWidget_repair->verticalScrollBar();//绑定表格滑动效果//维修建议列表
            update_Form();
        });//绑定槽点击按键进入更新界面函数
    }

四、结语

学而时习之,不亦说乎

  • 4
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

大桶矿泉水

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

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

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

打赏作者

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

抵扣说明:

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

余额充值