1483 字
7 分钟
MoneyProgress_win

起因#

前段时间分享了一个MoneyProgress的Mac软件,一直有人在论坛发帖问有没有win版的,恰好最近在看Qt,于是就有了这个项目.

写这个贴子的目的是为了记录一下开发过程,以及遇到的问题.

以后可以拿它做参考,也可以给有需要的人提供一些帮助.

MAC版的项目地址: MoneyProgress WIN版的项目地址: MoneyProgress_win

程序很大程度参考了原作者的UI设计,这里再次感谢原作者.

开发环境#

  • Windows 10 20H2(这个不是很重要)
  • Qt 5.15 with Mingw(这个很重要)

开发过程#

这块看我的commit记录就行了,虽然有点乱,但是基本上都是有用的.

这里只记录一些比较重要的问题,其他的问题可以参考Qt官方文档

多看文档,多看文档,多看文档.

问题1: 图片过大#

原作者的图片都是png格式,大小足足有3.27MB,分辨率为1024x1024,应该是自己画的吧.

刚开始导入图片设置为label设置样式表background-image: url(:/img/avatar.png);

是这样的:

20230411122233-2023-04-11

可以看到图片很大,很奇怪,

解决办法:

设置为border-image: url(:/img/avatar.png);

20230411122553-2023-04-11

这样它就会自动缩放了.可以通过设置labelwidthheight来控制图片的大小.

问题2: 无法获取到正确的屏幕分辨率#

这个问题是论坛上有人提出来的,我也遇到了.

原代码为:

// 这里省略了一些代码
// 获取屏幕分辨率高度
QApplication::desktop()->width();


实际获取的不一定就是当前屏幕的分辨率,有时候会获取到错误的值. 比如你有多块屏幕,它会获取到所有屏幕的分辨率的和.就很离谱. 这就会导致我们的程序在不同的屏幕上显示的效果不一样. 任务栏的弹窗就奇奇怪怪的.甚至看不到.

20230411123559-2023-04-11

解决办法:

// 这里省略了一些代码
QApplication::screenAt(QCursor().pos())->geometry().width()


意为获取鼠标所在屏幕的分辨率宽度.非常ok.

问题3: 文本无法正常更新#

问题代码:

因为我想实现每次点击任务栏图标都会弹出一个弹窗,显示当前的挣钱进度,所以我在MoneyProgress类中添加了一个IconMessage类的对象(一个小widget),并且在MoneyProgress类中添加了一个update函数,用来更新弹窗中的文本. 同时update还要负责更新主窗口中的文本.所以就有了如下代码


void MoneyProgress::update()
{
    // 这里省略了一些代码
    // 判断两个界面是否可见
    if (this->isVisible())
    {
        ui->labelMoneyNow->setText("您当前已经挣了"+QString::number(moneyday*progress/1000,'f',1)+"元;");
        ui->labelDay->setText("您一月工作" + QString::number(days) + "天;");
        ui->labelMoneyDay->setText("您一天能挣" + QString::number(moneyday, 'f', 1) + "元;");
        ui->labelHourDay->setText("您一天工作" + QString::number(hours, 'f', 1) + "小时;");
        ui->labelMoneySecond->setText("您一秒钟能挣" + QString::number(moneysecond, 'f', 6) + "元;");
    }
    if (iconmessage.isVisible())
    {
        iconmessage.update(progress, moneyday);
        qDebug() << progress;
    }
}

可以看到大致思路就是判断两个界面是否可见,如果可见就更新文本.但是任务栏那个小窗口的文本无法更新,调试发现了一个低级错误


update(); //错误的写法
iconmessage.show();
// update(); 把update()放在这里就可以更新了

确实很低级

问题4: QSettings 无效#

这个问题是在保存时间的时候遇到的,我想把设置保存到QSettings里面,但是发现无论怎么设置都无效. 在网上逛了半天,发现是因为QSettings只能在构造函数和析构函数中使用,不能在其他函数中使用.

问题代码:

//原本设计的是每次设置改变就保存一次,但是发现无效
void MoneyProgress::on_timeSleepdown_userTimeChanged(const QTime &time)
{
    // 这里省略了一些代码 settings 是一个QSettings对象,在.h文件中定义
    settings.setValue("sleepDown", sleepDown);
    
    // 保存设置

}

解决办法:

QSettings的保存设置放到析构函数中,这样就可以正常使用了.



MoneyProgress::~MoneyProgress()
{
    QSettings settings("MuYin", "MoneyProgress_win");
    // 保存设置
    settings.setValue("money", money);
    settings.setValue("days", days);
    settings.setValue("workUp", workUp);
    settings.setValue("workDown", workDown);
    settings.setValue("sleepUp", sleepUp);
    settings.setValue("sleepDown", sleepDown);
    // settings.setValue("geometry", this->saveGeometry());
    // settings.setValue("windowState", this->saveState());

    // 保存设置
    settings.sync();

    delete ui;
}


问题5: QSS样式表不会用#

因为我设置了标题栏隐藏

this->setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); // 隐藏标题栏

所以一直弄不出来borde的样式,最后发现改centralwidgetborder属性就可以了.

问题代码:

QWidget {
    background-color: rgb(255, 255, 255);
    border-width: 3px;
    border-color: rgba(255, 216, 58, 225);
    border-radius: 15px;
}

解决方法

QWidget {
    background-color: rgb(255, 255, 255);
    border-color: rgba(255, 216, 58, 225);
    border-radius: 15px;
}
QWidget#centralwidget {
    background-color: rgb(255, 255, 255);
    border: 3px solid #ffee6f;
    /* border-color: rgba(255, 216, 58, 225); */
}

css还是不太了解,回头需要好好学习一下.

问题6: 程序整体缩放问题#

引用网友的话:

Qt下高分屏的问题,几乎是一场灾难。希望未来 Qt 能有更好的解决方案。

解决方法: 添加 qt/etc/qt.conf文件,注意这是在qrc文件中的路径,它的完整路径是qrc:/qt/etc/qt.conf,网上说一定不要弄错 文件内容的意思为不使用QT的缩放功能,而是使用系统的缩放功能

[Platforms]
WindowsArguments = dpiawareness=0

具体看这个commit

问题7: QtCreator 无法Debug#

将build模式从release改为debug就可以了…

总结#

项目不大,时间也不算长,大概两三个晚上的样子,但是在这个过程中学到了很多东西,比如说QSettings的使用,QSS的使用,QTimer的使用,QApplication::screenAt(QCursor().pos())->geometry().width()的使用,以及一些小技巧,比如说QSettings只能在构造函数和析构函数中使用,QSSborder属性要写在centralwidget上,QTimerstart函数可以传入一个参数,表示延迟多久开始计时,QApplication::screenAt(QCursor().pos())->geometry().width()可以获取鼠标所在屏幕的分辨率宽度等等.

最后希望大家能够多多支持,如果有什么问题,欢迎指正,可以在评论区留言,我会尽快回复的.

MoneyProgress_win
https://f.undf.top/posts/post/code/cpp/moneyprogress_win/
作者
沐印
发布于
2023-04-11
许可协议
CC BY-NC-SA 4.0