一、前言
记录、备忘、分享
二、环境
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();
});//绑定槽点击按键进入更新界面函数
}
四、结语
学而时习之,不亦说乎