[PyQt5] 实现GitHub的CommitCalendar(贡献瓦片图)

Github的commit calendar记录了每天的贡献量。
commit
这次就实现一个这种样式的图表吧!使用PyQt5。

第一部分:

import datetime

from PyQt5.QtWidgets import QWidget
from PyQt5.QtGui import QPainter, QColor

from CommitCalendar.pyqt5._color import ColorScheme


class QCommitCalendar(QWidget):
    """ A Github Commit-Calendar like widget. """

    def __init__(self,
                 commit_data: dict,
                 block_size: int = 10,  # commit方块的大小
                 block_spacing: int = 3,  # commit方块的空隙
                 color_scheme=ColorScheme.Naive,  # 见第二部分
                 orientation: str = 'right',  # 图表的朝向,GitHub是朝右的,这里还可以朝左
                 # Inherit from QWidget.
                 parent=None, *args, **kwargs):
        super().__init__(parent, *args, **kwargs)
        self.commit_dict = commit_data
        self.block_size = block_size
        self.block_spacing = block_spacing
        self.color_scheme = color_scheme
        self.orientation = orientation

        self._today = datetime.date.today()
        self._weekday = datetime.datetime.now().weekday()  # 星期数下标,0开始
        self._painter = QPainter(self)

        self.setMinimumSize(250, 115)
        self.setMaximumWidth(725)
        self.setStyleSheet("background-color: white")

    def _calc_cols_nbr(self) -> int:
    	# 计算可以画出多少列
        return int(self.width() / (self.block_size + self.block_spacing) - 2)

    def _set_painter(self, color: str):
    	# 设置画笔
        self._painter.setPen(QColor(color))
        self._painter.setBrush(QColor(color))

    def _commit_color_map(self, date: str):
    	# 将不同的commit数对应不同的颜色,这里的标准自己拟定
        # Map commit number to color.
        commit = self.commit_dict.get(date)
        if commit is not None:
            commit = int(commit)
            if commit > 10:
                self._set_painter(self.color_scheme[3])
            elif commit > 5:
                self._set_painter(self.color_scheme[2])
            else:
                self._set_painter(self.color_scheme[1])
        else:
            self._set_painter(self.color_scheme[0])

    def paintEvent(self, paint_event):
        assert self.block_size >= 10
        assert self.block_spacing > 0
        assert self.orientation in ('right', 'left')

        # Begin painting...
        self._painter.begin(self)
        delta = 0  # 日期偏移
        cols = range(self._calc_cols_nbr())
        for col in cols:
            # Monday index is 0, and the first day of week is Sunday.
            # 周一的下标是0,而且一周的开始是周日
            # 这里绘制行时需分情况
            rows = range(self._weekday + 2) if col == 0 else range(7)
            for row in rows:
                if self.orientation == 'right':
                    x = self.width() - (self.block_size + self.block_spacing) * (col + 2)
                else:
                    x = (self.block_size + self.block_spacing) * (col + 1)
                y = (self.block_size + self.block_spacing) * (len(rows) - row)
                # Paint different color on.
                date = self._today - datetime.timedelta(days=delta)
                self._commit_color_map(str(date))
                delta += 1
                self._painter.drawRect(x, y, self.block_size, self.block_size)
        self._painter.end()

第二部分

这里配置颜色表,从左到右依次由浅入深。

class ColorScheme:
    # hex color from less to more (0 ~ 4)
    Naive = ('#ebedf0', '#c6e48b', '#7bc96f', '#239a3b', '#196127')  # GitHub原配色
    Velvet= ('#ebedf0', '#e1eec3', '#e6bea1', '#ea8e7f', '#f05053')  # 桃阳红配色

测试

这里使用json数据来代表每日的commit数:

{
  "2019-07-28": "2",
  "2019-07-29": "5",
  "2019-07-30": "8",
  "2019-07-31": "2",
  "2019-08-01": "1",
  "2019-08-08": "2",
  "2019-08-20": "12",
  "2019-08-25": "5",
  "2019-08-28": "2",
  "2019-08-31": "7",
  "2019-09-01": "2",
  "2019-09-18": "2",
  "2019-09-28": "5",
  "2019-09-30": "2",
  "2019-10-28": "1",
  "2019-11-28": "2",
  "2019-12-21": "12",
  "2019-12-28": "2",
  "2020-02-14": "4",
  "2020-02-26": "15"
}

测试脚本:

import sys
import cgitb
import json

from PyQt5.QtWidgets import QApplication
from CommitCalendar.pyqt5 import QCommitCalendar, ColorScheme

cgitb.enable(format("text"))

if __name__ == '__main__':
    app = QApplication(sys.argv)
    f = open('test.json', 'r')
    cc = QCommitCalendar(json.load(f))
    f.close()
    cc.setWindowTitle('PyQt5 Demo')
    cc.show()
    sys.exit(app.exec_())

运行效果如下:
demo
还可以更改配色:
cc = QCommitCalendar(json.load(f), color_scheme=ColorScheme.VelvetSun)
other

总结

大体效果是实现了,但是还差周围的一些标签,这些也好说,此处就不进行展示了。唯一的缺陷时,这些方块不可交互,不能用鼠标点击获取详细信息。如果要这样做的话,可以使用QQGraphicsRectItem实现。新的一年,看看今年会有多少贡献吧!

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PyQt5模板是一种用于创建基于PyQt5形用户界面(GUI)应用程序的代码蓝本。它通常是一个工程文件或项目文件,带有先前编写好的代码和预定义的布局和功能。通过使用这些模板,开发人员可以快速启动项目开发而不必从头开始编写代码。 GitHub是一个非常受欢迎的代码托管平台,开发人员可以在上面共享、存储和合作管理他们的代码。在GitHub上,我们可以找到许多PyQt5模板,可以作为我们项目的起点。 这些模板通常包含了实现常见功能的代码片段,例如主窗口的创建、菜单栏、工具栏、状态栏的设计,以及其他常用的界面元素(如按钮、文本框等)。开发人员只需要基于这些模板进行修改和扩展,以满足他们具体项目的需求。 使用PyQt5模板可以帮助开发人员节省时间和精力。由于模板中已经提供了一些基本的功能和架构,开发人员可以集中精力在项目的核心逻辑上,而不必从零开始编写界面相关的代码。 在GitHub上,有许多开源的PyQt5模板可供选择,开发人员可以根据项目需求,浏览并选择合适的模板。然后,他们可以克隆该模板的代码库到本地开发环境中,并对其进行自定义修改,以实现他们所需的具体功能和设计。 总之,PyQt5模板在GitHub上提供了一种便捷的方式,开发人员可以利用这些模板快速构建GUI应用程序,加快开发速度并提高效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值