I created a list of checkboxes with Tkinter but I would like to select all checkboxes with a single checkbox.
Here is part of my code:
root = tk.Tk()
root.title("SOMETHING")
buttons=[]
#If it is checked, then run the file
def callback():
for var, name in buttons:
if var.get():
subprocess.call("python " + "scripts/" + name)
for name in os.listdir("scripts"):
if name.endswith('.py') or name.endswith('.pyc'):
if name not in ("____.py", "_____.pyc"):
var = tk.BooleanVar()
cb = tk.Checkbutton(root, text=name, variable=var)
cb.pack()
buttons.append((var,name))
def select_all():
if var1.get():
for i in cb:
i.select(0,END)
def deselect_all():
if var2.get():
for i in cb:
i.deselect_set(0,END)
var1=tk.BooleanVar()
selectButton = tk.Checkbutton(root, text="Select All", command=select_all, variable=var1)
selectButton.pack()
var2=tk.BooleanVar()
deselectButton = tk.Checkbutton(root, text="None", command=deselect_all, variable=var2)
deselectButton.pack()
submitButton = tk.Button(root, text="Run", command=callback)
submitButton.pack()
root.mainloop()
When I run the file and press "select all", I get this error: 'str' object has no attribute 'select'.
Please help thanks :)
I have reviewed your code and attached a working tkinter code. Will leave you to resolve the issue with using subprocess.
My main comment is that your use of control variable and how to use it to get and set their value was inappropriate. I have remove the unnecessary codes. Also, shown you how to extract information from your list. Hope this helps your tkinter coding journey.
Working code:
import tkinter as tk
import os, subprocess
#If it is checked, then run the file
def callback():
if var.get():
for i in buttons:
cmd = "python3 " + filedir +"/" + i[1] #Note:Runs python3 and not python2
print(cmd)
subprocess.call(cmd)
def select_all(): # Corrected
for item in buttons:
v , n = item
if v.get():
v.set(0)
else:
v.set(1)
root = tk.Tk()
root.title("SOMETHING")
filedir = 'test'
buttons=[]
for name in os.listdir(filedir):
if name.endswith('.py') or name.endswith('.pyc'):
if name not in ("____.py", "_____.pyc"):
var = tk.IntVar()
var.set(0)
cb = tk.Checkbutton(root, text=name, variable=var)
cb.pack()
buttons.append((var,name))
var1=tk.IntVar()
var1.set(0)
selectButton = tk.Checkbutton(root, text="Select All", command=select_all,
variable=var1)
selectButton.pack()
submitButton = tk.Button(root, text="Run", command=callback)
submitButton.pack()
root.mainloop()
Related
I'm using Glade 3.20 but i don't known how to make a toggle column editable. I do not see any options.
screenshots
Please help me!
Look at this CellRendererToggle usage example (in python).
The source (in case the link breaks someday):
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
class CellRendererToggleWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="CellRendererToggle Example")
self.set_default_size(200, 200)
self.liststore = Gtk.ListStore(str, bool, bool)
self.liststore.append(["Debian", False, True])
self.liststore.append(["OpenSuse", True, False])
self.liststore.append(["Fedora", False, False])
treeview = Gtk.TreeView(model=self.liststore)
renderer_text = Gtk.CellRendererText()
column_text = Gtk.TreeViewColumn("Text", renderer_text, text=0)
treeview.append_column(column_text)
renderer_toggle = Gtk.CellRendererToggle()
renderer_toggle.connect("toggled", self.on_cell_toggled)
column_toggle = Gtk.TreeViewColumn("Toggle", renderer_toggle, active=1)
treeview.append_column(column_toggle)
renderer_radio = Gtk.CellRendererToggle()
renderer_radio.set_radio(True)
renderer_radio.connect("toggled", self.on_cell_radio_toggled)
column_radio = Gtk.TreeViewColumn("Radio", renderer_radio, active=2)
treeview.append_column(column_radio)
self.add(treeview)
def on_cell_toggled(self, widget, path):
self.liststore[path][1] = not self.liststore[path][1]
def on_cell_radio_toggled(self, widget, path):
selected_path = Gtk.TreePath(path)
for row in self.liststore:
row[2] = (row.path == selected_path)
win = CellRendererToggleWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()
I am writing a script which has an UI in Maya. I have a text box that is supposed to constantly update based on the last item in the users selection list. How would I go about something that constantly keeps checken whithout having the user to push a button or something manually to call a function.
Thx
Edit: Cool that is what I was looking for. Thx. Your script works just fine. I tried implementing that into my big script which resulted in that every button in the UI had to be pushed twice in order to take effect. But I will deal with that later. However testing my own version in a seperate script as follows sometimes produces the following error: 'sl' must be passed a boolean argument
#________________________________________________________________________________________________________________________________________________
import maya.cmds as cmds
idManagerUI = cmds.window(title='Vray ID Manager', s = False, wh = (305,500))
cmds.columnLayout(adj = True)
cmds.text (l = '__________________________________________ \n your current selection has this ID: \n')
curSelTxt = cmds.text (l = '', backgroundColor = [0.2, 0.2, 0.2])
def update_label(*_):
upCurrentObjectSel = cmds.ls(sl=True)
upCurrentObjectSelShapes = cmds.listRelatives(upCurrentObjectSel)
upLastobj = upCurrentObjectSelShapes[-1]
print upLastobj
cmds.text(curSelTxt, e=True, label = upLastobj)
cmds.scriptJob(event=("SelectionChanged", update_label), p= curSelTxt)
cmds.showWindow(idManagerUI)
Also, making two of these ScriptJobs makes the script stop working properly entirely.
#________________________________________________________________________________________________________________________________________________
import maya.cmds as cmds
idManagerUI = cmds.window(title='Vray ID Manager', s = False, wh = (305,500))
cmds.columnLayout(adj = True)
cmds.text (l = '__________________________________________ \n your current selection has this ID: \n')
curSelObjTxt = cmds.text (l = '', backgroundColor = [0.2, 0.2, 0.2])
curSelShadTxt = cmds.text (l = '', backgroundColor = [0.2, 0.2, 0.2])
def update_obj_label(*_):
upCurrentObjectSel = cmds.ls(sl=True)
upCurrentObjectSelShapes = cmds.listRelatives(upCurrentObjectSel)
upLastobj = upCurrentObjectSelShapes[-1]
objID = cmds.getAttr(upLastobj + '.vrayObjectID')
print objID
cmds.text(curSelObjTxt, e=True, label = objID)
def update_shader_label(*_):
upCurrentShaderSel = cmds.ls(sl=True, type= shaderTypes)
upCurrentShaderSelLast = upCurrentShaderSel[-1]
shadID = cmds.getAttr(upCurrentShaderSelLast + '.vrayMaterialId')
cmds.text(curSelShadTxt, e=True, label = shadID)
print shadID
cmds.scriptJob(event=("SelectionChanged", update_obj_label), p= curSelObjTxt)
cmds.scriptJob(event=("SelectionChanged", update_shader_label), p= curSelShadTxt)
cmds.showWindow(idManagerUI)
Edit:
still your latest version of the script produces the error from time to time.
Also, I noticed in my own version of it, that it sometimes works lovely, then not at all, once I e.g. switched my active window to Firefox or so and then get back to Maya, and sometimes it does not work at all. That is with just one of the functions in my script. With both of them (s.below) it is totally unusable. Very unstable results.
import maya.cmds as cmds
def curSelTxtShower():
idManagerUI = cmds.window(title='Vray ID Manager', s = False, wh = (305,500))
cmds.columnLayout(adj = True)
cmds.text (l = '__________________________________________ \n your current selection has this ID: \n')
curSelObjTxt = cmds.text (l = '', backgroundColor = [0.2, 0.2, 0.2])
curSelShadTxt = cmds.text (l = '', backgroundColor = [0.2, 0.2, 0.2])
def update_obj_label(*_):
upCurrentObjectSelShapes = cmds.listRelatives(s=True) or ["nothing selected"]
upLastobj = upCurrentObjectSelShapes[-1]
if upLastobj is not "nothing selected":
if cmds.attributeQuery('vrayObjectID', node = upLastobj, ex = True) is True:
objID = cmds.getAttr(upLastobj + '.vrayObjectID')
cmds.text(curSelObjTxt, e=True, label = objID)
else:
cmds.text(curSelObjTxt, e=True, label = 'curSel has no ObjID assigned')
def update_shader_label(*_):
upCurrentShaderSel = cmds.ls(sl=True, type= shaderTypes)
upCurrentShaderSelLast = upCurrentShaderSel[-1]
if cmds.attributeQuery('vrayMaterialId', node = upCurrentShaderSelLast, ex = True) is True:
shadID = cmds.getAttr(upCurrentShaderSelLast + '.vrayMaterialId')
cmds.text(curSelShadTxt, e=True, label = shadID)
print shadID
else:
cmds.text(curSelShadTxt, e=True, label = 'curSel has no MatID assigned')
cmds.scriptJob(event=("SelectionChanged", lambda *x: update_obj_label()), p= curSelObjTxt)
cmds.scriptJob(event=("SelectionChanged", lambda *x: update_shader_label()), p= curSelShadTxt)
cmds.showWindow(idManagerUI)
curSelTxtShower()
You need to use a scriptJob to watch for selection change events and respond. You'll want to parent the scriptJob to a particular piece of UI so it deletes itself when the UI object goes away.
An absolutely minimal example looks like this:
import maya.cmds as cmds
wind = cmds.window()
col = cmds.columnLayout()
txt = cmds.text(label="", width = 240)
def update_label(*_):
cmds.text(txt, e=True, label = str(cmds.ls(sl=True)))
cmds.scriptJob(event=("SelectionChanged", update_label), p= txt)
cmds.showWindow(wind)
Edit
This version of OP's code helps avoid the false error message. the actual error was happening when due to an empty selection - but the scriptJob falsely reports it in the previous line:
def scoped():
idManagerUI = cmds.window(title='Vray ID Manager', s = False, wh = (305,500))
cmds.columnLayout(adj = True)
cmds.text (l = '__________________________________________ \n your current selection has this ID: \n')
curSelTxt = cmds.text (l = '', backgroundColor = [0.2, 0.2, 0.2])
def update_label(*_):
# listRelatives works off the current selection already
upCurrentObjectSelShapes = cmds.listRelatives(s=True) or ["nothing selected"]
upLastobj = upCurrentObjectSelShapes[-1]
cmds.text(curSelTxt, e=True, label = upLastobj)
cmds.showWindow(idManagerUI)
cmds.scriptJob(event=("SelectionChanged", update_label), p= idManagerUI)
scoped()
I have downloaded an archive of mails from my gmail account. I am using the following python(2.7) code taken from a blog to convert the contents of the archive to csv.
import mailbox
import csv
writer = csv.writer(open(("clean_mail.csv", "wb"))
for message in mailbox.mbox('archive.mbox'):
writer.writerow([message['subject'], message['from'], message['date']])
I want to include the body of the mail(the actual messages) too...but couldn't figure out how. I have not used python earlier, can someone help please? I have used other SO options given but couldn't get through.
To do the same task, I have used the following code too: but get indentation error for line 60: return json_msg. I have tried different indentation options but nothing improved.
import sys
import mailbox
import email
import quopri
import json
import time
from BeautifulSoup import BeautifulSoup
from dateutil.parser import parse
MBOX = 'Users/mymachine/client1/Takeout/Mail/archive.mbox'
OUT_FILE = 'Users/mymachine/client1/Takeout/Mail/archive.mbox.json'
def cleanContent(msg):
msg = quopri.decodestring(msg)
try:
soup = BeautifulSoup(msg)
except:
return ''
return ''.join(soup.findAll(text=True))
# There's a lot of data to process, and the Pythonic way to do it is with a
# generator. See http://wiki.python.org/moin/Generators.
# Using a generator requires a trivial encoder to be passed to json for object
# serialization.
class Encoder(json.JSONEncoder):
def default(self, o): return list(o)
def gen_json_msgs(mb):
while 1:
msg = mb.next()
if msg is None:
break
yield jsonifyMessage(msg)
def jsonifyMessage(msg):
json_msg = {'parts': []}
for (k, v) in msg.items():
json_msg[k] = v.decode('utf-8', 'ignore')
for k in ['To', 'Cc', 'Bcc']:
if not json_msg.get(k):
continue
json_msg[k] = json_msg[k].replace('\n', '').replace('\t', '').replace('\r', '')\
.replace(' ', '').decode('utf-8', 'ignore').split(',')
for part in msg.walk():
json_part = {}
if part.get_content_maintype() == 'multipart':
continue
json_part['contentType'] = part.get_content_type()
content = part.get_payload(decode=False).decode('utf-8', 'ignore')
json_part['content'] = cleanContent(content)
json_msg['parts'].append(json_part)
then = parse(json_msg['Date'])
millis = int(time.mktime(then.timetuple())*1000 + then.microsecond/1000)
json_msg['Date'] = {'$date' : millis}
return json_msg
mbox = mailbox.UnixMailbox(open(MBOX, 'rb'), email.message_from_file)
f = open(OUT_FILE, 'w')
for msg in gen_json_msgs(mbox):
if msg != None:
f.write(json.dumps(msg, cls=Encoder) + '\n')
f.close()
Try this.
import mailbox
import csv
writer = csv.writer(open(("clean_mail.csv", "wb"))
for message in mailbox.mbox('archive.mbox'):
if message.is_multipart():
content = ''.join(part.get_payload() for part in message.get_payload())
else:
content = message.get_payload()
writer.writerow([message['subject'], message['from'], message['date'],content])
or this:
import mailbox
import csv
def get_message(message):
if not message.is_multipart():
return message.get_payload()
contents = ""
for msg in message.get_payload():
contents = contents + str(msg.get_payload()) + '\n'
return contents
if __name__ == "__main__":
writer = csv.writer(open("clean_mail.csv", "wb"))
for message in mailbox.mbox("archive.mbox"):
contents = get_message(message)
writer.writerow([message["subject"], message["from"], message["date"],contents])
Find the documentation here.
A little improvement of Rahul snippet for multipart content:
import sys
import mailbox
import csv
from email.header import decode_header
infile = sys.argv[1]
outfile = sys.argv[2]
writer = csv.writer(open(outfile, "w"))
def get_content(part):
content = ''
payload = part.get_payload()
if isinstance(payload, str):
content += payload
else:
for part in payload:
content += get_content(part)
return content
writer.writerow(['date', 'from', 'to', 'subject', 'content'])
for index, message in enumerate(mailbox.mbox(infile)):
content = get_content(message)
row = [
message['date'],
message['from'].strip('>').split('<')[-1],
message['to'],
decode_header(message['subject'])[0][0],
content
]
writer.writerow(row)
I have read a good solution for establishing a default numerical value on a Tkinter Spinbox widget when you use the from_ to options. But I have not seen a single one that can help establish a value (numerical or string) from a tuple.
My code is as follows, and is intended to set a default value in a Tkinter Spinbox widget from a tuple:
from Tkinter import *
root = Tk()
root.geometry('200x200+50+50')
root.title('Prueba')
t = ('One', 'Two', 'Three', 'Four', 'Five')
v = t[3]
var = StringVar()
var.set(v)
sb = Spinbox(root, values=t, textvariable=var, width=10)
sb.place(x=5, y=15)
root.mainloop()
Another variant that I have tried is the following:
from Tkinter import *
root = Tk()
root.geometry('200x200+50+50')
root.title('Prueba')
var = StringVar()
var.set('Four')
sb = Spinbox(root, ('One', 'Two', 'Three', 'Four', 'Five'), textvariable=var, width=10)
sb.place(x=5, y=15)
root.mainloop()
The only way the set method works on Spinbox (and which I took from here) is the following and only works with numbers and within a range established as options in the Spinbox widget:
from Tkinter import *
root = Tk()
root.geometry('200x200+50+50')
root.title('Prueba')
var = StringVar()
var.set(4)
sb = Spinbox(root, from_=1, to=5, textvariable=var, width=10)
sb.place(x=5, y=15)
root.mainloop()
Can please anyone help me to find out how to establish a default value in a Tkinter Spinbox from a Tuple? I will appreciate that greatly!
If you move the line var.set(v) to be after creating the widget, the default value will be set.
var = StringVar()
sb = Spinbox(root, values=t, textvariable=var, width=10)
var.set(v)
I want to use UIPickerView to select a number and assign the selected number to a label. I worked out how to do it using the ib gem and using interface builder to create the initial interface and it works fine. However, I would like to do it purely using RubyMotion code and I can't for the life of me get it to work. The best I have managed is for the label to return True and not a number.
I'm using the following standard code for the picker view delegate methods:
def pickerView(pickerView, numberOfRowsInComponent:component)
101
end
def pickerView(pickerView, titleForRow:row, forComponent:component)
row.to_s
end
def numberOfComponentsInPickerView (pickerView)
1
end
def pickerView(pickerView, didSelectRow:row, inComponent:component)
end
def pickerView(pickerView, titleForRow:row, forComponent:component)
" #{row+1}"
end
def submit
totals.addTotals(myPicker.selectedRowInComponent(0))
end
and then the label text is populated like this:
numLabel = UILabel.new
numLabel.text = "Number Selected: #{submit}"
numLabel.font = UIFont.boldSystemFontOfSize(18)
numLabel.frame = [[20,320],[260,340]]
numLabel.numberOfLines = 2
numLabel.adjustsFontSizeToFitWidth = 'YES'
self.view.addSubview numLabel
The totals is a shared client.
Here is how to do it in RubyMotion alone. Note that the label and picker are set up in viewDidLoad. The label gets updated in pickerView:didSelectRow:inComponent:
app_delegate.rb
class AppDelegate
def application(application, didFinishLaunchingWithOptions:launchOptions)
#window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
#window.rootViewController = PickerDemo.new
#window.makeKeyAndVisible
true
end
end
picker_demo.rb
class PickerDemo < UIViewController
def viewDidLoad
view.backgroundColor = UIColor.whiteColor
#numLabel = UILabel.new
#numLabel.text = "Number Selected: 0"
#numLabel.font = UIFont.boldSystemFontOfSize(18)
#numLabel.frame = [[20,100],[260,120]]
#numLabel.numberOfLines = 2
#numLabel.adjustsFontSizeToFitWidth = true
view.addSubview(#numLabel)
#picker = UIPickerView.new
#picker.frame = [[0, 183], [320, 162]]
#picker.delegate = self
#picker.dataSource = self
view.addSubview(#picker)
end
def pickerView(pickerView, numberOfRowsInComponent:component)
101
end
def pickerView(pickerView, titleForRow:row, forComponent:component)
row.to_s
end
def numberOfComponentsInPickerView(pickerView)
1
end
def pickerView(pickerView, didSelectRow:row, inComponent:component)
#numLabel.text = "Number Selected: #{row}"
end
end