I have a problem with the listbox because it does not display names like in the first listbox under 1T, only on one line, I want to display the names one under the other. I have no idea how to do this.
Thank you for every advice and attention to the code below
import random
import tkinter, sys
from tkinter import *
import tkinter.messagebox as messagebox
los = []
list = ['1. Kamil Winnicki', '#2. Wiktor Jasiński', '3. Adam Turowski', '#4. Arek Major', '5. Dominik Piechotka', '#6. Jakub Laskowski', '7. Jakub Materak', '8. Kacper Kołodziejski',
'#9. Kamil Stankiewicz', '10. Konrad Nosek', '11. Krzysiek Wawszczak', '12. Andrzej Oleksiak', '13. Miłosz Tarucin', '14. Paweł Pawłowski', '#15. Mateusz Lebioda']
lines = list
for line in lines:
if line [0] != '#':
los.append(line)
main = tkinter.Tk()
def koniec():
main.destroy()
def losowanie():
messagebox.showinfo(message=random.sample(los ,1))
#nagłowek
te = tkinter.Label(main, text = 'Lista 1T:')
te.pack()
#Wyswietla liste 1T
listbox = Listbox(main, width=21, height=15)
listbox.insert(1, '1. Mateusz Lebioda', '2. Jakub Laskowski', '3. Kamil Winnicki', '4. Wiktor Jasiński', '5. Adam Turowski', '6. Arek Major', '7. Dominik Piechotka', '8. Jakub Materak', '9. Kacper Kołodziejski', '10. Kamil Stankiewicz', '11. Konrad Nosek', '12. Krzysiek Wawszczak', '13. Andrzej Oleksiak', '14. Miłosz Tarucin', '15. Paweł Pawłowski')
listbox.pack()
#Obecne osoby
obecne1 = tkinter.Label(main, text = 'Obecne osoby:')
obecne1.pack()
obecne = Listbox(main)
obecne.insert(1, los)
obecne.pack()
#losuje
y = tkinter.Button(main, text = 'losuj', command = losowanie)
y.pack()
#wyjscie z aplikacji
x = tkinter.Button(main, text = 'Zakoncz', command = koniec)
x.pack()
main.mainloop()
You need to unpack your list when inserting.
Changing insertion line would be enough.
obecne.insert("end", *los)
#^ notice this star here. That one makes the unpacking
or you can just iterate over your list items using for loop.
obecne = Listbox(main)
for item in los:
obecne.insert("end", item)
obecne.pack()
Related
This question already has answers here:
How to select only one Radiobutton in tkinter
(3 answers)
Closed 6 months ago.
I am trying to learn the basics of the tkinter module. I made this program where I have some questions and each question has some options. My options are displayed using radio button selection. I want to select one choice at a time for each question independently. Currently when I select the 1st option then the 1st option of every question is selected but I don't want the selection for other than the one I am on.
My second question is once the selection [is made] I want to use the selection results and compare them with the answer keys to see how many answers are correct. How do I store the user's answer for each question?
Output result:
Edit:
Sorry for not posting my code as well.
Here is my python file which I am working on.
from tkinter import *
guessOptions =[]
def display():
global guessOptions
if x.get() == 0:
guessOptions.append("A")
elif x.get() == 1:
guessOptions.append("B")
elif x.get() == 2:
guessOptions.append("C")
else:
guessOptions.append("D")
window = Tk()
answers = ['A', 'B', 'C', 'D']
questions = ["Who invented Bulb? ",
"Which is not passive component? ",
"Which is not related to computer? ",
"Opertor used for and operation? "]
options = [['A. Thomas Edison', 'B. Nikola Tesla', 'C. Albert
Einstien', 'D. Michael Faraday'],
['A. Inductor', 'B. op-amp', 'C. Capacitor', 'D.
Resistor'],
['A. RAM', 'B. SSD', 'C. Heat', 'D. Keyboard'],
['!', '~', '||', '&']]
x = IntVar()
for i in range(len(questions)):
label = Label(window,
text=questions[i],
font=('Arial', 15, 'bold'))
label.pack(anchor=W)
for j in range(len(options)):
checkButton = Radiobutton(window,
text=options[i][j],
variable=x,
value=[j],
padx=10,
font=('Arial', 10),
command=display
)
checkButton.pack(anchor=W)
window.mainloop()
Each group of answers to a question needs its own IntVar and you'll need to add a Button to trigger the answer checking process. I've done most of that in the code below, except that check_answers() function doesn't really do anything meaningful since you haven't specified exactly what would be involved (or even what the correct choices are).
from tkinter import *
guessOptions =[]
def display(x):
global guessOptions
if x.get() == 0:
guessOptions.append("A")
elif x.get() == 1:
guessOptions.append("B")
elif x.get() == 2:
guessOptions.append("C")
else:
guessOptions.append("D")
def check_answers():
print(f'{guessOptions=}')
window = Tk()
answers = ['A', 'B', 'C', 'D']
questions = ["Who invented bulb? ",
"Which is not passive component? ",
"Which is not related to computer? ",
"Operator used for and operation? "]
options = [['A. Thomas Edison', 'B. Nikola Tesla', 'C. Albert Einstein',
'D. Michael Faraday'],
['A. Inductor', 'B. Op-amp', 'C. Capacitor', 'D. Resistor'],
['A. RAM', 'B. SSD', 'C. Heat', 'D. Keyboard'],
['!', '~', '||', '&']]
variables = []
for i in range(len(questions)):
label = Label(window, text=questions[i], font=('Arial', 15, 'bold'))
label.pack(anchor=W)
var = IntVar(value=-1)
variables.append(var) # Save for possible later use - one per question.
def handler(variable=var):
"""Callback for this question and group of answers."""
display(variable)
for j in range(len(options)):
checkButton = Radiobutton(window, text=options[i][j], variable=var,
value=j, padx=10, font=('Arial', 10),
command=handler)
checkButton.pack(anchor=W)
comp_btn = Button(window, text="Check Answers", command=check_answers)
comp_btn.pack()
window.mainloop()
I´ve created a loop of comboboxes and I'm appending the choices I make to a list. There are 3 comboboxes. The list must have 3 corresponding elements. The problem is that if I change my mind while choosing and replace the option, the list (of course) increases in size.
In this code I have 3 options: 'The One!', 'more or less','the bad'. I want to change the options during selection, but keeping the list always with 3 unique elements corresponding to number of combobox. I've tought about using set but didn't work because the actual loop is large.
I need the list with just the len of comboboxes with result corresponding to the last choices, independently of the number of choice changes I've done.
Thank you for any help.
from tkinter import ttk
from tkinter import Tk
from tkinter import Button
root = Tk()
my_heroes = ['Zidane', 'Ronaldo', 'Messi']
position = ['The One!', 'more or less','the bad']
result =[]
def get_combo_choice(event, cmb):
result.append(cmb.get())
print(result)
for index, heroe in enumerate(my_heroes):
var = StringVar()
bestPlayers = ttk.Combobox(root,values=position, textvariable=var, state="readonly")
bestPlayers.grid(row=0 + index, column=1,padx=(15,25))
label = Label(root, text = heroe)
label.grid(row=0 + index, column=0,padx=(15,25))
bestPlayers.bind("<<ComboboxSelected>>",lambda event, cmb=var:get_combo_choice(event, cmb))
button = Button(root, text ="get list of choices", command = callback)
button.grid(row=4, column=0,padx=(15,25))
root.mainloop()
The print grows to three, ok, but then continues...
I need to keep size of list = combobox len and freely update the values getting the last 3 choices at the end.
['The One!']
['The One!', 'more or less']
['The One!', 'more or less', 'the bad']
['The One!', 'more or less', 'the bad', 'The One!']
['The One!', 'more or less', 'the bad', 'The One!', 'more or less']
['The One!', 'more or less', 'the bad', 'The One!', 'more or less', 'The One!']
['The One!', 'more or less', 'the bad', 'The One!', 'more or less', 'The One!', 'more or less']
['The One!', 'more or less', 'the bad', 'The One!', 'more or less', 'The One!', 'more or less', 'more or less']
You can limit list length by usng list slice.
def get_combo_choice(event, cmb):
global result
result.append(cmb.get())
# limit list len to 3 using ~2
result = result[~2:]
print(result)
In order to control result columns a few things need to be added to your code.
result =[None, None, None]
best = []
# Here's the alternative
def get_combo_choice(event, cmb):
i = best.index(event.widget)
result[i] = cmb.get()
print(result)
Inside the for\loop insert best.append(bestPlayers)
Mr Derek
I updated my code with your answer. It works like a charm!! You teached me a lot, big thanks!
import tkinter as tk
from tkinter import ttk
from tkinter import Tk
from tkinter import Button
root = Tk()
my_heroes = ['Zidane', 'Ronaldo', 'Messi']
position = ['The One!', 'more or less','the bad']
# result =[]
# def get_combo_choice(event, cmb):
# result.append(cmb.get())
# print(result)
result =[None, None, None]
best = []
# Here's the alternative
def get_combo_choice(event, cmb):
i = best.index(event.widget)
result[i] = cmb.get()
print(result)
for index, heroe in enumerate(my_heroes):
var = tk.StringVar()
bestPlayers = ttk.Combobox(root,values=position, textvariable=var, state="readonly")
best.append(bestPlayers)
bestPlayers.grid(row=0 + index, column=1,padx=(15,25))
label = tk.Label(root, text = heroe)
label.grid(row=0 + index, column=0,padx=(15,25))
bestPlayers.bind("<<ComboboxSelected>>",lambda event, cmb=var:get_combo_choice(event, cmb))
button = tk.Button(root, text ="get list of choices", command = get_combo_choice)
button.grid(row=4, column=0,padx=(15,25))
root.mainloop()
code results in :
['The One!', None, None]
['The One!', None, None]
['The One!', None, None]
['The One!', 'more or less', None]
['The One!', 'more or less', 'the bad']
One last question:
in: def get_combo_choice(event, cmb):
I understand event(choice--> ex:"the one"),
cbm (--> the variable) and that results uses the index to get choice from best(list),
what I dont understand is why I can't use i = best.index() if best is a list we already know. What is (event.widget) and what it is doing there? By the way your code fits all my needs.
I am currently building a ReportLab PDF Form which I want to make interactive. I want that the options shown on the second choice widget, depend on the selection of the first choice widget. (For example: if the selection of the first choice is 'Italy', show as food options on the second widget 'Pizza' and 'Spaghetti').
Currently I am trying to control such condition with an if, however I have been unable to reference the first widget correctly. (Since I called it name='choice1', I figured this would be the way of calling such widget). I get an error:
if choice1 == 'Italy':
NameError: name 'choice1' is not defined
Is there a correct way to do the desired action? I am looking at the Reportlab documentation, however I have not found an answer.
My current Python code is the following:
from reportlab.pdfgen.canvas import Canvas
from datetime import datetime, timedelta
from reportlab.platypus import Table, TableStyle
from reportlab.lib import colors
from reportlab.pdfbase import pdfform
import win32com.client as win32
import pathlib
file_name = 'Example.pdf'
document_title = 'Example'
title = 'Example File'
instrucciones_1 = 'INSTRUCCIONES: Llenar toda la solicitud con la información que se pide.'
instrucciones_2 = 'Al finalizar, este PDF se enviará automáticamente al encargado de su área para aprobación.'
instrucciones_3 = 'La aprobación queda sujeta al criterio de dicho encargado. '
canvas = Canvas(file_name)
canvas.setTitle(document_title)
canvas.setFont("Helvetica-Bold", 24)
canvas.drawCentredString(385, 795, title)
now = datetime.now()
full_date = f'{now.day}/{now.month}/{now.year}'
canvas.setFont('Helvetica', 16)
canvas.drawCentredString(350, 790-20, 'Fecha solicitud: ')
canvas.setFont('Helvetica-Bold', 16)
canvas.drawCentredString(450, 790-20, full_date)
canvas.line(35, 755, 565, 755)
canvas.setFont("Helvetica", 12)
canvas.drawString(40, 740, instrucciones_1)
canvas.drawString(40, 740-15, instrucciones_2)
canvas.drawString(40, 740-30, instrucciones_3)
canvas.line(35, 740 - 35, 565, 740 - 35)
form = canvas.acroForm
canvas.setFont('Helvetica', 14)
canvas.drawString(70, 675, 'Origin of Food: ')
options = ['Select origin', 'Italy', 'Mexico', 'US']
form.choice(name='choice1', tooltip='Select origin of food',
value='Select origin',
x=165, y=670, width=200, height=25,
borderColor=colors.blue, fillColor=colors.lightblue,
textColor=colors.black, forceBorder=True, options=options)
origin = ''
food_italy = ['Select food', 'Spaghetti', 'Pizza']
food_mexico = ['Select food', 'Chiles en Nogada', 'Tacos]
food_us = ['Select food', 'Burgers', 'Buffalo Wings']
if choice1.value == 'Italy':
sucursal = food_italy
elif choice1.value == 'Mexico':
sucursal = food_mexico
elif choice1.value == 'US':
sucursal = food_us
canvas.drawString(70, 645, 'Food: ')
form.choice(name='choice2', tooltip='Select food',
value='Select food',
x=165, y=670, width=200, height=25,
borderColor=colors.blue, fillColor=colors.lightblue,
textColor=colors.black, forceBorder=True, options=sucursal)
canvas.save()
Any suggestions?
Thanks a lot in advance!
EDIT
If PDF and Reportlab is not the way, is there some way I can do an executable file/form which can perform such tasks? Thanks a lot.
This cannot be done in the way you approach this, i.e. in the Python code. The reason for this is that the selection of e.g. 'Italy' happens only when the user opens the PDF file and selects it. So you would need to create a (deprecated) XFA form for this.
What can I do to get the result in the interface instead of the terminal in the given code? I want the random.choice result to appear in the table.
import random
import tkinter, sys
from tkinter import *
lista = ['Kamil Winnicki', 'Wiktor Jasiński', 'Adam Turowski', 'Arek Major',
'Dominik Piechotka', 'Jakub Laskowski', 'Jakub Materak', 'Kacper Kołodziejski',
'Kamil Stankiewicz', 'Konrad Nosek', 'Krzysiek Wawszczak', 'Andrzej Oplebsiak',
'Miłosz Tarucin', 'Paweł Pawłowski', 'Mateusz Lebioda']
def koniec():
sys.exit()
def losowanie():
print(random.choice(lista))
main = tkinter.Tk()
#nagłowek
te = tkinter.Label(main, text = 'Lista 1T:')
te.pack()
#Wyswietla liste 1T
listbox = Listbox(main)
listbox.insert(1, '1. Mateusz Lebioda', '2. Jakub Laskowski', '3. Kamil Winnicki',
'4. Wiktor Jasiński', '5. Adam Turowski', '6. Arek Major',
'7. Dominik Piechotka', '8. Jakub Materak', '9. Kacper Kołodziejski',
'10. Kamil Stankiewicz', '11. Konrad Nosek', '12. Krzysiek Wawszczak',
'13. Andrzej Oplebsiak', '14. Miłosz Tarucin', '15. Paweł Pawłowski')
listbox.pack()
#losuje
y = tkinter.Button(main, text = 'losuj', command = losowanie)
y.pack()
#wyjscie z aplikacji
x = tkinter.Button(main, text = 'Zakoncz', command = koniec)
x.pack()
main.mainloop()
One way to do it would be to show a dialog with the choice.
import tkinter.messagebox as messagebox
def losowanie():
messagebox.showinfo(message=random.choice(lista))
If I understand the question correctly you need to append the result of random.choice(lista) to the listbox element, this can be achieved by the following code:
def losowanie():
listbox.insert(END, str(listbox.size() + 1) + ". " + random.choice(lista))
Like Dan-Dev suggested you could do that but you can also get rid of the function
This will do what you intend to, but without the function losowaine:
y = tkinter.Button(main, text = 'losuj', command = lambda :
listbox.insert(END, str(listbox.size() + 1) + ". " + random.choice(lista)))
This below code will just insert the random choice at the end of the table (with function losowanie)
def losowanie():
listbox.insert(END, (random.choice(lista)))
Let's say I have a list of lists like this:
lis_ = [['"Fun is the enjoyment of pleasure"\t\t',
'#username det fanns ett utvik med "sabrina without a stitch". acke nothing. #username\t\t','Report by #username - #JeSuisCharlie Movement Leveraged to Distribute DarkComet Malware https://t.co/k9sOEpKjbg\t\t'],
['I just became the mayor of Porta Romana on #username! http://4sq.com/9QROVv\t\t', "RT benturner83 Someone's chucking stuff out of the window of an office on tottenham court road #tcr street evacuated http://t.co/heyOhpb1\t\t", "#username Don't use my family surname for your app ???? http://t.co/1yYLXIO9\t\t"]
]
I would like to remove the links of each sublist, so I tried with this regular expression:
new_list = re.sub(r'^https?:\/\/.*[\r\n]*', '', tweets, flags=re.MULTILINE)
I used the MULTILINE flag since when I print list_ it looks like:
[]
[]
[]
...
[]
The problem with the above aproach is that I got an TypeError: expected string or buffer clearly I can not pass like this the sublists to the regex. How can I apply the above regex to the set of sublists in list_ ? in order to get something like this (i.e. the sublists without any type of link):
[['"Fun is the enjoyment of pleasure"\t\t',
'#username det fanns ett utvik med "sabrina without a stitch". acke nothing. #username\t\t','Report by #username - #JeSuisCharlie Movement Leveraged to Distribute DarkComet Malware'],
['I just became the mayor of Porta Romana on #username! \t\t', "RT benturner83 Someone's chucking stuff out of the window of an office on tottenham court road #tcr street evacuated \t\t", "#username Don't use my family surname for your app ????\t\t"]
]
Does this can be done with a map or is there any other efficient aproach?.
Thanks in advance guys
You need to use \b instead of start of the line anchor.
>>> lis_ = [['"Fun is the enjoyment of pleasure"\t\t',
'#username det fanns ett utvik med "sabrina without a stitch". acke nothing. #username\t\t','Report by #username - #JeSuisCharlie Movement Leveraged to Distribute DarkComet Malware https://t.co/k9sOEpKjbg\t\t'],
['I just became the mayor of Porta Romana on #username! http://4sq.com/9QROVv\t\t', "RT benturner83 Someone's chucking stuff out of the window of an office on tottenham court road #tcr street evacuated http://t.co/heyOhpb1\t\t", "#username Don't use my family surname for your app ???? http://t.co/1yYLXIO9\t\t"]
]
>>> [[re.sub(r'\bhttps?:\/\/.*[\r\n]*', '', i)] for x in lis_ for i in x]
[['"Fun is the enjoyment of pleasure"\t\t'], ['#username det fanns ett utvik med "sabrina without a stitch". acke nothing. #username\t\t'], ['Report by #username - #JeSuisCharlie Movement Leveraged to Distribute DarkComet Malware '], ['I just became the mayor of Porta Romana on #username! '], ["RT benturner83 Someone's chucking stuff out of the window of an office on tottenham court road #tcr street evacuated "], ["#username Don't use my family surname for your app ???? "]]
OR
>>> l = []
>>> for i in lis_:
m = []
for j in i:
m.append(re.sub(r'\bhttps?:\/\/.*[\r\n]*', '', j))
l.append(m)
>>> l
[['"Fun is the enjoyment of pleasure"\t\t', '#username det fanns ett utvik med "sabrina without a stitch". acke nothing. #username\t\t', 'Report by #username - #JeSuisCharlie Movement Leveraged to Distribute DarkComet Malware '], ['I just became the mayor of Porta Romana on #username! ', "RT benturner83 Someone's chucking stuff out of the window of an office on tottenham court road #tcr street evacuated ", "#username Don't use my family surname for your app ???? "]]
It seems that you have a list of lists of strings.
In that case, you simply need to iterate over these lists the proper way:
list_ = [['blablablalba', 'blabalbablbla', 'blablala', 'http://t.co/xSnsnlNyq5'], ['blababllba', 'blabalbla', 'blabalbal'],['http://t.co/xScsklNyq5'], ['blablabla', 'http://t.co/xScsnlNyq3']]
def remove_links(sublist):
return [s for s in sublist if not re.search(r'https?:\/\/.*[\r\n]*', s)]
final_list = map(remove_links, list_)
# [['blablablalba', 'blabalbablbla', 'blablala'], ['blababllba', 'blabalbla', 'blabalbal'], [], ['blablabla']]
If you want to remove any empty sub-lists afterwards:
final_final_list = [l for l in final_list if l]