With this code:
QtCore.QObject.connect(self.tabWidget, QtCore.SIGNAL("tabCloseRequested(int)"),
self.tabWidget.removeTab)
I can close any tab QTabWidget, and the names of these tabs are:
work_1
work_2
work_3
But I want the tab work_1 never closes.
Use Index did not work for two reasons:
The tabs can be dynamically moved by this code:
self.tabWidget.setMovable (True)
That makes the Index are constantly changing.
The user has the ability to add new tabs.
Tabs can be identified by their widgets, and the widgets can be identified by their objectName (or some other unique attribute):
self.tabWidget.tabCloseRequested.connect(sef.removeTab)
...
def removeTab(self, index):
widget = self.tabWidget.widget(index)
if widget is not None and widget.objectName() != 'work_1':
self.tabWidget.removeTab(index)
or perhaps more simply:
if widget is not None and widget is not self.work_1:
self.tabWidget.removeTab(index)
Related
The following code creates a standard listbox in tkinter. In normal use, after the user makes the first listbox selection with a mouse click, subsequent selections can be made either by clicking again with the mouse, or by using the up/down cursor keys. Both of these (mouse click and cursor keys) correctly trigger ListboxSelect and change the value of SelectedIndex using the associated function UserClickedSelection(event).
The code also includes a function that allows me to set a listbox selection programmatically. This works perfectly, and correctly changes SelectedIndex using the SetSelection(index) function. But...and this is the problem...after making a selection programmatically, the up/down arrow keys no longer function. The user needs to make the next selection using the mouse, and then the up/down arrow keys once again function normally.
import tkinter as tk
root = tk.Tk()
root.geometry("300x300")
SelectedIndex = 0
def UserClickedSelection(event): # get user selection
global SelectedIndex
SelectedIndex = mylistbox.curselection()[0]
def SetSelection(index): # set selection
global SelectedIndex
mylistbox.selection_clear(0,tk.END)
mylistbox.selection_set(index)
mylistbox.activate(index)
SelectedIndex = mylistbox.curselection()[0]
mylistbox = tk.Listbox(root,activestyle="none")
mylistbox.place(x=0,y=0)
mylistbox.config(selectmode=tk.BROWSE)
mylistbox.config(exportselection=False)
mylistbox.bind('<<ListboxSelect>>',UserClickedSelection)
mylist = ['Zero','One','Two','Three','Four','Five']
mylistbox.insert(0,*mylist)
# Using function: set selection to index 2
SetSelection(2)
root.mainloop()
As you can see, in the code I've used the programmatic function to select index 2 of the listbox. This works fine, but the up/down arrow keys do not work until another selection is made afterwards using a mouse click. So there is clearly a difference between a "real" user selection and my "programmatic" selection. Is there some way to rectify this? I need the up/down arrow keys to work consistently. Thanks in advance for any assistance.
If I understand the problem correctly, you just need to make sure the listbox has focus.
def SetSelection(index): # set selection
...
mylistbox.focus_set()
I am trying to select multiple entries from Tkinter treeview. I used selectmode = extended for the same(use ctrl+enter key). But as soon as I try to open new branch in the tree(ctrl pressed), I am not able to open and if I do the same without pressing ctrl my selections from branch 1 disappears.
Hence, I am trying to get some other way for selecting multiple nodes from Tkinter tree (from different brances) without pressing ctrl key. (i.e either remembering my mouse selections or some checkbox or any other suggestion)
Here is a working code example which works for multiple selection in different branches using ctrl key but I need multiple selection for selecting nodes in different branches without pressing ctrl as using this I am not able to open new branch after selecting first one and if released nodes opens but choices disappears.
code:
import ttk
import Tkinter as tk
def select():
for i in tree.selection():
item_iid = i
print "".join([str(tree.item(i)['text'])])# for i in curItems])
root = tk.Tk()
tree = ttk.Treeview(root,show="tree")#, selectmode=EXTENDED)
tree.config(columns=("col1"))
#SUb treeview
style = ttk.Style(root)
style.configure("Treeview")
tree.configure(style="Treeview")
tree.insert("", "0", "item1", text="Branch1",)
tree.insert("", "1", "item2", text="Branch2")
#sub tree using item attribute to achieve that
tree.insert("item1", "1", text="FRED")
tree.insert("item1", "1", text="MAVIS")
tree.insert("item1", "1", text="BRIGHT")
tree.insert("item2", "2", text="SOME")
tree.insert("item2", "2", text="NODES")
tree.insert("item2", "2", text="HERE")
tree.pack(fill=tk.BOTH, expand=True)
tree.bind("<Return>", lambda e: select())
root.mainloop()
Expected: Select multiple nodes from different branches without pressing ctrl key
The first thing you need to do is to set selectmode to None:
tree = ttk.Treeview(root,show="tree", selectmode="none")
From here onward you can handle the selection events yourself.
Now modify your select function to react on focus change:
def select(event=None):
tree.selection_toggle(tree.focus())
print tree.selection()
And finally bind it to a key you prefer, using mouse click as sample below:
tree.bind("<ButtonRelease-1>", select)
In my "main" class I have this
tabs = Tabs(self.db)
self.setCentralWidget(tabs)
where I create a tab and show it, with Tabs inheriting QTabWidget. On the Tabs class I have this
self.livros = QWidget()
self.pessoas = QWidget()
self.addTab(self.livros, 'Livros')
self.addTab(self.pessoas, 'Pessoas')
tabela = Tabela(self.db)
where I add two tabs to my tabs. In each of them I'd like to exhibit a table. I created one table class (QTableWidget) called Tabela, where I set rows and columns and stuff, but I have no idea of how to add this table to the tabs. If I instead use it on the setCentralWidget on my main screen it works fine, but again, I'd like to exhibit in the tabs. How could I accomplish this (considering QTabWidget can't have a setCentralWidget)? Thanks very much!
I'm finding out this pattern of solving out my problem minutes after posting a question here. Anyways, the solution was pretty simple: The method setParent. On the class Tabs:
self.livros = QWidget()
self.pessoas = QWidget()
tabela = Tabela(self.db)
tabela.setParent(self.livros)
self.addTab(self.livros, 'Livros')
self.addTab(self.pessoas, 'Pessoas')
Hope this helps someone.
We're building a GUI interface with Python+tkinter.
The problem is when we want to set the view mode of an entity. I need to set the view mode or state of the treeview widget as 'disabled'.
How can we solve it?
Thanks for any support.
UPDATE
self.frmTab01.trvDetailorder.configure(selectmode='none')
I'm looking for a solution in which appart from disable the selection, affect the visualization of the widget just like an entry widget.
nbro is right, you need to change the Treeview style to make it look disabled. In addition, I also deactivated the possibility to open/close items when the Treeview is disabled using binding tricks on the mouse click.
In my example I added an entry so that you can compare the look on the two widgets. If you are using OS X or Windows, you might need to change the theme (style.theme_use("clam") should do) because their default themes are not very customizable.
from tkinter import Tk
from tkinter.ttk import Treeview, Style, Button, Entry
root = Tk()
def toggle_state():
if "disabled" in tree.state():
e.state(("!disabled",))
tree.state(("!disabled",))
# re-enable item opening on click
tree.unbind('<Button-1>')
else:
e.state(("disabled",))
tree.state(("disabled",))
# disable item opening on click
tree.bind('<Button-1>', lambda e: 'break')
style = Style(root)
# get disabled entry colors
disabled_bg = style.lookup("TEntry", "fieldbackground", ("disabled",))
disabled_fg = style.lookup("TEntry", "foreground", ("disabled",))
style.map("Treeview",
fieldbackground=[("disabled", disabled_bg)],
foreground=[("disabled", "gray")],
background=[("disabled", disabled_bg)])
e = Entry()
e.insert(0, "text")
e.pack()
tree = Treeview(root, selectmode='none')
tree.pack()
tree.insert("", 0, iid="1", text='1')
tree.insert("1", 0, iid='11', text='11')
Button(root, text="toggle", command=toggle_state).pack()
root.mainloop()
While adding component dynamically, 'this.container is null' is displayed in firebug.
I have a window with some combo boxes say combo1, combo2, combo3 and a label. Based on the selection value of combo3 the 'label' field is removed and replaced with combobox or text field. i do this my using
form.items.removeAt(4);
form.items.insert(4, newItem); #here newItem can be combox/textfield
form.doLayout();
The form resides inside a panel.
When above lines are execueted. 'this.container is null' is displayed and component fails to insert/add in appropiate position.
Any suggestions?
You should not be modifying the underlying items collection. Use the remove/insert methods on the container.
Try to comment those lines line-by-line to see which one produces error like
form.items.removeAt(4);
//form.items.insert(4, newItem); #here newItem can be combox/textfield
//form.doLayout();
form.items.removeAt(4);
form.items.insert(4, newItem); #here newItem can be combox/textfield
//form.doLayout();
form.items.removeAt(4);
form.items.insert(4, newItem); #here newItem can be combox/textfield
form.doLayout();
Your problem could take place because of inserted/replaced object is no yet prepared when you try to insert it. Give us your newItem initilization code.
Upd
Or you can wrap your changing components (label, combobox, textfields) in a panel with card layout. And on change of combo3 simply select exact card in that panel.