QPainter+qss实现天气页面part1

目标:使用qt实现一个这样的页面

原型如下,是用html,css做的

这是参考网址:

(天气,天气预报查询,24小时,今天,明天,未来一周7天,10天,15天,40天查询_2345天气王 )

 小感想:qss比qpainter用得方便,但比较死板,有些功能不易实现。两者搭配使用,可能会有不一般的效果。

遇到了一些问题,经过许多尝试,最终几乎实现。

1. 实现小widget:

1.1

每个小widget都有两种状态:选中和被选中

所以我们可以使用两个样式表对不同的状态进行管理(但是两个样式表几乎一样)

void Widget::setSelected(bool s)
{
    selected=s;
    //两种情况下的样式表
    if(selected){

        QFile file(":/selected.qss");
        if(file.open(QFile::ReadOnly)){
            QString styleSheet=tr(file.readAll());
            ui->widget_2->setStyleSheet(styleSheet);
        }
    }
    else{
        QFile file(":/1.qss");
        if(file.open(QFile::ReadOnly)){
            QString styleSheet=tr(file.readAll());
            ui->widget_2->setStyleSheet(styleSheet);
        }
    }
}

1.2

再一个就是悬浮在图标上时图标被放大一些(一点点):

使用事件过滤器管理

 

bool Widget::eventFilter(QObject *watched, QEvent *event)
{
    if(watched==ui->pic){
        if(event->type()==QEvent::Leave){
            ui->pic->setFixedSize(QSize(60,60));
        }
        else if(event->type()==QEvent::Enter){
            ui->pic->setFixedSize(QSize(70,70));
        }
    }
    return QWidget::eventFilter(watched,event);
}

2.现在回到大widget中:

2.1

如何获取父widget下的子widget呢?

QList<T> QObject::findChildren(const QString &name = QString(), Qt::FindChildO ptions options = Qt::FindChildrenRecursively) const    

Qt官方给的例子:查询parentWidget下的所有QPushButton类
QList<QPushButton *> allPButtons = parentWidget.findChildren<QPushButton *>();    
    
这是我在这个程序中使用的:
allwidgets=findChildren<Widget *>();

2.2

对我来讲,难点是如何在把鼠标放上一个小widget时,它就被选中,然后显示对应的蓝色边框和下面的竖线。

(1)如何在把鼠标放上一个小widget时,它就被选中

(依然使用事件过滤器)

bool weatherbar::eventFilter(QObject *watched, QEvent *event)
{
    //进入时,会接收到。
    //最后进入的是哪个,哪个就被selected
    for(int i=0;i<allwidgets.count();++i)
    {
        Widget * a=allwidgets.at(i);
        if(watched==a){
            if(event->type()==QEvent::Enter){
                //qDebug()<<a<<"entered";
                allwidgets.at(num)->setSelected(false);
                num=i;
                a->setSelected(true);
                update();
            }
        }
    }
    return QWidget::eventFilter(watched,event);
}

(2)显示对应的蓝色边框和下面的竖线。

为了尽量和原图一致,我使用了重绘事件。 

画了5条线和4段小圆弧,思路简单,操作有点麻烦。 

 

void weatherbar::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.save();
    painter.translate(0,ui->widget->y()+ui->widget->height());

    QPen pen;
    pen.setWidth(6);
    pen.setColor(QColor(227, 240, 255));
    //pen.setJoinStyle(Qt::RoundJoin);
    painter.setPen(pen);

    QPointF point0,point5;
    QPointF point1,point2,point3,point4;
    Widget * wid=allwidgets.at(num);
    int x=wid->x();
    int w=wid->width();
    int h=wid->height();
    point0=QPointF(0,0);
    point5=QPointF(width(),0);
    point1=QPointF(x,0);
    point2=QPointF(x,-h);
    point3=QPointF(x+w,-h);
    point4=QPointF(x+w,0);

    //填充浅蓝色背景
    painter.fillRect(x,-h,w,h,QColor(247, 252, 255));
    //painter.drawPolyline(points,6);

    qreal radius=30;//把它当成宽和高
    QRect r1(point1.x()-radius,point1.y()-radius,radius,radius);
    QRect r2(point2.x(),point2.y(),radius,radius);
    QRect r3(point3.x()-radius,point3.y(),radius,radius);
    QRect r4(point4.x(),point4.y()-radius,radius,radius);

    //圆角的实现
    painter.drawArc(r1,270*16,90*16);
    painter.drawArc(r2,90*16,90*16);
    painter.drawArc(r3,0*16,90*16);
    painter.drawArc(r4,180*16,90*16);
    //画线
    painter.drawLine(QPointF(0,0),QPointF(x-radius/2,0));
    painter.drawLine(QPointF(x,-radius/2),QPointF(x,-(h-radius/2)));
    painter.drawLine(QPointF(x+radius/2,-h),QPointF(x+w-radius/2,-h));
    painter.drawLine(QPointF(x+w,-h+radius/2),QPointF(x+w,-radius/2));
    painter.drawLine(QPointF(x+w+radius/2,0),QPointF(width(),0));
    painter.restore();
    QWidget::paintEvent(event);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

lpl还在学习的路上

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

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

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

打赏作者

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

抵扣说明:

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

余额充值