[ Qt串口助手上 ] : C++Qt编写串口助手+无边框窗口处理+Qt多线程接收 (上)界面设置

前言(界面编写)

有关于界面UI的设置,我没有使用qt默认的有边框的样式,而是选择了自定义的方式,也就是无边框样式,由于失去了标题栏,无法拖动窗口和最小化,最大化,关闭,因此需要重写qt相关的内置函数。由界面效果可以看到,展现的控件的边角都是有一定的弧度的,相比生硬的直角更加美观一些,本文主要介绍的是界面布局以及一些Qss样式表的内容,其他的在后面几篇文章中。

串口助手的专栏:Qt串口助手_rqtz的博客-CSDN博客

源码在评论区

ui界面效果展示

日间模式

夜间模式

无边框设置

//设置无边框
setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);    

在类的构造函数中添加后,显示出的窗口会失去边框,且无法拖动和其他操作,只能右键图标关闭程序。

重写内置函数,实现窗口拖动

窗口的拖动是在qt中的内置函数中实现的,这些函数是受保护的,因此,要实现窗口拖动的功能,需重写这些函数。

protected:
      void mouseMoveEvent(QMouseEvent *e) override;
      void mousePressEvent(QMouseEvent *e) override;
      void mouseReleaseEvent(QMouseEvent *e) override;

在类的头文件中添加上述函数,分别是鼠标移动事件鼠标按压事件鼠标释放事件

鼠标按压事件

void MainWindow::mousePressEvent(QMouseEvent *e)
{
    if(e->button() == Qt::LeftButton)
    {
        mouseflag = true;
        mousepose = e->globalPos();
        windowpose = this->geometry().topLeft();
    }
}

代码解释:

  • 首先是判断鼠标是左键按下,因为我们移动窗口的习惯通常是按左键。
  • mouseflag = true;  左键按下的标志位,后面会用到。
  • mousepose = e->globalPos(); 获取到当前的鼠标坐标,类型是QPoint.
  • windowpose = this->geometry().topLeft(); 获取当前窗口左上角的坐标,类型同样是QPoint。

鼠标移动事件

void MainWindow::mouseMoveEvent(QMouseEvent *e)
{
    if(mouseflag)
    {
        QPoint dis = e->globalPos()-mousepose;
        this->move(windowpose+dis);
    }
}

代码解释:

  • 首先是判断鼠标是左键按下的状态下,mouseflag为真时。
  • QPoint dis = e->globalPos()-mousepose;  当前的鼠标坐标相对于鼠标按压时的鼠标坐标mousepos的差值,该差值为距离坐标。
  • mousepose = e->globalPos(); 获取到当前的鼠标坐标,类型是QPoint.
  • this->move(windowpose+dis); 当前窗口this移动到的坐标位置,windowpose(移动前窗口位置坐标)+dis。

鼠标释放事件

void MainWindow::mouseReleaseEvent(QMouseEvent *e)
{
    if(e->button() == Qt::LeftButton)
        mouseflag = false;
}

代码解释:

当鼠标有按下到松开时,我们将mouseflag置为假,保证在只有左键按下时才进行移动

最终效果

重写事件过滤器函数,实现窗口控件悬停切换图片效果

最小化与最大化和关闭这些功能的实现是通过获取label控件的点击事件,通过添加事件过滤器的方法,

安装事件过滤器

由于label控件并没有点击事件,所以我们只能使用 setAttributeinstallEventFilter 来添加事件过滤器使其具有相关事件。

void MainWindow::sethoverevent()
{
    ui->close->setAttribute(Qt::WA_Hover,true);
    ui->close->installEventFilter(this);
    ui->little->setAttribute(Qt::WA_Hover,true);
    ui->little->installEventFilter(this);
    ui->large->setAttribute(Qt::WA_Hover,true);
    ui->large->installEventFilter(this);
    ui->switch_2->installEventFilter(this);
}

上述代码中的ui控件分别指的下面的label控件,本质是照片。

setAttribute(Qt::WA_Hover,true)  是指让label控件具有悬停事件

installEventFilter(this) 为控件安装事件过滤器,使其可以接受并处理所有的事件,包括悬停事件。

重写事件过滤器函数

在.h文件中添加

protected:
      bool eventFilter(QObject*obj,QEvent *e) override;

在.cpp函数中添加

bool MainWindow::eventFilter(QObject *obj, QEvent *e)
{
    if(e->type() == QEvent::HoverEnter)
    {
        emit hoverval(obj,obj->objectName());
        return  true;
    }
    else if(e->type() == QEvent::HoverLeave)
    {
        emit hoverval(obj,"mouseout");
        return true;
    }
}

其中

  • QObject *obj, QEvent *e :obj 表示一个当前控件的一个指针,可以通过访问objectname来获取他的名字,e表示当前事件的一个指针,可以通过type()来获取事件类型。
  • 信号singal : 当鼠标悬浮在控件上时,我们 发送信号  emit hoverval(obj,obj->objectName()); 当鼠标离开控件时,我们 发送信号  hoverval(obj,"mouseout")

绑定信号和槽

 connect(this,&MainWindow::hoverval,this,&MainWindow::hoveraction);

编写悬浮事件槽函数

void MainWindow::hoveraction(QObject *obj, QString name)
{
    if(name=="close") {
        ui->close->setPixmap(QPixmap(rclose).scaled(16,16));
    }
    else if (name=="little") {
        ui->little->setPixmap(QPixmap(rmostlittle).scaled(16,16));
    }
    else if (name=="large") {
        ui->large->setPixmap(QPixmap(rmostlarge).scaled(16,16));
    }

    else if (name=="mouseout") {
        ui->little->setPixmap(QPixmap(bmostlittle).scaled(16,16));
        ui->large->setPixmap(QPixmap(bmostlarge).scaled(16,16));
        ui->close->setPixmap(QPixmap(bclose).scaled(16,16));
    }
}

我们通过得到不同的控件名称,来去设置不同的图片,达到视觉效果。

最终效果

重写事件过滤器函数,实现窗口最大化,最小化和关闭

获取label的点击事件

在上述的evenfliter函数中添加   

else if(e->type() == QEvent::MouseButtonPress)
    {
        theammode_count++;
        emit clickval(obj,obj->objectName());
        return true;
    }

完整函数为

bool MainWindow::eventFilter(QObject *obj, QEvent *e)
{
    if(e->type() == QEvent::HoverEnter)
    {
        emit hoverval(obj,obj->objectName());
        return  true;
    }
    else if(e->type() == QEvent::HoverLeave)
    {
        emit hoverval(obj,"mouseout");
        return true;
    }
    else if(e->type() == QEvent::MouseButtonPress)
    {
        theammode_count++;
        emit clickval(obj,obj->objectName());
        return true;
    }

}

 绑定信号和槽

 connect(this,&MainWindow::hoverval,this,&MainWindow::clickaction);

编写点击事件槽函数

void MainWindow::clickaction(QObject *obj, QString name)
{
    if(name=="close") {
         this->close();
    }
    else if (name=="little") {
            this->showMinimized();
    }
    else if (name=="large") {
        static int num = 0;
        num++;
        if((num+1)%2==0)
           this->showFullScreen();
        else
            this->showNormal();
    }
  • 控件名称为close时: 调用close方法来关闭窗口
  • 控件名称为littel时: 调用showMinimized方法来最小化窗口
  • 控件名称为llarge时: 当点击次数和为奇数时,调用showFullScreen方法来最大化窗口,偶数时,调用showNormal方法还原窗口。

最终效果

最后夜间模式的实现方法,只需要获取控件的点击事件,在该函数中更新样式表即可。

重写paintevent事件,使窗口由四角的方形显示圆角形

void MainWindow::paintEvent(QPaintEvent *e)
{
    QBitmap bmp(this->size());
    bmp.fill();
    QPainter p(&bmp);
    p.setPen(Qt::NoPen);
    p.setBrush(Qt::black);
    p.drawRoundedRect(bmp.rect(),20,20);//像素为20的圆角
    setMask(bmp);
}

按钮圆角

这个是界面中的一个按钮的圆角设置的样式表,大家参考一下

QPushButton{
	font: 9pt "微软雅黑";
    color: #080808;
    background-color:#ffffff;
    border-color:#c3c3c3;
    border-radius: 14px;
    border-style: solid;
    border-width: 1px;
    padding: 4px;
}
QPushButton::hover {
background-color:rgb(224,238,249);
border-color: rgb(0,120,212);
}

注意:如果没有显示出来圆角,可能是你的圆角半径值border-radius过大或过小,结合border-width和padding多试试几个不同的值,直到有效果为止。

  • 8
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值