How to remove the text from label when checkbutton is not being checked? - checkbox

i'm working on this code.i want to make it display the text from the checkbutton on the label, and also remove the text when the checkbutton is not being checked.the first question is i can't remove it since the system responses
TypeError: list indices must be integers or slices, not str
the other question is i want to make a shuffle button which can shuffle the text in the label.i tried random.shuffle() but it seems doesn't work. thanks in advance!!
import tkinter as tk
import random
window = tk.Tk()
checkbutton_frame = tk.Frame(window)
checkbutton_frame.grid(column=0, row=1)
contentvar = tk.StringVar()
label = tk.Label(window, textvariable=contentvar,
bg='white', font=('Arial', 10), width=20, height=20, wraplength=50)
label.grid(column=6, row=1, padx=20,
pady=20, columnspan=2)
cb_list = ['ray', 'kevin', 'jacky']
cb_vars = []
checked = []
check_list = 1
def display():
for text, var in zip(cb_list, cb_vars):
if var.get():
checked.append(text)
contentvar.set(list(set(checked)))
else:
for i in checked:
del checked[i]
def shuffle():
random.shuffle(checked)
for r, element in enumerate(cb_list):
var = tk.BooleanVar(window, False)
cb = tk.Checkbutton(checkbutton_frame, variable=var,
text=element, command=display)
cb.grid(column=check_list, row=r, sticky='w')
cb_vars.append(var)
shuffle_button = tk.Button(window, text='SHUFFLE', command=shuffle)
shuffle_button.grid(column=8, row=2)
window.mainloop()

In the function display() you have:
else:
for i in checked:
del checked[i]
but checked is a string, so i will be a string. Try:
for i, dummy in enumerate(checked):
There were a few more things: the function display() appends to the list checked for checked items even if they are already there. This makes it look like the delete does not work. You can't see that you have to many of any item as you put them through a set before you load them into the label as set doesn't allow identical items.
Then you should set the contentvar after all processing, i.e. last in the function. Here's a version that works:
def display():
for text, var in zip(cb_list, cb_vars):
if var.get():
if text not in checked:
checked.append(text)
else:
if text in checked:
checked.remove(text)
contentvar.set(checked)
Now the texts in the label appear in the order you put them there.
The function shuffle() works just fine and shuffles the list checked. But you will have to load it into the label as well:
def shuffle():
random.shuffle(checked)
contentvar.set(checked)

Related

why are there no objects added to my table

I'm working on a lua script where I need a list of buttons to display. I have the following method to add a button to the list buttons:
function addButton(name, text, func, activeColor, passiveColor, xmin, xmax, ymin, ymax, type)
buttons[name] = {}
buttons[name]["text"] = text
buttons[name]["func"] = func
buttons[name]["active"] = false
buttons[name]["activeColor"] = getColorOrDefault(activeColor, ACTIVECOLORDEFAULT)
buttons[name]["passiveColor"] = getColorOrDefault(passiveColor, PASSIVECOLORDEFAULT)
buttons[name]["xmin"] = xmin
buttons[name]["xmax"] = xmax
buttons[name]["ymin"] = ymin
buttons[name]["ymax"] = ymax
buttons[name]["type"] = type
print("added: "..table.getn(buttons))
end
This function is called twice to add 2 buttons, but the output is:
added: 0
added: 0
what could be a reason my elements are not added to the table?
They're being added--You're just using the wrong method to detect them.
As you can read about in this question, using table.getn only returns the amount of array slots (numeric indexes, such as buttons[0] or buttons[23]. Note that this only counts as an array slot if there are no null indexes in between buttons[1] and buttons[23]!
Using this debugging code, we'll see that your items are indeed being added to the buttons table:
for name, button in pairs(buttons) do
print(name, button)
end
This is also how you'd get a list of your buttons :-)

Is there a way to use/get the value from a current entry window

I'm trying to get the variable that's entered in an entry widget on the Return key pressed event, but struggling a bit. What I have tried has always produced a blank result.
This code may look messy and hap-hazard, but it's only going to be a template that I'll be using on a current project!
I've tried that many things to get it to work, I can't remember what I have tried!
from collections import OrderedDict
try:
import tkinter as tk
except:
import Tkinter as tk
root = tk.Tk()
labelLIST = OrderedDict([
('Temp ID', 'tempID'),
('PO Number', "poNumber"),
('Reference', "reference"),
('Cut/Sample Date', "csDate"),
('Cut Number', "cut")
])
i = 0
e_loops = len(labelLIST)
print (e_loops)
def bval1(event=None):
for i in range(e_loops):
print (entries[i].get())
entries[0].delete(0, tk.END)
entries[0].insert(0, 'DISABLED')
entries[0].configure(state='disabled')
def bval2():
entries[0].configure(state='normal')
for i in range(e_loops):
entries[i].delete(0, tk.END)
entries[0].focus()
def onClick(event):
ent = event.widget # event.widget is the widget that called the event
print(ent.cget("text")) # Print the text for the selected button
event.widget.tk_focusNext().focus()
def enterEV(event):
# print(entries[].get())
event.widget.tk_focusNext().focus()
entries = []
for key, value in labelLIST.items():
label = tk.Label(root, text=key)
label.grid(row=i, column=0, sticky="ew", padx=1, pady=1)
entry = tk.Entry(root, width=10)
entry.grid(row=i, column=1, sticky="ew", padx=5, pady=5)
if value == "cut":
entry.bind('<Return>', bval1)
else:
# entry.bind('<Return>', enterEV)
entry.bind('<Return>', onClick)
entries.append(entry)
i = i+1
button = tk.Button(root, text="Submit", command=bval1)
button.grid(row=0, column=2, columnspan=9, sticky="ew")
button = tk.Button(root, text="Clear", command=bval2)
button.grid(row=1, column=2, columnspan=9, sticky="ew")
entries[0].focus()
tk.mainloop()
When enter/return is pressed, I want the value that is the entry box to be printed to terminal via the onClick event. But the output is always empty.
def onClick(event):
ent = event.widget # event.widget is the widget that called the event
print(ent.cget("text")) # Print the text for the selected button
event.widget.tk_focusNext().focus()
You don't use the text attribute to get the value in an Entry widget. Using cget("text") returns the value for the textvariable attribute. Since you haven't set that attribute, it will always be the empty string.
Instead, you need to call the get method:
print(ent.get())

Swift - Update and store position of a multiple programmatically created buttons

I have a button which creates other buttons based on the class Clip seen below. Those newly created buttons are added to an array and stored in a plist.
class Clip: Encodable, Decodable {
var name: String = ""
var xCoordinate: Int = 100
var yCoordinate: Int = 300
// more parameter will be added later on e.g color, scale etc..
}
Each button can be moved around the view and the new x & y coordinates are stored in a plist.
#objc func handlePan(sender: UIPanGestureRecognizer){
let uIViewSelected = sender.view!
switch sender.state {
case .began, .changed :
moveViewWithPan(view: uIViewSelected, sender: sender)
break
case .ended:
//Finds the position when the button is no longer being dragged
let x = Int(uIViewSelected.center.x)
let y = Int(uIViewSelected.center.y)
//clipArray[0] need to be the corresponding clicked button e.g clipArray[2]
clipArray[0].xCoordinate = x
clipArray[0].yCoordinate = y
saveData()
break
default:
break
}
}
The above works only if I create one button. When more buttons are added, the above lines only change the first clip from the array. I need a way to update the value to the correct button clicked.
How can identify the array position of the click button as I am creating all them programmatically? At the moment I am placing at value 0 of the clipArray.
clipArray[0].xCoordinate = x
clipArray[0].yCoordinate = y
I am not even sure if using a plist is the best way to store the buttons in the first place.
Any help or documentation would be much appreciated.
Thanks
Following from dfd response, I added tags to each button which are created and it solved the issue for now.
let x = Int(uIViewSelected.center.x)
let y = Int(uIViewSelected.center.y)
//clipArray.append(clip)
var tagNo = uIViewSelected.tag
clipArray[tagNo].xCoordinate = x
clipArray[tagNo].yCoordinate = y

jQuery: Each Loop Oddity

I want to go through all fields of a form and determine if the fields are populated with data. When all fields are given, I'd like a button save to appear.
This is the Fiddle with code, that works (!) ...
This is the same in JavaScript.
The jQuery-Object to iterate through:
formElements = $ 'form input[type="text"], form input[type="number"], form textarea'
The Function:
formFilled = ->
filled = true
formElements.each ->
if $(this).val().length is 0
filled = false
filled
The Event-Handler:
formElements.on 'keyup', (keyup) ->
keyup.preventDefault()
if formFilled()
save.show()
else
save.hide()
Any suggestions?
# I know the answer:
JavaScript validates the number-input fields and accepts only values that are numbers.
I stupidly tested those fields with text input ... silly.
The code is fine. Just the testing was bad. Sorry for wasting your time.
This works:
formInputs = $ 'input[type="text"], input[type="number"], textarea'
formFilled = ->
filled = true
formInputs.each ->
if $(this).val().length is 0
filled = false
filled
formInputs.on 'keyup', (keyup) ->
if formFilled()
saveButton.show()
else
saveButton.hide()

How to update a combo box with a list of items

I am trying to update the list of items in one combobox2 depending on the item selected in another - combobox1.
For example, if the user selects a file.mp3 in combobox1 then combobox2 will display a list of audio extension (.aac, .wav, .wma). However, if the user selects a file.flv from combobox1, combobox2 will display a list of video extensions (.mpg, mp4, .avi, .mov).
I initially thought I could accomplish this with if statements. The initial selection works, but there after, if you continue to choose different files, the combobox2 is not updated. I tried using an Event, but it didn't work.
Below if a very stripped-down version of the code so that you can get the gist:
import wx
import os
import sys
import time
from wx.lib.delayedresult import startWorker
class udCombo(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, 'd-Converter', size=(500, 310))
panel = wx.Panel(self, wx.ID_ANY)#Creates a panel over the widget
toolbar = self.CreateToolBar()
toolbar.Realize()
font = wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD)
font2 = wx.Font(7, wx.DECORATIVE, wx.NORMAL, wx.NORMAL)
directory = wx.StaticText(panel, -1, 'Path to media files: c:\\ffmpeg\\bin', (300, 13))
directory.SetFont(font2)
convertfile = wx.StaticText(panel, -1, 'File:', (270, 53))
convertfile.SetFont(font)
convertfile2 = wx.StaticText(panel, -1, 'Format:', (245, 83))
#Select Media
os.chdir("c:\\ffmpeg\\bin")
wrkdir = os.getcwd()
filelist = os.listdir(wrkdir)
self.formats1 = []
for filename in filelist:
(head, filename) = os.path.split(filename)
if filename.endswith(".avi") or filename.endswith(".mp4") or filename.endswith(".flv") or filename.endswith(".mov") or filename.endswith(".mpeg4") or filename.endswith(".mpeg") or filename.endswith(".mpg2") or filename.endswith(".wav") or filename.endswith(".mp3"):
self.formats1.append(filename)
self.format_combo1=wx.ComboBox(panel, size=(140, -1),value='Select Media', choices=self.formats1, style=wx.CB_DROPDOWN, pos=(300,50))
self.Bind(wx.EVT_COMBOBOX, self.fileFormats, self.format_combo1)
self.format_combo2=wx.ComboBox(panel, size=(100, -1),pos=(300,81))
self.Bind(wx.EVT_COMBOBOX, self.fileFormats, self.format_combo2)
def fileFormats(self, e):
myFormats = {'audio': ('.wav', '.wma', '.mp3'), 'video': ('.mpg', '.mp4', '.mpeg')}
bad_file = ['Media not supported']
myFile = self.format_combo1.GetValue()
f_exten = [x for x in myFormats['audio'] or myFormats['video'] if myFile.endswith(x)]
if f_exten[0] in myFormats['audio']:
self.format_combo2.SetItems(myFormats['audio'])
elif f_exten[0] in myFormats['video']:
self.format_combo2.SetItems(myFormats['video'])
else:
self.format_combo2.SetItems(bad_file)
if __name__ == '__main__':
app = wx.PySimpleApp()
frame = udCombo()
frame.SetSizeHints(500,310,500,310)
frame.Show()
app.MainLoop()
Traceback error:
Traceback (most recent call last):
File "C:\Users\GVRSQA004\Desktop\udCombo.py", line 86, in fileFormats
if f_exten[0] in myFormats['audio']:
IndexError: list index out of range
Use a dictionary to hold the two lists. Then when the user clicks something in the first widget, you can call the second combobox's SetItems(myDict[selection]) method or something along those lines. The error message is because you're trying to do something with a CommandEvent that it doesn't support. They don't have an "rfind" attribute, for example.
EDIT: The new code the OP posted doesn't work because it's only running the list comprehension against the first half of the OR statement. It never runs against the "video" portion, so it returns an empty list if the user chooses anything with a video format extension. It WILL work if you select an audio selection.
Personally, I would recommend creating a video extension list and an audio list. That would be easier to understand in the future should you need to fix it later.

Resources