Okay, Does anyone know any code to load a image in the ui designer (ImageView) cause I want to use my own custom image I know how to import custom images but not sure how to load them in the ui designer. If Anyone can help that would be awesome!
Forum Archive
ImageView UI Designer Code
@SYS that works (see custom attributes at bottom, tested ok with my own images)
import ui
v = ui.load_view()
v.present('sheet')


Hi
Is there a way to visualise the custom image inside the ui designer?ie so you can use as a background to help place other ui elements?
The stock icons display fine, could that be extended somehow to alllow for another location of custom images to be dragged dropped onto canvas and visualised as a bg?
I not anyone have any other ideas apart from painstakingly building up many elements in code and testing line by line.
I have a lot of rectangular regions I want to define ideally interactively on top of an image as ref.
Thought about writing something to do just this task but it’s potentially lots of work when designer has everything apart from that 1 feature…is ui designer hackable?
@rb only to show I'm in the right way...
Not yet the correct image but already a customized image in ImageView in the designer.
To be perfect, the script should extract the image file from custom attributes, I'll try but perhaps not today, sorry
Set this script as a Pythonista tool and select it when your .pyui is edited in the designer
from objc_util import *
import ui
@on_main_thread
def SetImageInDesigner():
win = ObjCClass('UIApplication').sharedApplication().keyWindow()
main_view = win.rootViewController().view()
def analyze(v,indent):
for sv in v.subviews():
#print(indent,sv._get_objc_classname())
if 'UIImageView' in str(sv._get_objc_classname()):
if 'OMUIWidgetViewImageView' in str(sv.superview()._get_objc_classname()):
if 'OMUIDesignCanvasView' in str(sv.superview().superview()._get_objc_classname()):
sv.setImage_(ObjCInstance(ui.Image.named('test:Lenna')))
analyze(sv,indent+' ')
analyze(main_view,'')
return
if __name__ == '__main__':
SetImageInDesigner()


@rb new version, needs {'image': ui.Image.named('xxxxxxxxxx')} in custom attributes of ImageView
Please, test it and give me some feedback, thanks
import editor
import ast
import json
from objc_util import *
import ui
@on_main_thread
def SetImageInDesigner():
global filenames
filenames = {}
t = "ui.Image.named('"
fil = editor.get_path()
with open(fil) as f:
dic = json.load(f)[0]
nodes = dic['nodes']
for node in nodes:
if node['class'] == 'ImageView':
attrs = node['attributes']['custom_attributes']
i = attrs.find(t)
if i >= 0:
j = attrs.find("')", i)
img = attrs[i+len(t):j]
nam = node['attributes']['name']
filenames[nam] = img
win = ObjCClass('UIApplication').sharedApplication().keyWindow()
main_view = win.rootViewController().view()
def analyze(v,indent):
global filenames
for sv in v.subviews():
#print(indent,sv._get_objc_classname())
if 'UIImageView' in str(sv._get_objc_classname()):
if 'OMUIWidgetViewImageView' in str(sv.superview()._get_objc_classname()):
if 'OMUIDesignCanvasView' in str(sv.superview().superview()._get_objc_classname()):
w = sv.superview()
for svw in w.subviews():
if 'UILabel' in str(svw._get_objc_classname()):
n = str(svw.text())
break
if n in filenames:
sv.setImage_(ObjCInstance(ui.Image.named(filenames[n])))
analyze(sv,indent+' ')
analyze(main_view,'')
return
if __name__ == '__main__':
SetImageInDesigner()
Hey cvp both work perfectly thankyou so much !the latter obvs more elegant as I can important multiple images :) this has saved me a lot of time and energy again...
If I was to ask for even more..one thing that would be a great option would be to lock the position of bg images like this from being moved in the view somehow? Unless there is already a native way to do this in designer.
Its really easy to accidentally select and move a large image if your trying to populate / use it for ref to create other items on top of.
Maybe it’s only selectable in ui and not moveable by default in ui with touch ?That way it can be set in properties (usually 0,0,w,h for me) to fill the bg.
Thanks again!
@rb I guess that I don't understand your request. I think that the image in an ImageView is not movable. Perhaps am I wrong.
@rb As the topic title speaks about ImageView, perhaps I did not understand correctly.
Perhaps do you want to set a background image to the entire view?
Édit: and do you want that an ImageView as subview of the view becomes unmovable
Sorry yes - I’m loading an imageView as a sub view of the .pyui main ui.view and I’m basically using it as a bg image to help me position some other elements that I incorporate into another project later ie the easiest way to accurately place elements on an image is using the designer.I’m just saying that if the imageView that I use as a bg that fills entire canvas ,isn’t locked somehow in the designer ui ,it is very easy to accidentally select it and move it.
@rb try to only insert one line
w = sv.superview()
w.setFrame_(w.superview().frame()) # <--------------------------
for svw in w.subviews():
If you were busy to focus an ImageView, it's blue border would stay at its previous position/size but tap anywhere and it will disappear. Perhaps I'm not clear, try to
- change an ImageView position/size and let this object focused
- run the tool
- you will see the object back to 0,0,w,h but the blue focus border would stay because the code does not change it
- tap anywhere and it will disappear
@cvp not sure I understand..
I just want to lock a selected imageView in the ui at its current position I think so that it will no longer move unless using the properties window.
Also I can longer get either method to work today on a pyui that was working fine yesterday..or any other pyui - any ideas why that would happen?
I put a print statement in to check if it was finding the image name and it seems to be- it’s just not showing the image any longer.
@rb said
I just want to lock a selected imageView in the ui at its current position I think so that it will no longer move unless using the properties window.
I can't force as not movable but if you tap the script as tool, it resets the ImageView frame as full view if you had changed erroneously its position or size
@rb said
I put a print statement in to check if it was finding the image name and it seems to be- it’s just not showing the image any longer.
I got the same problem and have remarked a blank into the "named", like "test: Lena" instead of "test:Lenna" and I don't know why
@cvp so no longer working for you either?
Weird!?
@rb no, no, it works but yesterday I got the same problem, check the file name in your custom attributes
@rb with a blank in file name, no image is showed. Don't ask me why
@cvp no blanks no typos the test:Lenna works but not other images.Cant see a reason for it to not work. If I access an image in a dir the syntax would be :
{'image': ui.Image.named('testDir/test.jpg')}
Right?
At least that’s what I was doing yesterday and it worked…I’m confused.
@rb Perhaps due in which dir you were, could you try with the full path?
@rb this works (I present to you my dog, Nana)

Nana is a beauty :)
You are totally correct of course ! I managed to have 2 copies of the setImageInDesigner.py …duh one in iPad and one in iCloud where my scripts are stored so the path wasn’t resolving.Apologies for wasting part of your day with that !
@rb said
Apologies for wasting part of your day with that !
No problem, happy to have helped, sincerely
Next question..
If I want to add a custom image in designer for a button not an imageView…
I can’t get the image to load using the same above syntax in custom attributes.Is this something to do with :
.with_rendering_mode(ui.RENDERING_MODE_ORIGINAL)
And if so what would the proper syntax be inside that custom attribute string? So far I just get errors if I add that as an extra string on end of image path.
Also it’s not important that this image is visible in designer just that it works in final use when loaded/used in another view.
@rb try
import editor
import ast
import json
from objc_util import *
import ui
@on_main_thread
def SetImageInDesigner():
global filenames
filenames = {}
t = "ui.Image.named('"
fil = editor.get_path()
#print(fil)
with open(fil) as f:
dic = json.load(f)[0]
nodes = dic['nodes']
for node in nodes:
if node['class'] in ['ImageView', 'Button']:
attrs = node['attributes']['custom_attributes']
i = attrs.find(t)
if i >= 0:
j = attrs.find("')", i)
img = attrs[i+len(t):j]
nam = node['attributes']['name']
filenames[nam] = img
win = ObjCClass('UIApplication').sharedApplication().keyWindow()
main_view = win.rootViewController().view()
def analyze(v,indent):
global filenames
for sv in v.subviews():
#print(indent,sv._get_objc_classname())
if 'UIImageView' in str(sv._get_objc_classname()):
if 'OMUIWidgetViewImageView' in str(sv.superview()._get_objc_classname()):
if 'OMUIDesignCanvasView' in str(sv.superview().superview()._get_objc_classname()):
w = sv.superview()
w.setFrame_(w.superview().frame())
for svw in w.subviews():
if 'UILabel' in str(svw._get_objc_classname()):
n = str(svw.text())
break
if n in filenames:
sv.setImage_(ObjCInstance(ui.Image.named(filenames[n])))
elif 'UIButton' in str(sv._get_objc_classname()):
if 'OMUIWidgetViewButton' in str(sv.superview()._get_objc_classname()):
if 'OMUIDesignCanvasView' in str(sv.superview().superview()._get_objc_classname()):
w = sv.superview()
for svw in w.subviews():
if 'UILabel' in str(svw._get_objc_classname()):
n = str(svw.text())
break
if n in filenames:
sv.setImage_forState_(ObjCInstance(ui.Image.named(filenames[n]).with_rendering_mode(ui.RENDERING_MODE_ORIGINAL)),0)
analyze(sv,indent+' ')
analyze(main_view,'')
return
if __name__ == '__main__':
SetImageInDesigner()


@rb You have to know that you can set the image or the background_image of a button.
If you set the background_image, the button title is also visible.
The modified tool script sets the image, not the background_image.
If you would prefer to set the background_image or both (not together), tell me, I should need to change the tool script
@rb try this version, supporting custom attributes image and background_image but not together
import editor
import ast
import json
from objc_util import *
import ui
@on_main_thread
def SetImageInDesigner():
global filenames
filenames = {}
t = "ui.Image.named('"
fil = editor.get_path()
#print(fil)
with open(fil) as f:
dic = json.load(f)[0]
nodes = dic['nodes']
for node in nodes:
if node['class'] in ['ImageView', 'Button']:
attrs = node['attributes']['custom_attributes']
#print(attrs)
i = attrs.find(t)
if i >= 0:
j = attrs.find("')", i)
img = attrs[i+len(t):j]
nam = node['attributes']['name']
if node['class'] == 'Button':
if "'image'" in attrs:
k = 'image'
else:
k = 'background_image'
filenames[nam] = (img,k)
else:
filenames[nam] = (img,'image')
win = ObjCClass('UIApplication').sharedApplication().keyWindow()
main_view = win.rootViewController().view()
def analyze(v,indent):
global filenames
for sv in v.subviews():
#print(indent,sv._get_objc_classname())
if 'UIImageView' in str(sv._get_objc_classname()):
if 'OMUIWidgetViewImageView' in str(sv.superview()._get_objc_classname()):
if 'OMUIDesignCanvasView' in str(sv.superview().superview()._get_objc_classname()):
w = sv.superview()
w.setFrame_(w.superview().frame())
for svw in w.subviews():
if 'UILabel' in str(svw._get_objc_classname()):
n = str(svw.text())
break
if n in filenames:
sv.setImage_(ObjCInstance(ui.Image.named(filenames[n][0])))
elif 'UIButton' in str(sv._get_objc_classname()):
if 'OMUIWidgetViewButton' in str(sv.superview()._get_objc_classname()):
if 'OMUIDesignCanvasView' in str(sv.superview().superview()._get_objc_classname()):
w = sv.superview()
for svw in w.subviews():
if 'UILabel' in str(svw._get_objc_classname()):
n = str(svw.text())
break
if n in filenames:
#print(dir(sv))
if filenames[n][1] == 'image':
sv.setImage_forState_(ObjCInstance(ui.Image.named(filenames[n][0]).with_rendering_mode(ui.RENDERING_MODE_ORIGINAL)),0)
else:
sv.setBackgroundImage_forState_ (ObjCInstance(ui.Image.named(filenames[n][0]).with_rendering_mode(ui.RENDERING_MODE_ORIGINAL)),0)
analyze(sv,indent+' ')
analyze(main_view,'')
return
if __name__ == '__main__':
SetImageInDesigner()


Dude your so generous with your assistance always above and beyond Thankyou ! It’s sunny right now in uk so I’m chillin with my dawg in the garden with a beer - will check this as darkness falls :)
@rb said
with a beer
Don't move, I'm coming 🍻
Found couple of issues.
I had to add the middle line/check:
if node['class'] in ['ImageView', 'Button']:
if 'custom_attributes' in node['attributes']:
attrs = node['attributes']['custom_attributes']
As I have some other buttons without anything in custom_attributes and it was erroring.
After changing that I get the images appearing on buttons in designer woop! but unfortunately it still fails when imported as a load_view in my main function with same error ie :
Warning: Could not load custom attributes of view "test_btn": 'NoneType' object has no attribute 'with_rendering_mode'
Ok it was the path again but it makes no sense to me …
My path was resolved ok in designer using your script but I had to specify a full path to get it working as a load view. I don’t have to do this with the image views they work after I’ve set my file using
os.chdir(os.path.split(__file__)[0])
Anyhow it works so thanks again!
@rb said
I had to add the middle line/check:
Sorry, shame on me. I'm always in a hurry and I never do enough testing of different cases. You can call me an amateur.
Ok it was the path again but it makes no sense to me …
No idea, don't forget that the code which loads the images is unknown because belonging to Pythonista it-self.