How to hide ttk Treeitem indicators in a Python GUI - python

I'm building a Python GUI application using ttk treeviews. On Linux, when a Treeitem has child items, it displays an arrow to show that the row can be expanded. I want to hide this indicator arrow (I am using other ways to hint that the row can be expanded). How can I do this?
If I run Style().element_names() I see that there's a Treeview element and a Treeitem.indicator element. If I run Style().configure("Treeview", padding=50), I see the padding style get applied when I create the treeview, so I feel confident that any style I correctly apply to Treeitem.indicator should be visible also.
Running Style().element_options("Treeitem.indicator"), I see ('-foreground', '-indicatorsize', '-indicatormargins'). Running Style().lookup("Treeitem.indicator", "foreground") gives me "#000000", so it appears that value is initialized. If I try Style().configure("Treeview", foreground="#123456") I don't see the indicator arrow change color, though running Style.lookup("Treeitem.indicator", "foreground") shows me "#123456" as expected. My plan was to set the indicatorsize to 0 to make the arrow go away entirely, but I cannot even successfully edit the color. What am I doing wrong here and is there a better way to hide the indicator? In case it matters, I'm running Python 3.5.0.

Not sure if you ever figured it out.
When you create the new style and configure it, you have to change the name of the template to ".". This changes the root style for the treeview. You also need to specify a theme, even if it is default. So it would look something like:
s = ttk.Style()
s.configure(".", indicatorsize = '0')
s.theme_use('default')
Then when you create the treeview, you shouldn't have to specify a style at all.
Let me know if this works for you.
Edit: Since this is being downvoted for some reason, I'll clarify:
Code with the style part commented out:
#s = ttk.Style()
#s.configure(".", indicatorsize = '0')
#s.theme_use('clam')
j = ttk.Treeview(self.parent)
j.place(relx = 0.5, rely = 0.5, anchor = "center")
j.insert("",1,"jacob",text = "Jacob")
j.insert("jacob",1,"marcus",text = "Marcus")
j.insert("jacob",2,"tony",text = "Tony")
j.insert("jacob",3,"ricardo",text = "Ricardo")
gives us
Code with the style part present
s = ttk.Style()
s.configure(".", indicatorsize = '0')
s.theme_use('clam')
j = ttk.Treeview(self.parent)
j.place(relx = 0.5, rely = 0.5, anchor = "center")
j.insert("",1,"jacob",text = "Jacob")
j.insert("jacob",1,"marcus",text = "Marcus")
j.insert("jacob",2,"tony",text = "Tony")
j.insert("jacob",3,"ricardo",text = "Ricardo")
Hope this helps.
EDIT 2:
Added the s.theme_use('clam') line because you need to specify which theme you're using. It also works with classic and default, but for some reason doesn't work with the vista theme.

Related

Tkinter percentage sizes?

I am trying to build a small software with the Tkinter module and python but I can't figure out how to set a widget size with percentages instead of pixels. I could of course do it by grabbing the size of the entire window at every moment and divide by 2 to get a size of 50%, but is there a better way to do it with the Tkinter module?
EDIT 1: To answer your questions I put my code here:
class Navbar:
def __init__(self, master):
self.maxsizeFrame = Frame(master, height = 50) #maxsize handler, prevent self.frame to grow too big
self.maxsizeFrame.pack(fill = X, expand = NO)
self.frame = Frame(self.maxsizeFrame)
self.frame.pack(side = TOP, fill = BOTH, expand = YES)
self.masteries = Button(self.frame, text = "Masteries")
self.masteries.pack(side = LEFT, fill = BOTH, expand = YES)
self.runes = Button(self.frame, text = "Runes")
self.runes.pack(side = RIGHT, fill = BOTH, expand = YES)
So I want to create a navigation bar with two button handled in "self.frame". But I want this design to be responsive, that's why I set expand to "YES". However I wanted to set a maximum size for "self.frame" but the only way I found was to pack this frame in an other one ("self.maxsizeFrame") and set expand to "NO" on this one. And finally, I would like to set the maximum expand size to half the main window, so it could be great if the height of "self.maxsizeframe" could be in percentage. Thanks for reading.
EDIT 2:
Actually it seems more efficient to build the software with the grid layout and the weight's option would be accurate.
If you would like to make it half the size of the window, use width=root.winfo_width / 2, height=winfo_height
In the maximum size. (I had to post it late due to the limit of posting per 30Mins
Ok, I wonder how no one responded yet.
So instead of sizing the component at the moment of creation, you can instead use the widget.place() method, define relwidth and relheight (0=0%,0.5=50%,1=100%,etc), this will give the widget x% of its parent width/height. Using place() you can also define relative starting positions for the widgets using relx and rely, and even apply width,height,x, and y by specifying screen units as you would do normally.
Now the fun stuff, which I don't see talked around, is that you can apply relwidth and width at the same time,by playing with negative values and joining relx and x properties, you can get really responsive sites.
Here is an example where I played a bit with this fields to get the responsiveness I've desired:(don't mind 'yposition' comes from the application context)
self.label.place(rely=yposition,x=0.025,relheight=0.04,width=150)
self.entry.place(rely=yposition,x=150,relheight=0.04,relwidth=0.95,width=-190)
self.button.place(rely=yposition,relx=0.98,x=-40,relheight=0.04,width=40)
Although it depends on the widget, you should be able to do width=30% and same with height. Can you please edit your post saying which widget you are using. I would not recommend percents though as they get funky some times.

ipywidget interactive hiding visibility

I would like to make an interactive module with ipywidgets.
So far so good but I'm stuck.
I want to hide the visibility of a certain ipywidget object dependent on a certain situation, and I want my printed text to show up above the widget and stay there.
dropdown=widgets.Dropdown(
options={'Coffee machine': 1, 'Washing machine': 2, 'Water Heater': 3, 'Heating System': 4, 'Dryer': 5, 'Oven': 6, 'Microwave': 7, 'Other':8},
value=1,
description='Apparaat:',
)
text_new=widgets.Text()
def text_field(value):
if(value==8):
display(text_new)
text_new.on_submit(handle_submit)
else:
text_new.visible(False) #Doesn't work but I want something like this
print("Today you had an increase in electricity consumption, would you like to name this device?") #This just be above the dropdown menu and be stuck
i=widgets.interactive(text_field, value=dropdown)
display(i)
What this does now:
When "Other" is checked in the dropdown menu, a text box appears where the user can type something.
However, when checking another machine, the text box stays there.
I just need a "hide" function but I can't seem to find one that works.
Also, after checking another option on the dropdown, the print dissapears, not coming back.
Had same problem so i found in
boton.layout.visibility = 'hidden'
or
check.layout.display = 'none'
they made some changes... i got if from here
Cannot create a widget whose initial state is visible=False
Given a widget:
import ipywidgets
button = ipywidgets.Button()
There are two direct ways to hide the the widget, with a notable difference.
Hide and unhide the widget without affecting overall page layout:
# Turn the widget "invisible" without affecting layout
button.layout.visibility = "hidden"
# Make the widget visible again, layout unaffected
button.layout.visibility = "visible"
Hide and unhide the widget and collapse the space that the widget took up:
# Hide widget and collapse empty space
button.layout.display = "none"
# Re-add the widget, adjusting page layout as necessary.
button.layout.display = "block"
When to use each one? As a rule of thumb, use layout.visibility so the page layout is not constantly jumping around as visibility is toggled. However, for very large widgets, consider using layout.display to avoid huge blank spaces.
For more general CSS information that applies here, see What is the difference between visibility:hidden and display:none?
In addition to the accepted answer, if you want to dynamically change the visibility of a control, you can declare the layout variable and reuse.
layout_hidden = widgets.Layout(visibility = 'hidden')
layout_visible = widgets.Layout(visibility = 'visible')
Like attach to an event:
def visible_txt(b):
text_box.layout = layout_visible
def hidden_txt(b):
text_box.layout = layout_hidden
btn_visible.on_click(visible_txt)
btn_hidden.on_click(hidden_txt)

Facing issue using Action Bar in Python kivy Application

I am working on developing an application using Kivy. I am using Kivy ActionBar for creating a menu bar for my application.
Kindly refer to the image attached
I want to remove the Kivy icon and move the other options(file / edit) to the left. Please find the snippet of my code.
menuAcBar = ActionBar(pos_hint={'top': 1.3})
menuAcView = ActionView()
menuAcBar.add_widget(menuAcView)
menuAcPrevious = ActionPrevious(with_previous=False)
menuAcView.add_widget(menuAcPrevious)
menuAcView.add_widget(ActionButton(text="File"))
menuAcView.add_widget(ActionButton(text="Edit"))
menuAcView.add_widget(ActionButton(text="Documents"))
menuAcView.add_widget(ActionButton(text="help"))
self.add_widget(menuAcBar)
Right on ActionPrevious you can set app_icon. It's a little bit lower in docs. You can set app_icon_width/height for size of the icon or even remove it with app_icon='', but it'll leave white rectangle instead of a "transparent". Leave app_icon be and set only width and height to make it invisible.
The Ä„ctionPrevious has ActionItem's minimum_width property, therefore you need to change it like this:
menuAcPrevious = ActionPrevious(with_previous=False,
app_icon=<your_image>,
app_icon_width=1,
app_icon_height=0,
minimum_width=10,
size_hint_x: None)
Edit:
It seems that ActionPrevious leaves additional unused space even if title='' and minimum_width=1 and you can't access the damn thing through children because it's unregistered, therefore the only thing I came up with is resizing it so you won't see it anymore:
ActionPrevious(
size_hint_x = None,
width = 0,
app_icon_width = 0.1,
with_previous = False)

Creating a console in Kivy

I'm trying to write a very basic Kivy program that will use 3 different layouts to split the screen into :
a header (at the top of the screen)
a text zone (in the middle of the screen)
a console (at the bottom of the screen)
So far I was thinking to use a main gridLayout, in which I use 3 different floatLayout.
Here's what the code looks like:
class Logo(App):
def build(self):
layout = GridLayout(rows=3)
layoutTop = FloatLayout(size=(100,300))
layoutMid = FloatLayout(size=(100,300))
layoutDown = FloatLayout(size=(100,300))
logo = Image(source='imagine.png',size_hint=(.25,.25),pos=(30,380))
blank = Label(text='', font_size = '25sp',pos=(-200,100))
titre = Label(text='#LeCubeMedia',font_size='40sp',pos=(0,280))
ip = Label(text='192.168.42.1',font_size='25sp',pos=(250,280))
layoutTop.add_widget(titre)
layoutTop.add_widget(logo)
layoutTop.add_widget(ip)
layoutMid.add_widget(blank)
layout.add_widget(layoutTop)
layout.add_widget(layoutMid)
return layout
if __name__ == '__main__':
Logo().run()
Actually my problem is regarding the creation of the console. I have read a lot of the Kivy docs, but I am still looking for a good way to do this type of widget.
How do you think it would be if I send something with a Python print into my Kivy app, and then refresh as soon as I need to send something else (to erase the previous print). This way it would be a console-like. But, so far I have not much ideas..
Any ideas ?
I have seen 2 types of consoles in Kivy. The first is a multiline textinput in a scrollview where you append the new text to the old in the textinput. The second is a BoxLayout or GridLayout in a Scrollview where each console output is a separate label in the layout.
This was a attempt trying stuff out with kivy, the code is old and you might need to adjust it a bit to make it run with latest kivy. Kivy-designer also includes this. This is using the simple way of using two textinputs, 1 for history and the other for input.
A better way to do a proper console would be to use pyte and draw characters directly onto the canvas of a widget. This way one would get VT emulation for free.

After adding "primary toolbar" style class to a gtk.Builder object, gtk.ToolButtons in toolbar are not primary-themed

I've been trying to get my toolbar to look like the standard toolbars in stock Ubuntu apps, and it works to an extent, except the buttons in the toolbar do not have the correct theming applied to them. The text is colored for the default toolbar, and on hover the buttons are an ugly tan color instead of getting darker grey as they do in the standard Ubuntu apps.
In other words I'm getting this:
Instead of this:
(I don't have enough rep to post images directly)
I've been using the following method to change the toolbar style, since Glade doesn't seem to have an option to change it itself:
self.bd = Gtk.Builder()
self.bd.add_from_file("builderfile.glade")
self.bd.connect_signals(self)
...
toolb = self.bd.get_object("toolbar")
toolb_style = toolb.get_style_context()
toolb_style.add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR)
This works to the extent that the toolbar is now darkened, but the buttons are incorrectly themed. I tried adding buttons to the toolbar manually after setting the STYLE_CLASS_PRIMARY_TOOLBAR instead of using Gtk.Builder() but they weren't the right color either.
I suppose manually creating a toolbar and filling out all the information might work, but it would be nice to be able to use Glade for the design.
I'm writing this answer here since it's a solution, but it's not ideal because it doesn't use Glade and it's kind of messy. I'll have to wait until a new build of Glade gets into Ubuntu, since apparently the feature has been added upstream.
The solution I eventually used was just to do all the toolbar creation in standard GTK and python, and then add it to an empty Gtk.Box defined in Glade. Like this:
bd = Gtk.Builder()
bd.add_from_file("gladefile.glade")
...
button1 = Gtk.ToolButton(stock_id=Gtk.STOCK_ADD, ...)
button2 = Gtk.ToolButton(...)
toolbar = Gtk.Toolbar()
toolbar.get_style_context().add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR)
toolbar.insert(button1, 0)
toolbar.insert(button2, 1)
toolbar.show_all()
bd.get_object("toolbar_slot").pack_start(toolbar, False, True, 0)

Categories

Resources