I have written up a simple UI that requires user to select something from a drop-down list, then using that selection, the code will executes the rest of the stuff
Right now, I am having 2 issues..
1. The 'value' is not exactly returning, as soon as a Format is selected and the OK button is hit... Am I missing something?
2. How can I make my UI closes upon a OK button has been selected?
import maya.cmds as cmds
def mainCode():
...
...
print "UI popping up"
showUI()
print "A format has been selected"
cmds.optionMenu('filmbackMenu', edit = True, value = xxx ) # <-- I want to grab the value from the menu selection and input into this 'value' flag
...
...
def showUI():
if cmds.window("UI_MainWindow", exists = True):
cmds.deleteUI("UI_MainWindow")
cmds.window("UI_MainWindow", title = "User Interface Test", w = 500, h = 700, mnb = False, mxb = False, sizeable = False)
cmds.columnLayout("UI_MainLayout", w = 300, h =500)
cmds.optionMenu("UI_FormatMenu", w = 250, label = "Select a Format")
list01 = ['itemA-01', 'itemB-02', 'itemC-02', 'itemD-01', 'itemE-01', 'itemF-03']
for x in list01:
cmds.menuItem(label = str(x))
cmds.button("UI_SelectButton", label = "OK", w = 200, command=ObjectSelection)
cmds.showWindow("UI_MainWindow") #shows window
def ObjectSelection(*args):
currentFormat = cmds.optionMenu("UI_FormatMenu", query=True, value=True)
print currentFormat
return currentFormat
Use python dictionnaries or class to pass data in your script.
I really don't understand what the problem is.
When you say : "The 'value' is not exactly returning", what do you mean ? Can you tell us what do you get and what do you expect ?
def mainCode():
...
...
showUI()
cmds.optionMenu('filmbackMenu', edit = True, value = xxx ) # <-- I want to grab the value from the menu selection and input into this 'value' flag
...
Here the value selection from the "input value", I guess it is :
cmds.optionMenu('filmbackMenu', edit = True, value = ObjectSelection())
But as there is not filmbackMenu in your code, I'm not sure.
Your second question has been answered on google groups by Justin. You just have to do :
def ObjectSelection(*args):
currentFormat = cmds.optionMenu("UI_FormatMenu", query=True, value=True)
cmds.deleteUI("UI_MainWindow")#close the UI
print currentFormat
return currentFormat
Or maybe "upon a OK button has been selected?" doesn't mean "OK button pressed" ?
If you want to see how use dictionnaries, you can read this other post where I have answered : Maya Python - Using data from UI
You are in a good path to using partial, I recommend you to read about it : Calling back user input values inside maya UI
--- EDIT ---
I tried to create a fully functionnal example :
import maya.cmds as cmds
uiDic = {}
uiDic['this']= 1
def ui_refresh(*args):
uiDic['this'] = cmds.optionMenu("UI_FormatMenu", query=True, value=True)
return uiDic['this']
def showUI():
if cmds.window("UI_MainWindow", exists = True):
cmds.deleteUI("UI_MainWindow")
cmds.window("UI_MainWindow", title = "User Interface Test", w = 500, h = 700, mnb = False, mxb = False, sizeable = False)
cmds.columnLayout("UI_MainLayout", w = 300, h =500)
cmds.optionMenu("UI_FormatMenu", w = 250, label = "Select a Format")
list01 = ['itemA-01', 'itemB-02', 'itemC-02', 'itemD-01', 'itemE-01', 'itemF-03']
for x in list01:
cmds.menuItem(label = str(x))
cmds.button("UI_SelectButton", label = "OK", w = 200, command=ObjectSelection)
uiDic['om_filmback'] = cmds.optionMenu('filmbackMenu' )
list01 = ['itemA-01', 'itemB-02', 'itemC-02', 'itemD-01', 'itemE-01', 'itemF-03']
for x in list01:
cmds.menuItem(label = str(x))
cmds.showWindow("UI_MainWindow") #shows window
def ObjectSelection(*args):
cmds.optionMenu(uiDic['om_filmback'], edit = True, value=ui_refresh())
showUI()
I'm making a small GUI application that deals with grades and whatnot and outputs the highest grades and etc.
Here's a part of the code:
root = Tk()
gradeList = []
def addGradeObject(name, percentage):
gradeList.append(Grade(name, percentage))
updateOutput()
print(gradeList)
def undoAdd():
try:
gradeList.pop(len(gradeList) - 1)
updateOutput()
print(gradeList)
except Exception:
pass
def updateOutput():
highestGrade.setText(highest_grade(gradeList))
lowestGrade.setText(lowest_grade(gradeList))
numFailed.setText(num_failed(gradeList))
addButton = Button(text = "Add Grade", command = lambda: addGradeObject (entryA.get(), entryB.get())).grid(row = 1, column = 4)
undoButton = Button(text = "Undo", command = undoAdd).grid(row = 2, column = 4)
entryA = Entry()
entryA.grid(row = 1, column = 1)
entryB = Entry()
entryB.grid(row = 1, column = 2)
highestGrade = Entry()
highestGrade.grid(row = 2, column = 1)
lowestGrade = Entry()
lowestGrade.grid(row = 3, column = 1)
numFailed = Entry()
numFailed.grid(row = 4, column = 1)
root.title("Grade Checker")
root.mainloop()
The problem is I'm getting this error:
AttributeError: 'Entry' object has no attribute 'setText'
I don't understand. When you create an Entry box, doesn't the object of class "Entry" have an attribute/method that allows you to set text to it? I really don't know why it's not working
Entry methods can be found here. As far as I can tell, there is no setText method. There is however an insert method that you could use to set the text (though you might wand to delete the current text first).
def set_text(entry, text):
entry.delete(0, tkinter.END)
entry.insert(0 text)
Alternatively, you can hook the entry up to a StringVar and use it's .set() and .get() methods. e.g. (from the linked docs above):
v = StringVar()
e = Entry(master, textvariable=v)
e.pack()
v.set("a default value")
s = v.get()
I am currently trying to build my first GUI application through python's standard Tkinter. I soon came to grips with the computers coordinate system, and indeed I found I could pan things out as I so wish, but I came to the realisation that a drag and drop feature would be far superior then specifying coordinates explicitly. I am close, but I have one major problem; Whilst I can keep the value of the coords of a single widget in relation to where I dragged it last, I cannot do this for multiple widgets.
This is the code I have created so far:
from tkinter import *
root = Tk()
class Move_Shape:
data = {'x': 0, 'y': 0}
canvas = Canvas(width = root.winfo_screenwidth(), height = root.winfo_screenheight())
shape_coords = open('Shape_coords.py', 'r')
def __init__(self, shape, fill = 'White', *coords):
new_coords = self.shape_coords.readline().split(',')
if coords == (): coords = new_coords
if shape == 'line':
tag = 'line'
self.id = self.canvas.create_line(coords, tags = tag, fill = fill)
elif shape == 'rectangle':
tag = 'rect'
self.id = self.canvas.create_rectangle(coords, tags = tag, fill = fill)
... More code
self.canvas.tag_bind(tag, '<Button-1>', self.click)
self.canvas.tag_bind(tag, '<Button1-Motion>', self.track)
self.canvas.tag_bind(tag, '<ButtonRelease-1>', self.release)
self.canvas.grid()
def click(self, event):
self.data.update({'x': event.x, 'y': event.y})
self.item = self.canvas.find_closest(self.data['x'], self.data['y'])
def track(self, event):
x, y = event.x - self.data['x'], event.y - self.data['y']
self.canvas.move(self.item, x, y)
self.data.update({'x': event.x, 'y': event.y})
def release(self, event):
self.data.update({'x': event.x, 'y': event.y})
coords = str(self.canvas.coords(self.item))
coords = coords[1:-1]
shape_coords = open ('Shape_coords.py', 'a')
shape_coords.write(coords)
shape_coords.write('\n')
shape_coords.close()
Move_Shape('rectangle', 'blue', 50, 50, 100, 100)
Move_Shape( 'oval', 'green', 50, 50, 100, 100)
Move_Shape( 'arc', 'red', 50, 50, 100, 100)
mainloop()
If I was to start with an initial pair of coords, I would very much like to be able to delete the coords and pick up where I left of, or rather, where the shape left of. Appending the coordinates to a file does not work, the main reason being that I cannot return the final value of an updated dictionary, after exiting the mainloop.
I did some research before hand, and looked into data persistence. So I came across the Module, pickle, for the first time. Through others examples online, I managed to 'dump' the values into another file, however, if some variable, call it a, changes multiple times, those values are all appended within the file (which leads us back to square one). I would like to know if there is a way to make it so that only the last value assigned to a object through a variable, is stored.
I would go through the pickle module myself, but it's terminology overwhelms me, and I do not know what to look up in specific when it comes to data persistence.
I am the OP(internet slang for original poster), and I believe I have found an answer to my question. This just serves for those whom may run into a similar situation, not to mention that others can provide better solutions, for am sure they exist, but this is one none the less.
So, my initial solution was to store the values in a dictionary, and then append that to a file to read back, however there was no way of obtaining the final value, that is, I had to update the dictionary and append it to the file, however I could not obtain the final value.
After that, I looked into data persistence, where you assign a value to a variable, which refers to an object, however, if I assigned a value to variable 'foobar', and 'pickle' it, (erm... writing it to a file, but in bytes), and then assign another value to 'foobar', you end up storing both of those values, rather than storing one constant value for the same object.
What I did then, was to combine these two approaches, of updating a dictionary, and pickling objects. I pickled a dictionary to which I could update, and since it was referring to the same object, then only one value was binded to the dictionary. I don't know why this does not work for mutable sequences, but I suppose that whilst the variable stays the same, it points to multiple objects, though I may be wrong, so if someone could add some clarification that would be much appreciated.
So now everything works, and I can move items on the canvas/widgets to my hearts desire.
Remember, if you need to write to a file where you only want to store a single value for a given object, whose value in dependent on time, use and read up an pickle, here is the link:
https://docs.python.org/3.4/library/pickle.html
Here are exapmles of pickle in action:
This one in particular describes to how save a dict using pickle:
How can I use pickle to save a dict?
Good wiki reference:
https://wiki.python.org/moin/UsingPickle
Here is the latest source code, you may adapt it as you see fit, please note, the indentation may be wrong, because pasting this into here did some weird things with the indentation levels, but am sure you can handle that:
from tkinter import *
import pickle
import os
import __main__
class Drag_Shape:
filename = os.path.basename(__main__.__file__)
filename = filename[:filename.index('.')]+'_coords.py'
print(__main__.__file__)
if os.path.isfile(filename) == False:
foorbar = open(filename, 'w')
foorbar.close()
if os.path.getsize(filename) == 0: coords_dict = {}
else:
with open(filename, 'rb') as shape_cords:
coords_dict = pickle.load(shape_cords)
data = {'x': 0, 'y': 0}
def __init__(self, canvas, *coords, shape = 'rect', fill = 'white', outline = 'black', width = 1, activefill = '',
activeoutline = 'black', activewidth = 1, disabledfill = '', disabledoutline = 'black', disabledwidth = 1,
state = ''):
self.canvas = canvas
self.shape = shape.lower()
print(shape)
print(coords)
for i in self.coords_dict.keys():
if shape.lower() in i: shape = i.lower()
if coords != (): self.coords_dict.update({shape:coords})
else: coords = self.coords_dict[shape]
if shape in 'line':
tag = 'line'
ID = canvas.create_line(coords, tags = tag, fill = fill, width = width,
activefill = activefill, activewidth = activewidth, disabledfill = disabledfill,
disabledwidth = disabledwidth, state = '')
elif shape in 'rectangle':
tag = 'rect'
ID = canvas.create_rectangle(coords, tags = tag, fill = fill, outline = outline, width = width,
activefill = activefill, activeoutline = activeoutline, activewidth = activewidth, disabledfill = disabledfill,
disabledoutline = disabledoutline, disabledwidth = disabledwidth, state = '')
elif shape in 'oval':
tag = 'oval'
ID = canvas.create_oval(coords, tags = tag, fill = fill, outline = outline, width = width,
activefill = activefill, activeoutline = activeoutline, activewidth = activewidth, disabledfill = disabledfill,
disabledoutline = disabledoutline, disabledwidth = disabledwidth, state = '')
elif shape in 'arc':
tag = 'arc'
ID = canvas.create_arc(coords, tags = tag, fill = fill, outline = outline, width = width,
activefill = activefill, activeoutline = activeoutline, activewidth = activewidth, disabledfill = disabledfill,
disabledoutline = disabledoutline, disabledwidth = disabledwidth, state = '')
elif shape in 'polygon':
tag = 'poly'
ID = canvas.create_polygon(coords, tags = tag, fill = fill, outline = outline, width = width,
activefill = activefill, activeoutline = activeoutline, activewidth = activewidth, disabledfill = disabledfill,
disabledoutline = disabledoutline, disabledwidth = disabledwidth, state = '')
elif shape in 'window':
tag = 'win'
ID = canvas.create_window(coords, tags = tag, fill = fill)
elif shape in 'text':
tag = 'text'
ID = canvas.create_text(coords, tags = tag, fill = fill)
elif shape in 'image':
tag = 'img'
ID = canvas.create_image(coords, tags = tag, fill = fill)
elif shape in 'bitmap':
tag = 'bitmap'
ID = canvas.create_bitmap(coords, tags = tag, fill = fill)
self.ID = ID
self.tag = tag
with open(self.filename, 'wb') as shape_coords:
pickle.dump(self.coords_dict, shape_coords)
canvas.tag_bind(tag, '<Button-1>', self.click)
canvas.tag_bind(tag, '<Button1-Motion>', self.track)
canvas.tag_bind(tag, '<ButtonRelease-1>', self.release)
def click(self, event):
self.data.update({'x': event.x, 'y': event.y})
self.item = self.canvas.find_closest(self.data['x'], self.data['y'])
return self.item
def track(self, event):
x, y = event.x - self.data['x'], event.y - self.data['y']
self.canvas.move(self.item, x, y)
self.data.update({'x': event.x, 'y': event.y})
def release(self, event):
self.data.update({'x': event.x, 'y': event.y})
coords = list(self.canvas.coords(self.item))
self.coords_dict.update({self.shape : coords})
with open(self.filename, 'wb') as shape_coords:
pickle.dump(self.coords_dict, shape_coords)
return self.ID
Three important things:
You must specify the coords with a list, or possibly a tuple or other containers (though I have only tested on lists)
If you want to actually save the location of the shape on the canvas, delete the original coords that was used to create the shape, otherwise it will just reset back to it's original position, and so it should.
A file is automagically created when you use the class outside of the file that it belong too. If the file is called 'foorbar.py', than a file called 'foorbar.coords.py', is created in the same folder. If you touch this in anyway, well just don't, it will mess things up.
I know I said three, but am going to push this 'community wiki' sign and see what it does, sorry if this has an undesired effect.
I am new to python and recently i make dictionary using Python and Sqlite3 with tkinter.
When I run the code it returns multiple line in IDLE but in the GUI its only display the last result. I would like to display all the information in the GUI. Thanks you for any help and suggestion.
import tkinter
import sqlite3
class Dictionary:
def __init__(self,master =None):
self.main_window = tkinter.Tk()
self.main_window.title("Lai Mirang Dictionary")
self.main_window.minsize( 600,400)
self.main_window.configure(background = 'paleturquoise')
self.frame1 = tkinter.Frame()
self.frame2= tkinter.Frame(bg = 'red')
self.frame3 =tkinter.Text( foreground = 'green')
self.frame4 = tkinter.Text()
self.lai_label = tkinter.Label(self.frame1,anchor ='nw',font = 'Times:12', text = 'Lai',width =25,borderwidth ='3',fg='blue')
self.mirang_label = tkinter.Label(self.frame1,anchor ='ne',font = 'Times:12', text = 'Mirang',borderwidth ='3',fg ='blue')
self.lai_label.pack(side='left')
self.mirang_label.pack(side = 'left')
self.kawl_buttom= tkinter.Button(self.frame2 ,fg = 'red',font = 'Times:12',text ='Kawl',command=self.dic,borderwidth ='3',)
self.lai_entry = tkinter.Entry(self.frame2, width= 28, borderwidth ='3',)
self.lai_entry.focus_force()
self.lai_entry.bind('<Return>', self.dic,)
self.lai_entry.configure(background = 'khaki')
self.lai_entry.pack(side='left')
self.kawl_buttom.pack(side = 'left')
self.value = tkinter.StringVar()
self.mirang_label= tkinter.Label(self.frame3,font = 'Times:12',fg = 'blue',textvariable = self.value,justify = 'left',wraplength ='260',width = 30, height = 15,anchor = 'nw')
self.mirang_label.pack()
self.mirang_label.configure(background = 'seashell')
self.copyright_label = tkinter.Label(self.frame4,anchor ='nw',font = 'Times:12:bold',text = "copyright # cchristoe#gmail.com",width = 30,borderwidth = 3, fg = 'purple',)
self.copyright_label.pack()
self.frame1.pack()
self.frame2.pack()
self.frame3.pack()
self.frame4.pack()
tkinter.mainloop()
self.main_window.quit()
def dic(self, event = None):
conn = sqlite3.connect('C:/users/christoe/documents/sqlite/laimirangdictionary.sqlite')
c = conn.cursor()
kawl = self.lai_entry.get()
kawl = kawl + '%'
c.execute("SELECT * FROM laimirang WHERE lai LIKE ?", (kawl,))
c.fetchall
for member in c:
out = (member)
self.value.set(out)
print(out, )
dic=Dictionary()
You need to change:
c.execute("SELECT * FROM laimirang WHERE lai LIKE ?", (kawl,))
c.fetchall
for member in c:
out = (member)
self.value.set(out)
print(out, )
To:
for member in c.execute("SELECT * FROM laimirang WHERE lai LIKE ?", (kawl,)):
current_text = self.value.get()
new_text = current_text +( "\n" if current_text else "") +" ".join(member)
self.value.set(new_text)
The new version gets the current value of the StringVar value and then appends the results returned with a space inbetween for each row returned with each row on its own line. What you were doing however involved just updating the StringVar to be the current member object, and therefore it only ever had the last values.
This is how it looks with more than one line:
I'm trying to create a custom ComboBox that behaves like the one in here: http://chir.ag/projects/name-that-color/
I've got two problems right now:
I can't seem to find a way to have a scrollbar on the side; the gtk.rc_parse_string function should do that, since the ComboBox widget has a "appears-as-list" style property, but my custom widget seems unaffected for some reason.
When you select a color from my widget, then click the ComboBox again, instead of showing the selected item and its neighbours, the scrolled window starts from the top, for no apparent reason.
This is the code, you can pretty much ignore the __load_name_palette method. You need the /usr/share/X11/rgb.txt file to run this code, it looks like this: http://pastebin.com/raw.php?i=dkemmEdr
import gtk
import gobject
from os.path import exists
def window_delete_event(*args):
return False
def window_destroy(*args):
gtk.main_quit()
class ColorName(gtk.ComboBox):
colors = []
def __init__(self, name_palette_path, wrap_width=1):
gtk.ComboBox.__init__(self)
liststore = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING,
gobject.TYPE_STRING)
name_palette = self.__load_name_palette(name_palette_path)
for c in name_palette:
r, g, b, name = c
if ((r + g + b) / 3.) < 128.:
fg = '#DDDDDD'
else:
fg = '#222222'
bg = "#%02X%02X%02X" % (r, g, b)
liststore.append((name, bg, fg))
self.set_model(liststore)
label = gtk.CellRendererText()
self.pack_start(label, True)
self.set_attributes(label, background=1, foreground=2, text=0)
self.set_wrap_width(wrap_width)
if len(name_palette) > 0:
self.set_active(0)
self.show_all()
def __load_name_palette(self, name_palette_path):
if exists(name_palette_path):
try:
f = open(name_palette_path,'r')
self.colors = []
palette = set()
for l in f:
foo = l.rstrip().split(None,3)
try:
rgb = [int(x) for x in foo[:3]]
name, = foo[3:]
except:
continue
k = ':'.join(foo[:3])
if k not in palette:
palette.add(k)
self.colors.append(rgb + [name])
f.close()
return self.colors
except IOError as (errno, strerror):
print "error: failed to open {0}: {1}".format(name_palette_path, strerror)
return []
else:
return []
if __name__ == '__main__':
win = gtk.Window()
#colname = ColorName('./ntc.txt')
colname = ColorName('/usr/share/X11/rgb.txt')
gtk.rc_parse_string("""style "mystyle" { GtkComboBox::appears-as-list = 1 }
class "GtkComboBox" style "mystyle" """)
print 'appears-as-list:', colname.style_get_property('appears-as-list')
model = gtk.ListStore(gobject.TYPE_STRING)
hbox = gtk.HBox()
win.add(hbox)
hbox.pack_start(colname)
win.connect('delete-event', window_delete_event)
win.connect('destroy', window_destroy)
win.show_all()
gtk.main()
The problem was the self.show_all() line. Also, you can't have a list AND a wrap_width != 1