I am not an experienced programmer so advance apologies if I am asking a basic question. I am using a for loop to print tkinter Entries and trying to return the reference of these Entries to the calling function. But when I try to get the text typed in the entry it always returns empty string? So my question is whether it is possible to return the reference of the control variable in python ? or I am using a wrong approach?
def data_entry_txtfield(self,rn,cn,pu,pd):
# Creates the Entry to enter data - rn is the row and cn is column
# pd and pu are padding up and padding down
entry = tk.StringVar()
tk.Entry(self.inputlab,width=32,bg=entrycolor,textvariable=entry)
entry.grid(column=cn,row=rn,pady=(pu,pd))
return entry
tbtlocationentry = self.data_entry_txtfield(9,4,0,12)
text = tbtlocationentry.get()
print(text)`
There are a lot of errors in this code like the bottom line your using self.data_entry_txtfield to call the function but you dont need the self. unless your using in a class. Also the entry needs a variable name to be able to change stuff inside it. I've fixed some errors and here is the code
def data_entry_txtfield(self,rn,cn,pu,pd):
# Creates the Entry to enter data - rn is the row and cn is column
# pd and pu are padding up and padding down
entry = tk.StringVar()
ety = tk.Entry(self.inputlab,width=32,bg=entrycolor,textvariable=entry)
ety.grid(column=cn,row=rn,pady=(pu,pd))
return entry
tbtlocationentry = self.data_entry_txtfield(9,4,0,12)
text = tbtlocationentry.get()
print(text)
I've left in the self. because i'm assuming your using this inside a class
Related
Hello I'm struggling to find a cleaner way to handle multiple StringVar assignments from a text file import. Whatever method I end up using needs to be adaptable for more StringVars in the future as this project grows.
Each line in the text file import has a key preceding a value "key: value" where the delimiter is ": ". While I currently have the order of the text file lines fixed, that will not be the case in the future for this project. Certain settings the program I'm making may influence what values are stored in this text file and some keys may not be written if there is no data associated with them.
From what I understand, I need the StringVars to fill in dynamic tkitner GUI Label and Entry elements so I don't see a way around using StringVars. Below is a snippet from my save-file import function which is assigns StringVar values from the input file data.
My current solution to manually set each StringVar to a value from a list is a bit clunky but better than a massive if-else statement evaluating the label which was my first pass.
# Read in the data
raw = open_regatta_save_file(file_path)
# Process the regatta save file.
row = 0
# Process Regatta Information
regatta_labels = ["Regatta_Name", "Regatta_Host", "Regatta_Location", "Regatta_Start_Day",
"Regatta_Start_Month", "Regatta_Start_Year", "Regatta_End_Day", "Regatta_End_Month",
"Regatta_End_Year", "Regatta_Type", "Regatta_Throw_Outs"]
regatta_values = [""] * len(regatta_labels)
while raw[row] != ":::BOAT INFORMATION:::": # Header for next section of input file
line = raw[row]
if ': ' in line and line.startswith(':::') is False:
# This is a line with data in it and not a header
[label, data] = line.split(': ')
if data is None or data == '':
# Either the provided data was blank or missing
continue
else:
if label in regatta_labels:
label_index = regatta_labels.index(label)
regatta_values[label_index] = data
row += 1
# Set regatta parameter values. Since regatta_labels control the order of the regatta_values list,
# these variables can be assigned in order.
self.regatta_name.set(regatta_values[0])
self.regatta_host.set(regatta_values[1])
self.regatta_location.set(regatta_values[2])
self.regatta_start_day.set(regatta_values[3])
self.regatta_start_month.set(regatta_values[4])
self.regatta_start_year.set(regatta_values[5])
self.regatta_end_day.set(regatta_values[6])
self.regatta_end_month.set(regatta_values[7])
self.regatta_end_year.set(regatta_values[8])
# Process Rest of file using similar method.
I'm hoping someone can help me understand Python StringVars better so that I can approach something simpler like:
StringVar1, StringVar2 ... = [list with values to assign to StringVars]
Thank you for your help.
I am creating a display using a tkinter label. I have lists of variables established for every line of "pixels", aka:
Line1 = []
Line2 = []
So that the number of lines is also the height of the display. The width of the display is the number of characters in each line, which I have added like this:
A = range(1, 311)
for b in A:
i = " "
Line1.append(i)
Line2.append(i)
I then transform the empty spaces into empty spaces which will actually print like empty spaces (I do not really understand this part since I got it from a question that I asked here, but it works, and I am happy it does) ...
LLine1 = ''.join(map(str, Line1))
LLine2 = ''.join(map(str, P2))
And finally, I "display" the display using a label:
Display = tkinter.Label(window, text = (LLine1, "\n", LLine2)
Up to here, every think should work properly. Now here comes the problem. In order for the display to show images, I need my program to change the variables and at the same time configure the label - possibly using... eeh... queues(?)... multi-threading(??)... multi-processing(???)? Basically, I need something like this:
threads.append(threading.Thread(target = Start_tkinter))
threads.append(threading.Thread(target = Start_running))
map(lambda x: x.start(), threads)
Where "Start_tkinter" configures the label sixty times per second using this (which will be in a loop):
window.mainloop() //this part will obviously not be a part of the loop
LLine1 = ''.join(map(str, Line1)) //But all this will be in the loop
LLine2 = ''.join(map(str, Line2))
Display.config(text = (PP1, PP2))
Display.after(16, count)
And "Start_running" changes the variables (which will also be in a loop). However, this does not work. So... what is the problem? I know that I have almost no experience, so and tips on any part of this programs are VERY appreciated :)
About your question with changing variables i may choose tkinter StringVar
import tkinter as Tk
root=Tk.Tk()
Var=Tk.StringVar()
Var.set("Some string")
print(Var.get())
Label=Tk.Label(root, text=Var.get())
Label.pack()
root.mainloop()
you can insert text by command set()
Var.set("Some string")
and insert to tkinter lable by get()
Label=Tk.Label(root, text=Var.get())
Label.pack()
and the label may change too.
I think this is the one of best solutions because you donĀ“t need to change Labels, but only variables, which is much faster.On the other hand you need same number of variables as your resolution.
Hi i got a script im working on and its not working out as well as I want it to
This is what I got so far
import bpy
def Key_Frame_Points(): #Gets the key-frame values as an array.
fcurves = bpy.context.active_object.animation_data.action.fcurves
for curve in fcurves:
keyframePoints = fcurves[4].keyframe_points # selects Action channel's axis / attribute
for keyframe in keyframePoints:
print('KEY FRAME POINTS ARE #T ',keyframe.co[0])
KEYFRAME_POINTS_ARRAY = keyframe.co[0]
print(KEYFRAME_POINTS_ARRAY)
Key_Frame_Points()
When I run this its printing out all the keyframes on the selected Objects as I wanted it to. But the problem is that I cant for some reason get the Values its printing into a variable. If you run it and check the the System concole. its acting odd.Like as in its printing out the Values of the Keyframed object.But when I ask it to get those values as an array, its just printing out the last frame.
Here is how it looks like briefly
I think what you want to do is add each keyframe.co[1] to an array which means you want to use KEYFRAME_POINTS_ARRAY.append(keyframe.co[1]) and for that to work you will need to define it as an empty array outside the loop with KEYFRAME_POINTS_ARRAY = []
Note that keyframe.co[0] is the frame that is keyed while keyframe.co[1] is the keyed value at that frame.
Also of note is that you are looping through fcurves but not using each curve.
for curve in fcurves:
keyframePoints = fcurves[4].keyframe_points
By using fcurves[4] here you are reading the same fcurve every time, you probably meant to use keyframePoints = curve.keyframe_points
So I expect you want to have -
import bpy
def Key_Frame_Points(): #Gets the key-frame values as an array.
KEYFRAME_POINTS_ARRAY = []
fcurves = bpy.context.active_object.animation_data.action.fcurves
for curve in fcurves:
keyframePoints = curve.keyframe_points
for keyframe in keyframePoints:
print('KEY FRAME POINTS ARE frame:{} value:{}'.format(keyframe.co[0],keyframe.co[1]))
KEYFRAME_POINTS_ARRAY.append(keyframe.co[1])
return KEYFRAME_POINTS_ARRAY
print(Key_Frame_Points())
You may also be interested to use fcurves.find(data_path) to find a specific curve by it's path.
There is also fcurve.evaluate(frame) that will give you the curve value at any frame not just the keyed values.
I have a QTableWidget populated with a list of lists. Each inner list have eight elements and my table have a ninth control column calculated after the others are loaded.
I can read and print to console the content of any cell of the table like print(self.tAccounts.item(52,3).text()), so I think there is no problem with the data, but the table shows only the cell's content for the first line and column in the table, leaving the others bank.
I should be making a mistake in some place, but I can't see.
Using PyQt 5 and Python 3.
The constructor
class Table(QWidget):
def __init__(self, parent=None):
super(Table, self).__init__(parent)
self.accounts = [] # The source is created in the constructor\
# and populate in other member function
self.tAccounts = QTableWidget(0,9)
self.tAccounts.setSortingEnabled(True)
self.tAccounts.setHorizontalHeaderLabels(['1','2','3','4','5','6','7','8','9'])
self.tAccounts.resizeColumnsToContents()
self.tAccounts.verticalHeader().hide()
The member function:
def loadDay(self):
for row, account in enumerate(self.accounts):
self.tAccounts.insertRow(row)
for col in range(8):
self.tAccounts.setItem(row, col, QTableWidgetItem(str(accounts[col])))
self.tAccounts.item(row,col).setTextAlignment(Qt.AlignRight)
self.tAccounts.setItem(row, 8, QTableWidgetItem('')) # defined for further use
Finally I found it.
The problem is in enabling the sorting in the constructor. Seems the default sorting is Z-A. Changing the sort to A-Z by clicking in the header of the empty table solves the bug but the best solution is to move the line self.tAccounts.setSortingEnabled(True) to the end of the loadDay function. Seems to be a clash between the ever changing row number because of enabled sorting and the updating algorithm of QTableWidget
Ok so I am trying to find the frame which Tkinter is using, then take its width and height and resize the window so that everything fits nicely without ugly spaces left. So far I have gotten the following...
convert = {"tab1_name", "tab1"; "tab2_name", "tab2"; "tab3_name", "tab3") ##(it goes on)
a = mainframe.tab(mainframe.select(), "text")
b = convert[a]
w = b.winfo_reqwidth()
h = b.winfo_reqheight()
mainframe.configure(width=w, height=h)
The names of each frame in the notebook are tab1, tab2, tab3, etc., but the labels on them are unique because they describe what happens in the tab. I want to be able to take the string returned from the convert dictionary function and use it as the frame's name. I am not sure if the frame is a class or what else. Is there a way to convert the string b into the frame's name and somehow use it in the .winfo_reqheight()? I do not want to have to make a thing which says...
if b=="tab1":
w = tab1.winfo_reqwidth()
h = tab1.winfo_reqheight()
mainframe.configure(width=w, height=h)
for each frame because I want it to be easy to add new frames without having to add so much code.
Thank you
Option 1:
You can store actual objects in dictionaries. So try:
convert = {"tab1_name": tab1, "tab2_name": tab2, "tab3_name": tab3}
a = mainframe.tab(mainframe.select(), "text")
b = convert[a]
w = b.winfo_reqwidth()
h = b.winfo_reqheight()
mainframe.configure(width=w, height=h)
Option 2:
Executing strings is possible with the 'exec('arbitrary code in a string')' function
See How do I execute a string containing Python code in Python?.
You could do this: (with just text in the dictionary or whatever convert is)
convert = {"tab1_name": "tab1", "tab2_name": "tab2", "tab3_name": "tab3"}
a = mainframe.tab(mainframe.select(), "text")
b = convert[a]
code1 = "w = %s.winfo_reqwidth()" % b
code2 = "h = %s.winfo_reqheight()" % b
exec(code1) # for python 2 it is: exec code1
exec(code2) # python 3 changed the exec statement to a function
mainframe.configure(width=w, height=h)
Be careful that you don't let malicious code into the exec statement, because python will run it. This is usually only a problem if an end user can input things into the function(it sounds like you don't have to worry about this).
btw, I think your first line is incorrect. You open with a { but close with ). Proper dictionary syntax would be:
convert = {"tab1_name": "tab1", "tab2_name": "tab2", "tab3_name": "tab3"}
Notice the colons separating key and value, and commas in-between entries.