为了账号安全,请及时绑定邮箱和手机立即绑定

通过 PIL/Python 将元素添加到 OLED 显示而不擦除剩余元素

通过 PIL/Python 将元素添加到 OLED 显示而不擦除剩余元素

慕娘9325324 2023-10-05 16:27:05
我有一个 SH1106 显示器连接到我的 Raspberry Pi,我使用 luma.oled 控制它。我可以用不同的字体显示各种内容,这很棒。但是,我不知道如何在不刷新整个显示的情况下向当前显示的内容添加内容。我的代码是这样的:from os import systemimport serialfrom time import sleepfrom luma.core.interface.serial import i2cfrom luma.core.render import canvasfrom luma.oled.device import sh1106from PIL import ImageFont# config displaydevice = sh1106(i2c(port=1, address=0x3C), rotate=0)device.clear()FA_solid = ImageFont.truetype('/home/pi/Desktop/tests/fa-solid-900.ttf', 16)FA_regular = ImageFont.truetype('/home/pi/Desktop/tests/fa-regular-400.ttf', 16)text_large = ImageFont.truetype('/home/pi/Desktop/tests/coolvetica condensed rg.ttf', 48)text_small = ImageFont.truetype('/home/pi/Desktop/tests/coolvetica condensed rg.ttf', 16)# display thingsdef show_icon(code):    with canvas(device) as draw:        draw.text((112, 0), text=code, font=FA_solid, fill="white")        def large_text(content, paddingleft =0, paddingtop =0):    with canvas(device) as draw:        draw.text((0, 0), text=content, font=text_large, fill="white")        def small_text(content, paddingleft =0, paddingtop =0):    with canvas(device) as draw:        draw.text((0, 0), text=content, font=text_small, fill="white")show_icon("\uf124")sleep(2)large_text("Hi ;)")sleep(10)device.clear()这会在右上角显示一个来自 fontawesome 的图标,然后清除屏幕并显示 Hi。如何更改它以显示图标 + hi?理想情况下,我会在屏幕上有“区域”,我可以在其中更改图标区域,同时保持文本显示,反之亦然。谢谢!
查看完整描述

2 回答

?
慕容森

TA贡献1853条经验 获得超18个赞

我没有 SH1106 可供测试,也从未使用过该luma库,因此可能有一种更简单的方法可以完成您想要的操作。如果是这样,也许有人会好心地告诉我,我会删除这个答案。


background = Image.new("RGB", device.size, "white")

background.paste(frame.resize(size, resample=Image.LANCZOS), posn)

device.display(background.convert(device.mode))

所以,看来你可以创建一个PIL Image并将其发送到显示器上。第一行创建一个与整个显示器大小相同的空白白色画布,第二行将另一个画布粘贴PIL Image到指定位置的画布上,最后一行将图像发送到显示器。因此,您需要做的就是分别定义您的N “区域”并分别绘制它们(每个区域都是一个PIL Image),然后当您想要更新显示时,将您的N区域粘贴到您想要的位置并发送完整的图片到显示屏。


抱歉,我不能更准确,但我没有什么可以测试的。这是一个包含 3 个区域的小示例,可以单独绘制这些区域,然后在调用之前将其组装成一个整体device.display()


#!/usr/bin/env python3


from PIL import Image, ImageDraw


def UpdateDisplay(z1,z2,z3):

   """Pass in the three zones and they will be sent to the screen"""


   # Make a black canvas the size of the entire screen

   whole = Image.new("RGB", (128,64), (0,0,0))


   # Now paste in the 3 zones to form the whole

   whole.paste(z1, (2,2))        # zone1 at top-left

   whole.paste(z2, (66,2))       # zone2 at top-right

   whole.paste(z3, (2,34))       # zone3 across the bottom


   # I save the image here, but you would write it to the screen with "device.display()"

   whole.save('result.png')

   return


# Make zone1 dark grey and annotate it

z1 = Image.new("RGB", (60,30), (64,64,64))

z1draw = ImageDraw.Draw(z1)

z1draw.text((10,10),"Zone1")


# Make zone2 mid-grey and annotate it

z2 = Image.new("RGB", (60,30), (128,128,128))

z2draw = ImageDraw.Draw(z2)

z2draw.text((10,10),"Zone2")


# Make zone3 light grey and annotate it

z3 = Image.new("RGB", (124,28), (192,192,192))

z3draw = ImageDraw.Draw(z3)

z3draw.text((10,10),"Zone3")


# Blit all zones to display

UpdateDisplay(z1,z2,z3)


# Now change just zone 2 and update display

z2.paste("red", (0,0,z2.width,z2.height))

UpdateDisplay(z1,z2,z3)

这是原始显示:

https://img1.sycdn.imooc.com//651e739a0001b31001280061.jpg

更新 zone2 后再次出现:

https://img1.sycdn.imooc.com//651e73a7000126b201280063.jpg


查看完整回答
反对 回复 2023-10-05
?
潇潇雨雨

TA贡献1833条经验 获得超4个赞

好吧,我基本上明白了:


from luma.core.interface.serial import i2c

from luma.core.render import canvas

from luma.oled.device import sh1106

from PIL import ImageFont, Image, ImageDraw    


### setting up display using LUMA oled

device = sh1106(i2c(port=1, address=0x3C), rotate=0)

device.clear()


### Initialize drawing zone (aka entire screen)

output = Image.new("1", (128,64))

add_to_image = ImageDraw.Draw(output)


### I have the exterior temp and altitude I want to display. Each has an assigned zone for the icon (FontAwesome) and the data

# temp_ext

temp_zone = [(14,44), (36,64)]

temp_start = (14,44)

temp_icon_zone = [(0,48), (15,64)]

temp_icon_start = (3,48)

add_to_image.text(temp_icon_start, "\uf2c9", font=FA_solid, fill="white")


### every time I have a new reading, I basically draw a black rectangle over what I had and the rewrite the text

add_to_image.rectangle(temp_zone, fill="black", outline = "black")

add_to_image.text(temp_start, str(temp_c), font=text_medium, fill="white")

device.display(output)

这使我能够只更新我想要的屏幕部分,其余部分保持原样,最重要的是,在重写信息时不会有半秒钟的空白屏幕。欢迎提出优化建议!


我仍然需要查看内存使用情况,当不同区域同时更新时感觉有点缓慢。但它有效!


查看完整回答
反对 回复 2023-10-05
  • 2 回答
  • 0 关注
  • 158 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信