How to combine two strings to describe a property of tree.insert? - python

I'm creating a gui with tKinter, working with python for the first time.
Part of my gui is a treeview, the nodes in the treeview have images attached.
I made a function to add new nodes to the treeview.
I want to add an image to the new node based on the mother of the node.
In this case The variable 'curItem' returns the mother as a string, "test" in this case.
I want to combine the string "photo_" and "test" and use this in the 'tree.insert' code.
But for this to work I have to convert the string to something else, but I dont know to what and how to do this.
This is probably a very basic question, but I have been unable to find an answer so far.
Part of the relevant code:
photo_test = PhotoImage(file="resources/test.png")
def add():
curItem = tree.selection()[0] #returns "test"
img = "photo_" + curItem
tree.insert(curItem, 'end', text='new', image=img) #doesn't work
tree.insert(curItem, 'end', text='new', image=photo_test) #works

You're trying to set the image to the string 'photo_test'. Try storing the actual photo in a dict and access it via the string, something like this.
photos = dict()
photos["photo_test"] = PhotoImage(file="resources/test.png")
def add():
curItem = tree.selection()[0] #returns "test"
img = "photo_" + curItem
tree.insert(curItem, 'end', text='new', image=photos[img])
You seems to have misunderstood the difference between a variable and a string though. A string is just text within the code, not actually code, so you can't pass a variable name in string form and expect the code to read that value. "photo_test" is not the same as photo_test.

Related

Problem with python-docx putting pictures in a table

I am using python-docx to create a new document and then I add a table (rows=1,cols=5). Then I add a picture to each of the five cells. I have the code working but what I see from docx is not what I see when I use Word manually.
Specifically, if I set on "Show Formatting Marks" and then look at what was generated by docx, there is always a hard return in the beginning of each of the cells (put there by the add_paragraph method.) When I use Word manually, there is no hard return.
The result of the hard return is that each picture is down one line from where I want it to be. If I use Word, the pictures are where I expect them to be.
What is also strange is that on the docx document I can manually go in and single click next to the hard return, press the down cursor key once, and then press the Backspace key once and the hard return is deleted and the picture moves to the top of the cell.
So my question is, does anyone know of a way to get a picture in a table cell without having a hard return put in when the add_paragraph method is executed?
Any help would be greatly appreciated.
def paragraph_format_run(cell):
paragraph = cell.add_paragraph()
format = paragraph.paragraph_format
run = paragraph.add_run()
format.space_before = Pt(0)
format.space_after = Pt(0)
format.line_spacing = 1.0
format.alignment = WD_ALIGN_PARAGRAPH.CENTER
return paragraph, format, run
def main():
document = Document()
sections = document.sections
section = sections[0]
section.top_margin = Inches(1.0)
section.bottom_margin = Inches(1.0)
section.left_margin = Inches(0.75)
section.right_margin = Inches(0.75)
table = document.add_table(rows=1, cols=5)
table.allow_autofit = False
cells = table.rows[0].cells
for i in range(5):
pic_path = f"Table_Images\pic_{i}.jpg"
cell = cells[i]
cell.vertical_alignment = WD_ALIGN_VERTICAL.TOP
cell_p, cell_f, cell_r = paragraph_format_run(cell)
cell_r.add_picture(pic_path, width=Inches(1.25))
doc_path = "TableTest_1.docx"
document.save(doc_path)
Each blank cell in a newly created table contains a single empty paragraph. This is just one of those things about the Word format. I suppose it gives a place to put the insertion mark (flashing vertical cursor) when you're using the Word application. A completely empty cell would have no place to "click" into.
This requires that any code that adds content to a cell must treat the first paragraph differently. In short, you access the first paragraph as cell.paragraphs[0] and only create second and later paragraphs with cell.add_paragraph().
So in this particular case, the paragraph_format_run() function would change like this:
def paragraph_format_run(cell):
paragraph = cell.paragraphs[0]
...
This assumes a lot, like it only works when cell is empty, but given what you now know about cell paragraphs you may be able to adapt it to adding multiple images into a cell if later decide you need that.

Filter list while typing and select entry

I try to build a command line / terminal application using the prompt_toolkit, which should do the following:
I have a list of (title, id) pairs, which is to big to fit on one screen but small enough to fit into memory. Let's say around 1000 entries.
To select an item, I start typing. While typing - for example "dog" - the list is filtered to only those entries, having "dog" in the title.
If the list is small enough (but not empty) I would like to use the arrow keys to select an entry.
I want to have the id associated with that title.
I'm completely new to prompt_toolkit and approach the problem from both ends:
Using plain prompt() with autocompletion: I tried to misuse a custom completion method to filter my list, but did not managed to display it.
I checked the widget / full screen examples, but the documentation is rather limited. I found for example the SearchToolbar but could not really figure out how it interacts with other widgets.
I did not found any example on how to display a list to select an element. There are more complex examples, so I would expect that it's possible, but got lost.
Could somebody point me to an example that solves something like my use case or give me a starting point how to approach this in general?
Here's a quick autocompleter that does what you want I think. This assumes the first field is unique. If it isn't, and the ID is, switch the keys and values in the dictionary.
This checks the first item in the tuple for a match with the input text, and displays both the first item and the ID, then returns the ID when a selection is made.
The display keyword arg lets you show different text in the autocomplete window than what you will return on the completion. The display_meta isn't strictly necessary here, but it does show what will be returned when an item is selected.
from prompt_toolkit import prompt
from prompt_toolkit.completion import Completer, Completion
data_list = [('Katherine Davis', '105221'),
('Brandy Norman', '331005'),
('Leah Williams', '326092'),
('Veronica Sanchez', '104658'),
('Joyce Jackson', '236807'),
('Scott Luna', '276109'),
('Stephanie Fields', '712971'),
('Katie Griffin', '324463'),
('Gregory Davis', '626086'),
('Michael Mullins', '588486')]
class MyCustomCompleter(Completer):
def __init__(self, data_list):
self.data_list = data_list
self.data_dict = dict(data_list)
def get_completions(self, document, complete_event):
matches = [name for name in self.data_dict.keys() if document.text in name]
for m in matches:
yield Completion(self.data_dict[m], start_position=-len(document.text_before_cursor), display = m, display_meta = self.data_dict[m])
mycompleter = MyCustomCompleter(data_list)
if __name__ == '__main__':
answer = prompt('>', completer = mycompleter)
print('ID: %s' % answer)

Tkinter Find and Replace Function for Notepad

I'm new at Tkinter, and python. I've been experimenting with a notepad script I've made. I'm working on a find / replace command. But I've had no luck. Here is what I've tried so far:
def replace():
def replaceall():
findtext = str(find.get(1.0, END))
replacetext = str(replace.get(1.0, END))
alltext = str(text.get(1.0, END))
alltext1 = all.replace(findtext, replacetext)
text.delete(1.0, END)
text.insert('1.0', alltext1)
replacebox =Tk()
replacebox.geometry("230x150")
replacebox.title("Replace..")
find = Text(replacebox, height=2, width=20).pack()
replace = Text(replacebox, height=2, width=20).pack()
replaceallbutton = Button(replacebox, text="Replace..", command=replaceall)
replaceallbutton.pack()
(this is just the function I am defining for the replace command)
The 'text' variable is on the large canvas which contains the menu's and the main text widget.
Any help is appreciated
So far I've been creating this notepad in 2.7.8, so the Tkinter import is 'Tkinter.'
What I'm shooting for is having the first box have the text to find and the second box have the text to be replaced. Upon pressing the replace button, the function replaceall() should begin.
Are there any obvious mistakes in my function, or is it just deeply flawed? Any help is appreciated.
The most obvious mistake is that you are creating a second instance of Tk. If you need a popup window you should create an instance of Toplevel. You should always have exactly one instance of Tk running.
The second problem is related to the fact you are using a Text widget for the find and replace inputs. When you do a get with a second index of END, the string you get back will always have a newline whether the user entered one or not. If you want exactly and only what the user typed, use "end-1c" (end minus one character).
Finally, there's no reason to get all the text, replace the string, and then re-insert all the text. That will work only as long as you have no formatting or embedded widgets or images in the text widget. The text widget has a search command which can search for a pattern (either string or regular expression), and you can use the returned information to replace the found text with the replacement text.

Python EasyGui : Returning User Input In TextBoxes

Hello i am currently using python 2.7 to create a GUI based program with the add on library EasyGui. I'm trying to take the user input from a multiline textbox and print those values to another function which displays inside a messagebox. currently my code looks like this:
fieldNames = ["Name","Street Address","City","State","ZipCode"]
fieldValues = []
def multenterbox123():
multenterbox(msg='Fill in values for the fields.', title='Enter', fields=(fieldNames), values=(fieldValues))
return fieldValues
multenterbox123();
msgbox(msg=(fieldValues), title = "Results")
its currently returing a blank value in the messagebox (msgbox) and i understand why its doing this , as its pointing to the blank list variable fieldValues. I actually want to take the list values after its passed in from the user in the multi line textbox (multenterbox123) function, but im having trouble trying to work out how to best implement this.
Any help into this would be greatly appreciated as im only new to python programming (:
from easygui import msgbox, multenterbox
fieldNames = ["Name", "Street Address", "City", "State", "ZipCode"]
fieldValues = list(multenterbox(msg='Fill in values for the fields.', title='Enter', fields=(fieldNames)))
msgbox(msg=(fieldValues), title = "Results")
I tested the code above on my computer and the msgbox returned what I entered in the multenterbox . There is an example in the documentation if you want to take a look at it. Multenterbox-EasyGUI-Documentation. Basically you first need to make a list, hence the list function. And all the values entered will be stored in it. So whatever I write in the multenterbox will be saved in the fieldValues list.

How do you pprint a obj.lookup() into a Tkinter textbox

I've been trying to print the results of an ipwhois lookup into a Tkinter textbox but it's not working.
Currently i Get this error: TclError: wrong # args: should be ".40872632.46072536 insert index chars ?tagList chars tagList ...?"
Here's my code:
result2=unicode(set(ipList).intersection(testList));
result3=result2[:19].strip()
result4=result3[6:]
obj = ipwhois.IPWhois(result4)
results = obj.lookup()
results2= pprint.pprint(results)
text = Tkinter.Text(self)
text.insert(Tkinter.INSERT, results2)
text.insert(Tkinter.END, "")
text.pack()
text.grid(...)``
How do I pprint or at least split the results string by newline and why does it not work?
The issue here is that when you are trying to get the pprinted value of results2, it's returning None because pprint just writes the output to sys.stdout. When you then go on to do text.insert(Tkinter.INSERT, None) it throws the error that you keep receiving. This basically means you need to find another way to get the formatted string of your list - I'd recommend "\n".join(results).
As a side note, unless self is a Tkinter.Tk() or Tkinter.Toplevel() or something of the sort, you shouldn't have it as the text widget's parent. On top of that, you can cut and shorten the code you have above to the following:
results2 = "\n".join(results)
text = Tkinter.Text(self)
text.insert(Tkinter.END, results2) # Write the string "results2" to the text widget
text.pack()
# text.grid(...) # Skip this, you don't need two geometry managers
Check this out to read more about Tkinter - it's a really great resource for Tcl/Tk reference.

Categories

Resources