Python tkinter cannot print in same line? - python

So I am currently writing a program using python Tkinter where I enter details and it will enter each task on the same line. I left a photo of what I have done down below. I would like to have all of them print out on the same line.
I would like to have both 2s and the three buttons in the same line.
Here's my code
# This Python file uses the following encoding: utf-8
import os, sys
import tkinter as tk
from tkinter import *
from tkinter import ttk
import tkinter.font
import tkinter.messagebox
#Set up window
root = tk.Tk()
root.title("SNKRS Bot")
root.geometry("1000x600")
#Enter ID
IDHead = Label(root, text="ID:")
IDHead.grid(row=1, column=0)
IDInput = Entry(root, textvariable="", width='5')
IDInput.grid(row=1, column=1)
#Enter link
linkHead = Label(root, text="Link:")
linkHead.grid(row=2, column=0)
linkInput = Entry(root, textvariable="", width='60')
linkInput.grid(row=2, column=1)
ID = []
linkList = []
def createTask():
#Create variables for inputs
linkInput1 = linkInput.get()
IDInput1 = IDInput.get()
#Append to lists
linkList.append(linkInput1)
ID.append(IDInput1)
#print lists to check
print("ID: " + str(ID))
print("Links: " + str(linkList))
#Clear inputs
IDInput.delete(0, END)
linkInput.delete(0, END)
#Output values
# Label(root, text=(IDInput1 + " | " + linkInput1)).grid(column=0)
Label(root, text=linkInput1).grid(column=0)
Label(root, text=linkInput1).grid(column=1)
#Actions for each task
def startTask():
print("Task started")
def stopTask():
print("Task stopped")
def deleteTask():
print("Task deleted")
#Buttons for actions
startButton = tk.Button(root, text="start", command=startTask).grid(column=2)
stopButton = tk.Button(root, text="stop", command=stopTask).grid(column=3)
deleteButton = tk.Button(root, text="delete", command=deleteTask).grid(column=4)
#Create task
create = tk.Button(root, text="Create task", command=createTask)
create.grid(row=3, column=1)
root.mainloop()

Whenever you are packing a label,in the grid method you are passing only the column.by doing so,it will pack the widget in a new row.
To avoid that pass both the row and column arguments.
Ex:
Label(root,text="some text").grid(row=3,column=0)

Related

How to set time.sleep for different widgets

There is code that checks the availability of sites.
How can we make the status for each site to change at a user defined time (i.e. the time for each site can be different) The problem is that the number of sites is not limited, because you can add more lines to the application, so I do not understand how to implement it.
I attach a picture of how it looks like:
Code:
import tkinter as tk
from tkinter import ttk
import requests
import time
from tkinter import *
from tkinter import messagebox
data_list = []
window = Tk()
window.geometry('400x700')
window.title("SiteChecker")
def set_input(obj, value):
obj.delete(1.0, "END")
obj.insert("END", value)
def SiteCheck():
# time.sleep
for data in data_list:
url = data[0].get()
status = data[2]
if not str(url).startswith('http'):
continue
print(url)
Get_Response = None
try:
Get_Response = requests.get(url)
except:
status.config(text='status bad')
continue
if Get_Response.status_code == 200:
status.config(text='status ok')
pass
implement
else:
status.config(text='status bad')
def clicked():
txt = Entry(window, width=18)
txt.grid(column=0, pady=8)
txt_row = txt.grid_info()['row']
tim = Entry(window, width=3)
tim.grid(row=txt_row, column=1, pady=8)
txt_row = tim.grid_info()['row']
result1 = Label(window, text="status")
result1.grid(row=txt_row, column=2, pady=8)
data_list.append([txt, tim, result1])
lbl1 = Label(window, text="Enter references:")
lbl1.grid(column=0, row=1)
lbl2 = Label(window, text="Enter the test time: ")
lbl2.grid(column=1, row=1)
lbl3 = Label(window, text="Availability status ")
lbl3.grid(column=2, row=1)
for loop in range(2, 6):
txt1 = Entry(window, width=18)
txt1.grid(column=0, row=loop, pady=8)
tim1 = Entry(window, width=3)
tim1.grid(column=1, row=loop, pady=8)
result1 = Label(window, text="status")
result1.grid(column=2, row=loop, pady=8)
data_list.append([txt1, tim1, result1])
btn = Button(window, text="Add another site", command=clicked)
btn.grid(column=1, row=0)
Check_Button = Button(
window,
command=SiteCheck,
text='Start checking',
)
Check_Button.grid(row=0, column=2)
window.mainloop()
See here (How do I make my function run every second) how to use tkinter after() to achieve what you want. time.sleep won't work for your purpose because it is blocking the execution of the entire code.
From the link given in the comment to your question by Patrick Artner :
Tkinter root windows have a method called after() which can be used to schedule a function to be called after a given period of time. If that function itself calls after() you've set up an automatically recurring event.

Python tkinter: why does he want to quit?

I would need a bit of help with my code I'm writing... and although when I start the code then comes directly such a window which asks me if I want to close it.
Does anyone have an idea where this could come from?
The code should open a window where I have some buttons to open some other windows with sliders to control DMX Lights.
Here is the code:
import tkinter as tk
from tkinter import ttk
from tkinter import *
from print_dict import pd
from time import sleep
from tkinter import messagebox
Pultdatas = {'DMXtype':512,
'columns':2,
'rows':8,
'slider':8,
'modes':4
}
root = Tk()
root.configure(background='gray')
root.title('DMX-Pult v2')
Screens = {'mainscreen':[root,{}]}
def on_closing(screen):
if messagebox.askokcancel("Quit", f"Do you want to quit Scanner {screen}?"):
Screens[screen][0].destroy()
def setmode(screen,mode):
print(f'setmode on screen {screen} to {mode}')
for i in Screens[screen][1]['modesel']:
print(i)
i.config(bg='gray')
Screens[screen][1]['modesel'][mode].config(bg='green')
def pressed(btn):
print('pressed Button: ' + str(btn))
if not Screens.__contains__(btn):
Screens[btn] = []
Screens[btn].append(Tk())
Screens[btn][0].configure(background='gray')
Screens[btn][0].title(f'Scanner {btn}')
Screens[btn].append({})
Screens[btn][1]['modesel'] = []
for i in range(Pultdatas['modes']):
Screens[btn][1]['modesel'].append(Button(Screens[btn][0], text=f"mode {i+1}", bg='gray', fg='white', command=lambda name = i:setmode(btn,name)))
Screens[btn][1]['modesel'][i].grid(row=i,column=0)
setmode(btn,0)
else:
if Screens[btn][0].winfo_exists() == 1:
sleep(0.2)
print('This window exist.')
Screens[btn][0].attributes('-topmost', True)
Screens[btn][0].update()
Screens[btn][0].attributes('-topmost', False)
else:
Screens[btn] = []
Screens[btn].append(Tk())
Screens[btn][0].configure(background='gray')
Screens[btn][0].title(f'Scanner {btn}')
Screens[btn].append({})
Screens[btn][1]['modesel'] = []
for i in range(Pultdatas['modes']):
Screens[btn][1]['modesel'].append(Button(Screens[btn][0], text=f"mode {i + 1}", bg='gray', fg='white',
command=lambda name=i: setmode(btn, name)))
Screens[btn][1]['modesel'][i].grid(row=i, column=0)
Screens[btn][0].protocol("WM_DELETE_WINDOW", lambda name = btn:on_closing(name))
setmode(btn, 0)
print()
def close():
if messagebox.askokcancel("Quit", f"Do you want to quit?"):
for screen in Screens:
print(f'closed {Screens[screen][0].title()} Succesfully')
Screens[screen][0].destroy()
tmpint = 0
Screens['mainscreen'][1]['Back'] = Button(root, text='close all',bg='gray',fg='white',command=close)
Screens['mainscreen'][1]['Back'].grid(row=0,column=0)
for column in range(Pultdatas['columns']):
for row in range(Pultdatas['rows']):
tmpint += 1
Screens['mainscreen'][1][tmpint] = Button(root, text=f"Scanner {tmpint}", bg='gray', fg='white', command=lambda name = tmpint:pressed(name))
Screens['mainscreen'][1][tmpint].grid(row=row+1,column=column)
pd(Screens)
root.protocol("WM_DELETE_WINDOW", close())
root.mainloop()
You can just change this line of code
root.protocol("WM_DELETE_WINDOW", close())
To this:
root.protocol("WM_DELETE_WINDOW", close)
You don't need to write (), we can just write handler not as function.
For more info you can visit here

How to use class and self here to get two different entries?

With my current code, it does not matter whether I click on "Input Folder" - Change or "JukeBox" change the result always gets displayed in "JukeBox" entry. This is incorrect, using class and self how can I change the code to display result from "Input Folder" - Change in "Input Folder" entry and the result from "Jukbox" - Change in "Jukebox" entry?
Also, how can I save the selected folders to a file so that it is there on app exit and re open?
My code:
import os
from tkinter import *
from tkinter import filedialog
inPut_dir = ''
jukeBox_dir = ''
def inPut():
opendir = filedialog.askdirectory(parent=root,initialdir="/",title='Input Folder')
inPut_dir = StringVar()
inPut_dir = os.path.abspath(opendir)
entry.delete(0, END)
entry.insert(0, inPut_dir)
def jukeBox():
opendir = filedialog.askdirectory(parent=root,initialdir="/",title='JukeBox')
jukeBox_dir = StringVar()
jukeBox_dir = os.path.abspath(opendir)
entry.delete(0, END)
entry.insert(0, jukeBox_dir)
root = Tk()
root.geometry("640x240")
root.title("Settings")
frametop = Frame(root)
framebottom = Frame(root)
frameright = Frame(framebottom)
text = Label(frametop, text="Input Folder").grid(row=5, column=2)
entry = Entry(frametop, width=50, textvariable=inPut_dir)
entry.grid(row=5,column=4,padx=2,pady=2,sticky='we',columnspan=20)
text = Label(frametop, text="JukeBox").grid(row=6, column=2)
entry = Entry(frametop, width=50, textvariable=jukeBox_dir)
entry.grid(row=6,column=4,padx=2,pady=2,sticky='we',columnspan=20)
ButtonA = Button(frametop, text="Change", command=inPut).grid(row=5, column=28)
ButtonB = Button(frametop, text="Change", command=jukeBox).grid(row=6, column=28)
ButtonC = Button(frameright, text="OK").grid(row=5, column=20, padx=10)
ButtonD = Button(frameright, text="Cancel").grid(row=5, column=15)
frametop.pack(side=TOP, fill=BOTH, expand=1)
framebottom.pack(side=BOTTOM, fill=BOTH, expand=1)
frameright.pack(side=RIGHT)
root.mainloop()
See attached image:enter image description here
Your code has both:
entry = Entry(frametop, width=50, textvariable=inPut_dir)
entry.grid(row=5,column=4,padx=2,pady=2,sticky='we',columnspan=20)
and
entry = Entry(frametop, width=50, textvariable=jukeBox_dir)
entry.grid(row=6,column=4,padx=2,pady=2,sticky='we',columnspan=20)
with jukeBox_dir/row 6 overriding inPut_dir/row 5
Therefore, in def input:
where you have:
entry.insert(0, inPut_dir)
You'll get the result in row 5 (jukebox_dir)

How to clear a label using tkinter when pressing a button?

I am using labels to show a generated password in my tkinter password generator program, but when I change the length of a password from a lower value than before (for example from a length of 20 to 10) the label displaying the password appears to be overwritten - it does not clear. I have searched methods to do this, but I cannot seem to find any.
Here is my code:
from tkinter import *
from random import *
import string
root = Tk()
root.wm_title("Password Generator")
topFrame = Frame(root)
topFrame.pack()
bottomFrame = Frame(root)
bottomFrame.pack(side=BOTTOM)
root.geometry("1000x1000")
title = Label(topFrame, text="Length", fg="blue")
title.grid(row=3,column=5)
var = DoubleVar()
Slider_1 = Scale(root,orient=HORIZONTAL,length=32*10,from_=0,to=32, variable
= var)
Slider_1.pack()
passLen = var.get()
uppercaseLetters = "QWERTYUIOPASDFGHJKLZXCVBNM"
lowercaseLetters = "qwertyuiopasdfghjklzxcvbnm"
symbols = "!£$%^&*()_+-=}{][~##':;?>/.<,"
digits = "1234567890"
def gen():
characters = uppercaseLetters + lowercaseLetters + symbols + digits
password = "".join(choice(characters) for x in range(int(var.get())))
passLabel = Label(topFrame, text=password)
passLabel.grid(row=4, column=5)
genButton = Button(topFrame, text="Generate Password", fg="blue",
command=gen)
genButton.grid(row=1, column=5)
root.mainloop()
When I set the length to 32 characters:
And when I set the length to 6 characters it does not clear the old password label - it simply overwrites it in the middle of the old password label:
First of all, move your gen method definition to just below imports so that they're recognized in the main body. Then take your widgets and mainloop out of the method. Just configure passLabel's text when needed:
def gen():
characters = uppercaseLetters + lowercaseLetters + symbols + digits
password = "".join(choice(characters) for x in range(int(var.get())))
passLabel['text'] = password
Entire code with suggested edits been made:
from tkinter import *
from random import *
import string
def gen():
characters = uppercaseLetters + lowercaseLetters + symbols + digits
password = "".join(choice(characters) for x in range(int(var.get())))
passLabel['text'] = password
root = Tk()
root.wm_title("Password Generator")
topFrame = Frame(root)
topFrame.pack()
bottomFrame = Frame(root)
bottomFrame.pack(side=BOTTOM)
root.geometry("1000x1000")
title = Label(topFrame, text="Length", fg="blue")
title.grid(row=3,column=5)
var = DoubleVar()
Slider_1 = Scale(root,orient=HORIZONTAL,length=32*10,from_=0,to=32, variable
= var)
Slider_1.pack()
passLen = var.get()
uppercaseLetters = "QWERTYUIOPASDFGHJKLZXCVBNM"
lowercaseLetters = "qwertyuiopasdfghjklzxcvbnm"
symbols = "!£$%^&*()_+-=}{][~##':;?>/.<,"
digits = "1234567890"
passLabel = Label(topFrame)
passLabel.grid(row=4, column=5)
genButton = Button(topFrame, text="Generate Password", fg="blue",
command=gen)
genButton.grid(row=1, column=5)
root.mainloop()
Change two things:
First:
bottomFrame = Frame(root)
bottomFrame.pack(side=BOTTOM)
passLabel = Label(topFrame)
root.geometry("1000x1000")
Second:
def gen():
characters = uppercaseLetters + lowercaseLetters + symbols + digits
password = "".join(choice(characters) for x in range(int(var.get())))
passLabel.config(text=password)
passLabel.grid(row=4, column=5)
"How to clear a label using tkinter when pressing a button?"
Below is an example that clears label's text when the button is pressed:
try: # In order to be able to import tkinter for
import tkinter as tk # either in python 2 or in python 3
except ImportError:
import Tkinter as tk
def clear_widget_text(widget):
widget['text'] = ""
if __name__ == '__main__':
root = tk.Tk()
label = tk.Label(root, text="This will be cleared.")
button = tk.Button(root, text="Clear",
command=lambda : clear_widget_text(label))
label.pack()
button.pack()
root.mainloop()
Below is an example that destroys label when button is pressed:
try: # In order to be able to import tkinter for
import tkinter as tk # either in python 2 or in python 3
except ImportError:
import Tkinter as tk
def clear_widget(widget):
widget.destroy()
if __name__ == '__main__':
root = tk.Tk()
label = tk.Label(root, text="This will be cleared.")
button = tk.Button(root, text="Clear",
command=lambda : clear_widget(label))
label.pack()
button.pack()
root.mainloop()

How can I pop up a messagebox from a menu?

I am a newbie in Python. I want to create a program with Tkinter that takes the entry from the entry "box" and then compares each character of it with the charset and finally pops up a messagebox that shows the phrase. I have almost complete it but I can not make this line work:
info_menu.add_command(label="About",
command=messagebox.showwarning(message="Creator: GakPower\nVersion: 1.0.0\nCreated at 1/5/2017")
Full code:
from tkinter import ttk
from tkinter import *
from tkinter import messagebox
import string as s
class Bruteforcer:
def output(self, result):
self.result = result
if result == "":
messagebox.showwarning(title="Enter a Phrase",
message="Please enter a Phrase!")
else:
messagebox.showinfo(title="Phrase Found!",
message=("The process completed Successfully!\n The Phrase Found!!!!\n", result))
def submit_button_pressed(self):
entry_val = self.entry_value.get()
charset = list(s.ascii_letters + "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρστυφχψω" + s.digits + s.punctuation)
result = ""
x = 0
while x <= len(entry_val)-1:
echar = entry_val[x]
for char in charset:
if char == echar:
result += echar
x += 1
break
return self.output(result)
def __init__(self, root):
self.entry_value = StringVar(root, "")
self.the_menu = Menu(root)
info_menu = Menu(self.the_menu, tearoff=0)
**info_menu.add_command(label="About",
command=messagebox.showwarning(message="Creator: GakPower\nVersion: 1.0.0\nCreated at 1/5/2017")**
)
info_menu.add_separator()
info_menu.add_command(label="Quit", command=root.quit)
self.the_menu.add_cascade(label="Info", menu=info_menu)
root.config(menu=self.the_menu)
text_fond = StringVar()
text_fond.set("Times")
root.title("Graphical Bruteforcer")
root.geometry("500x500")
root.resizable(width=False, height=False)
style = ttk.Style()
style.configure("TButton",
foreground="red",
fond="Times 20",
padding=10)
style.configure("TEntry",
foreground="red",
fond="Times 20",
padding=10)
style.configure("TLabel",
foreground="red",
fond="Times 35 Bold")
# ---------- Entry -----------
self.entry_value = ttk.Entry(root,
textvariable=self.entry_value, width=25, state="normal")
self.entry_value.grid(row=1, columnspan=2)
# ---------- Label ----------
self.secret_label = ttk.Label(root,
text="The Secret Phrase").grid(row=0, column=0)
# ---------- Button ---------
self.button_submit = ttk.Button(root,
text="Submit", command=self.submit_button_pressed)
self.button_submit.grid(row=1, column=2)
root = Tk()
brute = Bruteforcer(root)
root.mainloop()
As furas said in the comments, command= expects a function. So you should replace
info_menu.add_command(label="About",
command=messagebox.showwarning(message="Creator: GakPower\nVersion: 1.0.0\nCreated at 1/5/2017"))
by something like
def show_about():
''' show the about messagebox '''
messagebox.showwarning(message="Creator: GakPower\nVersion: 1.0.0\nCreated at 1/5/2017")
info_menu.add_command(label="About", command=show_about)

Categories

Resources