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

我有一个 SH1106 显示器连接到我的 Raspberry Pi,我使用 luma.oled 控制它。


我可以用不同的字体显示各种内容,这很棒。但是,我不知道如何在不刷新整个显示的情况下向当前显示的内容添加内容。我的代码是这样的:


from os import system

import serial

from time import sleep

from luma.core.interface.serial import i2c

from luma.core.render import canvas

from luma.oled.device import sh1106

from PIL import ImageFont


# config display

device = 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 things

def 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?理想情况下,我会在屏幕上有“区域”,我可以在其中更改图标区域,同时保持文本显示,反之亦然。谢谢!


慕娘9325324
浏览 159回答 2
2回答

慕容森

我没有 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 python3from PIL import Image, ImageDrawdef 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 itz1 = Image.new("RGB", (60,30), (64,64,64))z1draw = ImageDraw.Draw(z1)z1draw.text((10,10),"Zone1")# Make zone2 mid-grey and annotate itz2 = Image.new("RGB", (60,30), (128,128,128))z2draw = ImageDraw.Draw(z2)z2draw.text((10,10),"Zone2")# Make zone3 light grey and annotate itz3 = Image.new("RGB", (124,28), (192,192,192))z3draw = ImageDraw.Draw(z3)z3draw.text((10,10),"Zone3")# Blit all zones to displayUpdateDisplay(z1,z2,z3)# Now change just zone 2 and update displayz2.paste("red", (0,0,z2.width,z2.height))UpdateDisplay(z1,z2,z3)这是原始显示:更新 zone2 后再次出现:

潇潇雨雨

好吧,我基本上明白了:from luma.core.interface.serial import i2cfrom luma.core.render import canvasfrom luma.oled.device import sh1106from PIL import ImageFont, Image, ImageDraw    ### setting up display using LUMA oleddevice = 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_exttemp_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 textadd_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)这使我能够只更新我想要的屏幕部分,其余部分保持原样,最重要的是,在重写信息时不会有半秒钟的空白屏幕。欢迎提出优化建议!我仍然需要查看内存使用情况,当不同区域同时更新时感觉有点缓慢。但它有效!
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python