Does anyone know how Kivy renders text in different fonts?
I have labels with text at 16sp.
On a tablets with screen sizes (1024, 552) and (2048, 1536) it works perfectly (width/height ratios 1.855 and 1.333 respectively)
On the pc with screen size (1280, 720) (ratio 1.778) it also displays perfectly, but on a phone with this screen size the letters are truncated
The only difference here is the physical size of the device. It thus appears, that Kivy text is not rendered according to some algorithm based on pixels, but takes into account the physical size of the screen
Is there any way to determine the physical size in Kivy? and hence allow me to adjust font size accordingly. The text appears correctly on the phone (small device) if I use a smaller (10sp) font size, but then it appears too small on the larger devices.
Yes, you can determine the physical size of screen with kivy -
You could simply use this Module:
(from kivy.core.window import Window)
and then determine sizes by writing this:
(Window.size)
Check this code out (this code determines screen physical sizes on a simple label):
⬇️⬇️
from kivy.app import App
from kivy.uix.label import Label
from kivy.core.window import Window
class MyApp(App):
def build(self):
window_sizes=Window.size
return Label(text="screen sizes= "+str(window_sizes))
MyApp().run()
It is possible to obtain the screen sizes, but you'll need to install plyer and before packaging also patch it, so that you could access the info.
Or just use the plain pyjnius and access android.util.DisplayMetrics with autoclass.
From what I am understanding, you are having issues displaying your text properly, over multiple devices. Now, I do not think that you can get the devices actual dimensions through Kivy itself, but with plain old python, you can.
An Example in Python:
import gtk
window = gtk.Window()
screen = window.get_screen()
print "screen size: %d x %d" % (
gtk.gdk.screen_width(),gtk.gdk.screen_height())
The Code above will print out the screen heigh and width, or resolution, for you to use.
To store them in variables instead:
import gtk
window = gtk.Window()
screen = window.get_screen()
ScreenWidth = gtk.gdk.screen_width()
ScreenHeight = gtk.gdk.screen_height()
# And to prove it worked (You would not want to include this part in code
#########################################################################
print str(ScreenWidth) + 'x' + str(ScreenHeight)
Now that you have those variables, you can use them in your .kv file, by pulling them from a python file, or implementing the whole function directly into your Kivy Code somehow.
From: https://kivy.org/docs/api-kivy.metrics.html we learn that 'sp' is the scale independent pixel size. Thus it includes the pixel density already and the font size appears the same on each device (at least should).
The reason, why your font is clipped is because of the size of the container. You also should also give the desired size, like in this example (note: if you want a secific height, you must include the size_hint_y: None argument)
TextInput:
id: text_input
size_hint_y: None
height: '30sp'
multiline: False
What I ended up doing is maximizing my window to get the maximum allowed non-full screen size, then reading that size. I actually used it to center a smaller window on screen:
#-- maximize first, to get the screen size, minus any OS toolbars
Window.maximize()
maxSize = Window.system_size
#-- set the actual window size, to be slightly smaller than full screen
desiredSize = (maxSize[0]*0.9, maxSize[1]*0.9)
Window.size = desiredSize
#-- center the window
Window.left = (maxSize[0] - desiredSize[0])*0.5
Window.top = (maxSize[1] - desiredSize[1])*0.5
Note that by maximizing my window first, I am getting the maximum allowed size, less any operating system's toolbars etc., i.e., the size that the window has when you press the maximize button.
Related
For some reason when ever I make a program with pygame, the window is bigger then I make it but all the coordinates are okay and it's been annoying me a lot. Can anyone help with this?
Here is a part of code I use to test it:
WIN = pygame.display.set_mode() # Makes a window the size of the screen
print(f'Window size: {WIN.get_size()}\nScreen size: {pygame.display.list_modes()[0]}') # Displays window size and screen size
Here is the output:
Window size: (1536, 864)
Screen size: (1920, 1080)
Edit: putting (1536, 864) doesn't work
replace WIN = pygame.display.set_mode() with WIN = pygame.display.set_mode((1536, 864)) . So what I think is the problem is that the screen's size is not specified. Hence the weird scaling.
Situation:
I'm making a software that has to be full screen
It is all UIs and interfaces.
I want it to work on computers with screens that have different resolutions - So I need the GUI to adjust to the screen size: text will be smaller if the screen resolution is smaller, but it will still be in the middle of the screen
I've tried not using numbers in deciding the position of the text, but instead getting the screen resolution, and multiplying it
Problem:
The text is not getting smaller.
Question:
Is there an easy solution for my problem? Is there a module in python for this purpose? I'm currently using WxPython but I'm open to use any other GUI module.
def Title(object):
(sizeX, sizeY) = object.GetSize()
(displayX, displayY) = wx.GetDisplaySize()
print(displayX)
print(displayY)
print(sizeX)
print(sizeY)
object.SetPosition((displayX/2 - sizeX/2, displayY*0.01))
To adjust the text size to be appropriate to the screen size, you would have to define a custom font size.
Although I suspect that the default font size will already be roughly correct, as the user will have set the system font size, based on the screen size.
You can get the current font size as follows:
self.font = wx.SystemSettings.GetFont(wx.SYS_SYSTEM_FONT)
point_size = self.font.GetPointSize()
Define a new, appropriate, font size based on the result from wx.GetDisplaySize():
self.font.SetPointSize(new size)
Then use SetFont(font) on the items in your UI:
self.panel.SetFont(self.font)
I create script for playblast. I need some HUD data over my video like a user and scene name, fps and current frame...
First i try HUD created by headsUpDisplay() is good, but not have a background... I change color of HUD labels but sometimes they are not readable without a background.
cmds.headsUpDisplay('HUDObjectSceneName', label='label TEXT',
section=2, block=0, blockSize='large',
dfs='large', labelFontSize='large')
Second i try use HUD buttons created by hudButton() - they have a background. But one of my label - is current time. headsUpDisplay() have 'command' to refresh and change label text. But hudButton() does not have this functionality.
label = 'FPS: 25 FRAME:'
cmds.hudButton('HUDHelloButton3', s=9, b=0, vis=1, l=label,
bw=blockLen(label), lfs='large')
cmds.headsUpDisplay('HUDCurentFrame', label=label,
section=9, block=0, blockSize='large', dfs='large',
labelFontSize='large', atr=True,
command=lambda: cmds.currentTime(query=True))
hudButton() have second trouble - width of button is set manually. and when i want long label i need to calculate label width. but HUD font is not fixed and i don't know how right calculate a label width in pixels. After some experiments i create this function to calculate width. It made rough, but at least as that:
def blockLen(label):
FONT_WIDTH = 8
THIN_WIDTH = 6
BLOCK_ADD = 10
thin_symbol = ' :,.!i[];:\'"|-'
sum = BLOCK_ADD
for x in label:
sum += THIN_WIDTH if x in thin_symbol else FONT_WIDTH
return sum
I need HUD label with background and dynamic data like a current frame. But i can't find another way how create it?
ps. I try to use scriptJob() to change HUD button label when time changed. But its not worked with playblast...
scriptJobs do not execute when animations are playing. If you really need to update the hud during playback you can trigger your update from inside an expression. You'll have to call it from mel, unfortunately. And keep it as light as possible, it will slowdown interactive playback for anybody viewing the animation.
You might want to dynamically create the expression before playblasts and then delete it right afterwards so you don't leave it lying around to bother your animators.
You can also get out of using HUD buttons by creating an image plane set to an appropriate color.
One part of my problem i decided to. I don't find how to update button directly. I create headsUpDisplay() without label - he is able to updated. And i forced him to change the text on my hudButton()
def frame_label():
label = 'FPS: 24 FRAME: %s' % cmds.currentTime(query=True)
cmds.hudButton('HUDCurentFrame', e=True, l=label)
# bottom-right: FPS and current frame info
cmds.headsUpDisplay('HUDCurentFrameInvisible', label='',
section=9, block=1, blockSize='large', dfs='large',
labelFontSize='large', command=frame_label, atr=True)
cmds.hudButton('HUDCurentFrame', s=9, b=0, vis=1, l='', bw=200, lfs='large')
But second part of my problem not solved. I cant calculate text size in pixels. The correct solution is to get from the Maya which font is used for HUD. And then i can use wx library to calculate width of text using font name...
But how to get font data (name, size and decorations) from Maya?
to your second problem:
i was able to find the needed font data (only name, size) but its not really accurate(more hacking, no voting needed), if you change the view port renderer to ViewPort 2.0 and than
and changing the sizes of the font you will get the Error (nor on the default renderer):
# small display ui font size and display ui size
cmds.displayPref(sfs=9, dfs=10) #font size
cmds.savePref()
Failed trying to load font: -*-helvetica-bold-normal-*-9-*-*-*-*-*-iso8859-1
so the used font is helvetica bold and the size is relativ(you own input or the default value like cmds.optionVar(q="defaultFontSize"))
I checked the document for Graphics.
It says:
Image(anchorPoint, filename)
Constructs an image from contents of the given file, centered at the given anchor point. Can also be called with width and height parameters instead of filename. In this case, a blank (transparent) image is created of the given width and height.
But I tried to type:
window = GraphWin("game", 400, 400)
Image((200,200),"flower.png")
But it doesnt work.
Do I need to import the picture first??Or add it to the window?
Please help.
This normally should work, you missed the anchorPoint
from graphics import *
window = GraphWin("game", 400, 400)
myimage=Image(Point(200,200),"flower.png")
myimage.draw(window)
I am making a BoxLayout widget (orientation = 'horizontal') that contains three widgets inside of it, a label, a text box, and a check box.
thisRow = BoxLayout(orientation='horizontal')
l = Label(text='Enter plate 1:\n(Plate #)')
t = TextInput(text = 'this is a text box')
c = CheckBox()
thisRow.add_widget(l)
thisRow.add_widget(t)
thisRow.add_widget(c)
This produces the following widget (thisRow):
After the box is checked...
The rightmost black box is actually the checkbox, and works functionally, however there is no way for the user to know that it is in fact a checkbox. I would expect a smaller empty square in the middle, as is depicted in pictures here.
How do i get the traditional checkbox image (smaller empty square box)? Or generally, how can I make it more obvious that the box is a check box and not just an empty label?
Thank you
This is really interesting question and Malonge tried it in a good way. Right now(1.9.2-dev) there is still fixed size on CheckBox's well, call it a background. It's an image that Widget takes from atlas and changes if the state changes. Therefore until now there was no clear way how to do it. Here is an example. Soon on master there'll be CheckBox(color=[r,g,b,a]) option. Thanks ;)
from kivy.lang import Builder
from kivy.base import runTouchApp
from kivy.uix.boxlayout import BoxLayout
Builder.load_string('''
<CheckBoxBG>:
Label:
TextInput:
CheckBox:
canvas.before:
Color:
rgb: 1,0,0
Rectangle:
pos:self.center_x-8, self.center_y-8
size:[16,16]
Color:
rgb: 0,0,0
Rectangle:
pos:self.center_x-7, self.center_y-7
size:[14,14]
''')
class CheckBoxBG(BoxLayout):pass
runTouchApp(CheckBoxBG())
Looks like the smaller check box is hidden when the background color is black. Here is an example of a red background.
It's not ideal because I do like the black background, but I can run with it for now. If anyone knows how to do this with a black background that would be great. Thank you
Alternatively, to change your checkboxes background, you can use another image from the atlas or create images and then load them:
mycheckbox= CheckBox(
background_checkbox_normal ='tlas://data/images/defaulttheme/button_disabled'
background_checkbox_down = 'my_checkboxes_checked.png'
)
In Kivy 1.9.2.dev0 (and apparently since version 1.9.0) you can change the background image of checkboxes. By default, Kivy uses for these backgrounds from the atlas*.
background_checkbox_normal = StringProperty('atlas://data/images/defaulttheme/checkbox_off') #when the checkbox is not active.
background_checkbox_down = StringProperty('atlas://data/images/defaulttheme/checkbox_on') # when the checkbox is active.
background_checkbox_disabled_normal = StringProperty('atlas://data/images/defaulttheme/checkbox_disabled_off') #when the checkbox is disabled and not active.
background_checkbox_disabled_down = StringProperty('atlas://data/images/defaulttheme/checkbox_disabled_on') #when the checkbox is disabled and active.
You can have a look here at all the attributes :
*The atlas is a package of multiple textures that reduces the number of images loaded and speedup the application loading. You have see a preview of the atlas in Python Install Folder\Lib\site-packages\kivy\data\images\defaulttheme-0.png