我想使用 Python NiceGUI 库构建一个小型 GUI。 对于我的应用程序,我使用网格元素将界面分为两列。这很好用。左侧有一些带有复选框的卡片,可以查看叠加层。
在右栏中,我插入了一张 T 恤图像,并希望在该图像上覆盖一个小红色框,该红色框标记了 T 恤上的一个洞。框的坐标在与原始图像大小一起使用的列表中给出。 (我已经使用
plt.imshow()
对此进行了测试)。
我已经弄清楚如何显示 viewBox,绘制红色框并将其覆盖在图像上。
只是覆盖层的尺寸与图像的尺寸还不匹配。由于某种原因,覆盖层周围有未指定数量的填充,我似乎无法访问或获取其 ID。
我认为这应该可以使用
.props()
.style()
或 .classes()
方法或列的宽度来修复,但我不知道使用哪一种以及如何使用。对于我的应用程序,图像和视图框有多大并不重要,只要它们相同即可使红色框位于正确的位置。
我不熟悉 html 或 CSS,因此代码中的那些部分可能存在我不知道的错误。 (我也愿意接受风格改进。)
在我看来,NiceGUI 在其文档中给出的示例也有类似的问题。 (参见https://nicegui.io/documentation/section_audiovisual_elements#captions_and_overlays) 如果您手动检查飞机图片的元素并手动将
cx
更改为 960,将 cy
更改为 638(视图框的尺寸),则飞机周围会出现圆圈,这对我来说更有意义。
这是一个小工作示例: (任何图像都应该有效,但这就是我得到我的图像的地方: https://www.ebay.com/itm/225367896573)
from nicegui import ui
complete_im = plt.imread("test_file_large.jpg")
y_dim, x_dim = complete_im.shape[1], complete_im.shape[0]
tile = complete_im[355:385, 895:935] # This was saved to 'test_hole_3.jpg'
tile_files = ['test_hole_3.jpg']
tile_ids = (355, 385, 895, 935)
tile_dims = (30, 40)
with ui.grid(columns=2).classes("w-auto").style():
with ui.card():
ui.image(tile_files[0])
ui.space()
checkbox_0 = ui.checkbox('Show hole')
checkbox_0.value = True
with ui.image('test_file_large.jpg').style('object-position: top right;'):
# .props('fit=contain'):
svg_code = f'''
<svg viewBox="0 0 {y_dim} {x_dim}" width="100%" height="100%"
xmlns="http://www.w3.org/2000/svg" style="color: transparent;">
<rect width="{str(tile_dims[1])}" height="{str(tile_dims[0])}"
x="{str(tile_ids[2])}" y="{str(tile_ids[0])}"
style="stroke:red;stroke-width:5;fill-opacity:0.0;stroke-opacity:0.99" />
</svg>'''
ui.html(svg_code).bind_visibility_from(checkbox_0, 'value')
ui.run()
为了让 SVG 填充完整图像尺寸,您可以添加一个“w-full”类,如下所示:
with ui.image('https://cdn.stocksnap.io/img-thumbs/960w/airplane-sky_DYPWDEEILG.jpg'):
ui.html('''
<svg viewBox="0 0 960 638" width="100%" height="100%" xmlns="http://www.w3.org/2000/svg">
<circle cx="445" cy="300" r="100" fill="none" stroke="red" stroke-width="10" />
</svg>
''').classes('w-full bg-transparent')
(我正在使用 NiceGUI 网站上的示例,因为您的代码需要更多工作才能运行。)
顺便说一下,你正确地发现了官方示例中的一个错误。我们将在下一次网站更新时修复它。
ui.interactive_image
可能比常规的ui.image
更适合,因为它带有开箱即用的正确缩放的SVG:
ui.interactive_image(
'https://cdn.stocksnap.io/img-thumbs/960w/airplane-sky_DYPWDEEILG.jpg',
content='<circle cx="445" cy="300" r="100" fill="none" stroke="red" stroke-width="10" />',
)