I wrote this code (actually using Jupyter-Notebook):
import random
from ipywidgets import widgets
for ind in range(0,10):
print('Some text'+str(ind))
cb_inner = []
a = random.randint(0,3)
for el in range(0,3):
cb_value = True if el == a else False
A = widgets.Checkbox(value=cb_value, description='cb'+str(el))
cb_inner.append(A)
for_box_list = cb_inner
box = widgets.HBox(for_box_list)
display(box)
print('---'*41)
Now I have text strings and line of chackboxes for each. Only one checkbox active at the time. If I check another checkbox both of them become checked. What I want to do: if I check another checkbox, first one become disabled automatically (for group of checkboxes for every text message).
I suppose I need to create event for this. I found this:
Python ipywidgets checkbox events
But I can't understand how to implement it for all my boxes?
I thought a lot about list of checkboxes and creating events for them in a loop, but finally found simple way:
using RadioButtons. To handle the situation where all checkboxes in a line are turned off, I just added one more option in RadioButton arguments:
from ipywidgets import widgets
buttons_list = []
for ind in range(0,10):
print('My message',ind)
rb = widgets.RadioButtons(options=['cb1', 'cb2', 'noone checked'],
value='cb1')
display(rb)
print('---'*41)
buttons_list.append(rb)
Related
I have built a application which contained multi QComboBox.
On change, each one add buttons (about 100) in a grid layout, here a part of the called function:
for x in xrange(1,100):
my_list_shots.append(str(x))
x=2 # line 1 has the menu
y=1 # row
incrementLineX=1 # every 10 we go to line 2 (x+1) and reset incrementLine and y (row) to 1
for i in xrange(1,121):
try:
my_shot_number=my_list_shots[i]
my_shot_number = "%03d"%int(my_shot_number)
self.buttons = QtWidgets.QPushButton(my_shot_number,self)
self.buttons.setStyleSheet("background-color:brown;color:white")
self.buttons.clicked.connect(partial(self.my_open_mov,my_shot_number))
self.my_grid_layout.addWidget(self.buttons,x,y,1,1)
except Exception as e:
self.buttons = QtWidgets.QPushButton("",self)
self.buttons.setEnabled(False)
my_shot_number=""
y=y+1
incrementLineX=incrementLineX+1
if incrementLineX>10:
x=x+1
y=1
incrementLineX = 1
self.buttons.clicked.connect(partial(self.my_open_mov,my_shot_number))
and so on...
I worried about the memory, if I keep my window open all day long with many changes, I'll create each time 99 buttons? or not..?
How can I properly build my buttons?
Do I need to destroy them when I call the function?
In another way, what I want is to replace new buttons by old ones and I don't want to create thousand of buttons if I keep the windows open.
I just need the way to do it.
I have got the solution.
I use deleteLater() for each created buttons before to rebuild new ones.
# DELETE THE OLD WIDGET IN THE LAYOUT GRID
def clearShotsWidget(self):
while self.shotsWidgetLayout.count():
item = self.shotsWidgetLayout.takeAt(0)
item.widget().deleteLater()
self.shotsWidgetLayout.removeItem(item)
The other idea is to put all the build buttons in a list and delete them before to create the new ones.
Thanks a lot
Gui
I wanna build GUI and there is a button which Combobox adds every time the button is pressed. but i cant find out how to figure or code this concept
And, is there any other Widget? or is there other way to build my concept??
please some one help me..
the main concept without using tkinter is Like this shown . i want this concept to be made in Tkinter.
[THIS IS WHAT I TRIED BUT WHENEVER I PRESS THE BUTTON, ALL COMBOBOX ADDED WORKS TOGETHER (which means when i change the list name, all combobox also changes..)]
def Plus_EXT():
button_plus = Button(window3,justify = CENTER,command = Add_EXT, text= "+")
button_plus.grid(row=0,column=0)
def Add_EXT():
global Num
window3.update()
Num += 1
CEList1 = [x for x in os.listdir(cur_dir) if ('CE' in x.upper()) and ('.rpt' in x)]
RPT_EXT_file=ttk.Combobox(window3, values=CEList1,textvariable= EXT_String)
RPT_EXT_file.grid(row=8+Num,column=1)
RPT_EXT_file.set("FILE")
[MAIN CONCEPT WITHOUT USING TKINTER]
CE_Num= int(input("How Many EXTRA Chordae?: "))
User_File = input("Type the New File Name: ")
for Num_Of_EXT in range(CE_Num):
RPT_EXT_file = input("Type the RPT of EXTRA CHORDAE: ") + ".rpt"
EXTRA(User_File,RPT_EXT_file,Num_Of_EXT)
EXTRA_PLT(User_File,Num_Of_EXT)
the output i want is { everytime i press the button a new Combobox is added in the frame with the lists which works separately.}
The issue is that all your Combobox widgets are linked with same textvariable called EXT_String.So when you change the value of one Combobox widget, it updates same value in all of them.
I would suggest to keep a list of such variables and index that list using NUM in your loop to assign the textvariable.
UPDATE:
Just an example based on limited code shared in Add_EXT method:
global var_list
var_list.append(IntVar()) #Or StringVar(), whatever you are using
RPT_EXT_file=ttk.Combobox(window3, values=CEList1,textvariable=var_list[-1])
I wrote the below code to bind event and do operations on individual listbox items.
import tkinter as tk
root = tk.Tk()
custom_list = tk.Listbox(root)
custom_list.grid(row=0, column=0, sticky="news")
def onselect_listitem(event):
w = event.widget
index = int(w.curselection()[0])
value = w.get(index)
print(index, value, " color : ",custom_list.itemcget(index,'background'))
custom_list.itemconfig(index, fg='gray', selectforeground="gray")
custom_list.bind('<Double-Button-1>', onselect_listitem)
for k in range(20):
custom_list.insert(k, " --------- " + str(k))
root.mainloop()
I am having trouble using itemcget to get the background properties while itemconfig works properly. Everything else is working. Can someone tell me if there is something wrong? I am trying to obtain the current item background color via index of the item in the listbox. The part with custom_list.itemcget doesn't print anything.
Thanks
From the New Mexico tech Tkinter reference:
.itemcget(index, option)
Retrieves one of the option values for a specific line in the listbox. For option values, see itemconfig below. If the given option has not been set for the given line, the returned value will be an empty string.
So since you haven't set the background option, itemcget returns an empty string. You can see this working by changing the print to custom_list.itemcget(index,'fg'). The first time you doubleclick you get an empty sting because you haven't set it, the second time it prints gray.
I have a pyqtgraph Combobox which is defined as follows.
def __init__(self):
# some other stuff....
mylist=OrderedDict()
mylist['1k'] = 1
mylist['10k'] = 10
mylist['100k'] = 100
mylist['1M'] = 1000
self.myselectorA = ComboBox()
self.myselectorA.setItems(mylist)
self.myselectorA.currentIndexChanged.connect(self.selchangedA)
def selchangedA(self):
self.sq.setA(self.myselectorA.value())
if self.sq.gainlink:
self.sq.setB(100./self.myselectorA.value())
self.viewupdate = True
self.myselectorB.setValue(100./self.myselectorA.value())
self.viewupdate = False
The attached callback function selchangedA does some stuff which includes the optional update of a second Combobox (myselectorB). This update is dependant on a further variable gainlink.
I have the situation where I need to be able to detect the reselection of the same element in the combobox so that it updates the secondary combobox. Is this possible?
I understand that the user should just select the appropriate value on the secondary combobox but I want maximum flexibility for the user.
Instead of currentIndexChanged(int) you can connect the signal activated(int) (which is also emitted if the choice didn't change but an element was selected) to selchangedA(self, int). Besides that you can save the current index of the combo box in a separate variable and check in selchangedA if the value is the same as the previous and act accordingly.
I am writing a Tkinter program for the first time and have a question on radio buttons. What I am trying to do is this:
open a set of images (one at a time).
When an image is opened, annotate a value using the radio button.
Collect this value in a list
So, in this example I have 2 compounds and the list would have 2 annotations.
The problem I have is, if by mistake the user clicks radiobutton 2 instead of one, and then corrects him/herself, the list will have 4 items (3 for the first image, 1 for the second). How do I handle this, so that the list will have only 2 values?
import Tkinter as tk
from PIL import ImageTk, Image
from tkFileDialog import askopenfilename
cmp_list = ["VU435DR","VU684DR"]
li = []
li_final = []
def sel():
selection = str(var.get())
if selection == "1":
li.append("Antagonist")
elif selection == "2":
li.append("Agonist")
for i in range(len(cmp_list)):
root = tk.Tk()
var = tk.IntVar()
ig = str(cmp_list[i] + '.png')
img = ImageTk.PhotoImage(Image.open(ig))
panel = tk.Label(root,image=img)
panel.pack(side = "top",fill="none",expand="no")
#w = tk.Text(height=2,width=50)
#w.pack(side='right")
q = tk.Radiobutton(root,text="Antagonist",command=sel,value=1,variable=var)
q.pack()
r = tk.Radiobutton(root,text="Agonist",command=sel,value=2,variable=var)
r.pack()
root.mainloop()
print li
Your code is creating more than one instance of tk.Tk(). This is not how Tkinter was designed to work, and it will yield unpredictable behavior. A proper Tkinter program always has exactly one instance of tk.Tk().
If you need more than one window, for the second and subsequent windows you should create an instance of tk.Toplevel.
To answer your specific question about how to handle someone first hitting one radiobutton and then the other -- the problem is that you are unconditionally appending to your list each time they click on a radiobutton. The solution is to use some sort of flag or indicator to know whether one of the radiobuttons has been clicked, or change your code so that it doesn't matter.
Let's look at that second option - make it so it doesn't matter. When you open up a new image you can automatically append a value to your list. In this case, set it to None to say that nothing has been picked yet. Then, in sel, you would always replace the last element rather than append a new element, since you know that the last element always refers to the current compound.