https://github.com/howarder3/ironman2021_PyQt5_photoshop/tree/main/day28_final_project_day1
我们接下来的讨论,会基於读者已经先读过我 day5 文章 的架构下去进行程序设计
如果还不清楚我程序设计的逻辑 (UI.py、controller.py、start.py 分别在干麻)
建议先阅读 day5 文章後再来阅读此文。
https://www.wongwonggoods.com/python/pyqt5-5/
虽然原本我有想直接拿 Day17 的内容继续改,
後来觉得架构上还不够漂亮,最後决定乾脆直接砍掉重练比较快哈哈哈。
这次我设计的 final project UI 初版长这样
欸等等先别吐血啊!!! 这 UI 不是一天搞出来的啊!!
UI 就请大家自己慢慢刻哈哈哈哈哈!!!
(你说突然这也突然跳太高阶了吧?!
其实只是设定一些颜色而已XD,之前因为这个相对简单就没特别介绍)
如果还有机会的话有空在介绍,不过这边的内容多半是用於排版,
所以也难能以单一例子举出 demo 在干嘛,
总之可以自己玩玩看 Layouts 这一块,
先「拉一个 Layout」,再把「要排版的元件丢进去」,就对自动对整齐了!
使用的应该是类似 css 语法? 我不确定XD
总之有兴趣可以直接参考下面的延伸阅读进行修改,
设定位置在 Qt desinger 的这边
延伸阅读:给想研究更多怎麽设定颜色的人,请参考 Qt Style Sheets Examples
Qlabel 就是一个我们可以输入图片的地方,
透过右边的「...」,选择一张我们要的图片,就可以直接把 LOGO 嵌入 UI 中了。
一样,这程序只有介面 (视觉上的呈现),没有任何互动功能
python UI.py
赞到不行XDDDD (自己讲
这次的 final project 真的内容会做太多,如果没有好好规划一下架构,
很有可能写出来的东西会一团乱XDDD
所以我们要先趁今天来规划,明天再来慢慢把功能实现
依照 day5 的设计,我们至少也会有
而 UI 因为我们在 Qtdesigner 已经设计得够复杂了,也不太需要另外写程序,
所以基本上在经由 pyuic 的转换後,就已经完成了 UI.py
pyuic5 -x day28.ui -o UI.py
controller 是我们这边要讨论的重点,在我们的 photoshop 後端逻辑里面,
我之前在 day17 实作的最终版是把「图像+图像变化方法」写在同一个 class 当中,
我们如果继续让我们的「变化方法增加」,不适不能这样实作,
但最终我们会有一个超级巨大的 class 共同实作 「图像+图像变化方法」,
於是我决定把「变化方法」拆出去独立一个 class,
使得「图像」与「变化方法」分开成两套独立机制,而能互向协助。
这也符合 design pattern 的 Interface Segregation Principle(ISP) 介面隔离原则
以游戏来说,我们也可以举例:
我们大可以把一个角色的所有「属性、装备、技能」全部都包在这个角色当中,
但如果另外一个玩家也玩了同一个职业,我们何必把技能「整个复制进去另外一个角色当中呢?
」
於是我们可以把「技能」这个介面分离出去,让有需要的类别再去呼叫这个介面即可。
因此,这时候就能透过这样的拆分方式,把我们实作的弹性与扩充功能的弹性提升。
套用 design pattern 前,基本上这个设计没什麽问题,
硬要说缺点只是维护职业技能时,「需要一个个角色去调整内部的技能
」
套用 design pattern 的 Interface Segregation Principle(ISP) 介面隔离原则後,
我们把技能独立出来维护,这样的好处就是我们可以调整一次职业技能,
所有的角色都能得到修正!
而这边我们也要做同样的事情,我们要把
「修改图片的方法」这个介面独立出来!
独立「图片本身」与「图片处理方法」,
另外因为滑鼠事件的资讯比较特别,需要从图片上获取,所以我们也另外独立出来处理
第一次设计这个系统的时候,就碰到一个最关键的问题,
「没有提早先想好架构就开始写,导致绕了很多弯路
」,
应该要先想好再下去写的问题就是,在这个系统里面,「什麽事情会是触发事件的 trigger?
」
如果我们不知道「什麽事件会被使用者触发
」,
「就不知道要从哪个点开始启动後续的修改
」,
我一开始就是疯狂地开始写功能XDD,然後没注意谁呼叫谁,
结果功能都有了,但是 trigger 位置写在错误的 class,
所以要重搞顺序XDD
所以在写系统时,我们需要特别注意,
我们箭头指的地方就是「会触发事件的 trigger
」,
凡经过此处的程序都是「一次修改的起点
」,引导我们进行往後的修改。
基本上我们设计的「修改图片」都有符合一些同样的原则,
我们可以使用「介面继承」的方式来实现,
为了达到这样的效果,我们需要 「import abc
」 这个 python 酷酷的 library,
细节的部分我会再另外写一篇文章,这边我们先直接实作。
注:冷知识(?) abc = the infrastructure for defining 「abstract base classes (ABCs)」 in Python
简单来说,就是「抽象的类别 (class)」定义
我们预计设计的架构如下,一共会有三层,底下会一层层介绍:
我们可以大致归纳我们全部的变化介面都会有两个基本的要素:
__init__
另外,我们强制这两个介面在继承後都必须被定义,
所以我们透过「@abc.abstractmethod」,定义这个抽象的方法 (未实作功能),
以及「return NotImplemented」,如果使用者继承介面後未定义这个函数,
会跳 「NotImplemented error」,强制跳错 (逼使用者一定要定义介面内容)。
import abc
class method_interface(abc.ABC):
@abc.abstractmethod
def __init__(self):
return NotImplemented
@abc.abstractmethod
def update_img(self):
return NotImplemented
我们会实作的「图像变化方法」,能够产生变化的方法大概有两种,
一种是滑条类,另一种是画笔类。
这两类在实作时,都会继承我们的介面大祖宗 (method_interface),
然後再分别基於滑条的特性与画笔的特性,实作各自的介面。
这所有的介面方法都属於「图片变化方法」,所以我们会强烈推荐用继承的方法撰写。
会比起一个个慢慢定义有更好的架构与维护性
(维护一个父类别,也许底下的所有子类别都能全部受惠到这次的更动。不用一个个慢慢改。)
最大的差别就是:
因此这两个方法我们要分开实作,实作细节一样我们明日再提,
今天光是讲大架构就已经够累了。
在看该方法是「滑条方法介面 slider_method_interface」或是「画笔方法介面 pen_method_interface」後,
我们就可以开始实作细部功能了,这部分的实作细节我们就明日在提吧。
(今天光是讲完大架构相信大家已经都累了XDDD)
这个是旧版,滑鼠那部分因为是新加的,目前还没更新上去,
不过相信上面已经说明得相当完整了,应该能大约类推出他在图形上会呈现的细节
★ 本文也同步发於我的个人网站(会有内容目录与显示各个小节,阅读起来更流畅):【PyQt5】Day 28 final project - 1 / 来搞一个自己的 photoshop 吧!UI 篇 + 纯程序架构篇 (结合 PyQt + OpenCV)
<<: 【Day32】[演算法]-内插搜寻法Interpolation Search
>>: 30天学会Python语言: Day 27-时间管理大师
前面讲了很多 Kotlin Exposed 框架使用的方式。 今天来讲点观念性的东西,谈谈 Expo...
事件种类 事件处理是由各个浏览器提供的功能,然後我们再去呼叫出来使用,所以随着浏览器版本的更新,一些...
APP 开发 组别 https://wolkesau.medium.com/app-开发-组别-49...
上一篇讲到SPA的缺点,Vue是用JvaScript载入後台的数据,并且动态产生元件,SEO只能抓取...
接下来後半段实作SQL. 这边使用的是MS SQL. 由於安全性原则, 先建立一个Security ...