Could you help me understand what I am doing wrongly.
I want this
My code is:
from tkinter import *
import Pmw
master = Tk()
class GetPassword(Pmw.Dialog):
def body(self, master):
self.title('Enter New Password')
Label(master, text='Old Password:').grid(row=0, sticky=W)
Label(master, text='New Password:').grid(row=1, sticky=W)
Label(master, text='Enter New Password Again:').grid(row=2, sticky=W)
self.oldpw = Entry(master, width = 16, show='*')
self.newpw1 = Entry(master, width = 16, show='*')
self.newpw2 = Entry(master, width = 16, show='*')
self.oldpw.grid(row=0, column=1, sticky=W)
self.newpw1.grid(row=1, column=1, sticky=W)
self.newpw2.grid(row=2, column=1, sticky=W)
a = GetPassword()
a.body(master)
master.mainloop()
The result looks likt this:
My problems:
The title is Tk instead of Enter New Password.
I somehow manage to split the frame in two: 1. Entry fields. 2. Buttons.
I'm getting only one button (Cancel button is lost somewhere).
I would be thankful if you could help me.
1. The title is Tk instead of Enter New Password.
You need to set title for master. The code in the question put widgets in the master (main window).
master = Tk()
master.title('Enter New Password')
This may not be needed, if you solve the second problem.
2. I somehow manage to split the frame in two: ...
In the dialog body method, you're putting widget into the master. Use Pmw.Dialog.interior() to put widgets into dialog:
def body(self, master):
self.title('Enter New Password')
Label(self.interior(), text='Old Password:').grid(row=0, sticky=W)
Label(self.interior(), text='New Password:').grid(row=1, sticky=W)
Label(self.interior(), text='Enter New Password Again:').grid(row=2, sticky=W)
self.oldpw = Entry(self.interior(), width = 16, show='*')
self.newpw1 = Entry(self.interior(), width = 16, show='*')
self.newpw2 = Entry(self.interior(), width = 16, show='*')
self.oldpw.grid(row=0, column=1, sticky=W)
self.newpw1.grid(row=1, column=1, sticky=W)
self.newpw2.grid(row=2, column=1, sticky=W)
3. I'm getting only one button (Cancel button is lost somewhere).
Use buttons option to list names of buttons:
a = GetPassword(buttons=('OK', 'Cancel'))
Related
I am creating a password manager which includes some buttons, but for some reason these buttons aren't aligning properly, could someone help out?
Here is the code i've done usint Tkinter for these buttons:
btn = Button(window, text="Exit Securely", command=exit)
btn.grid(column=2)
btn = Button(window, text="Add Entry", command=addEntry)
btn.grid(column=1)
btn = Button(window, text="Generate", command=run)
btn.grid(column=0)
lbl = Label(window, text="Website")
lbl.grid(row=3, column=0, padx=80)
lbl = Label(window, text="Username")
lbl.grid(row=3, column=1, padx=80)
lbl = Label(window, text="password")
lbl.grid(row=3, column=2, padx=80)
which makes my program look like this:
Any general tips or helpful links for how to make a nicer GUI would be appreciated as well, as I have been struggling with that.
As #acw1668 said if you don't specify row in grid(), it will take the next available row.
# Code to make this example work:
from tkinter import *
def addEntry():pass
def run():pass
window = Tk()
# Added `row=0` for each one of them
btn = Button(window, text="Exit Securely", command=exit)
btn.grid(row=0, column=2)
btn = Button(window, text="Add Entry", command=addEntry)
btn.grid(row=0, column=1)
btn = Button(window, text="Generate", command=run)
btn.grid(row=0, column=0)
# Changed the row to 1 for all of them
lbl = Label(window, text="Website")
lbl.grid(row=1, column=0, padx=80)
lbl = Label(window, text="Username")
lbl.grid(row=1, column=1, padx=80)
lbl = Label(window, text="password")
lbl.grid(row=1, column=2, padx=80)
By the way it is a good idea to use different names for the different buttons/labels.
I have been trying various method of aligning the widgets of tkinter in the program window lately and well I have found a better working solution to this.
In you program you have been using grid for aligning. I would say that you replace with place instead.
place will allow you to set a definite x and y coordinate for the widget and it would be easy to use.
If I alter your code accordingly, I can show you the code (after alteration) and the image of the output.
Code (After Alteration)
# Code to make this example work:
from tkinter import *
def addEntry():pass
def run():pass
window = Tk()
# Adding geometry ettig.
window.geometry('500x500')
btn = Button(window, text="Exit Securely", command=exit)
btn.place(x=410, y=20)
btn = Button(window, text="Add Entry", command=addEntry)
btn.place(x=210, y=20)
btn = Button(window, text="Generate", command=run)
btn.place(x=10, y=20)
lbl = Label(window, text="Website")
lbl.place(x=10, y=50)
lbl = Label(window, text="Username")
lbl.place(x=210, y=50)
lbl = Label(window, text="password")
lbl.place(x=410, y=50)
The Output Screen
I have a simple label and entry field that would:
1) Create a static label and clear the entry field after confirmation button click
2) Clear static label after reset button click
Is there any way to overwrite the entry field with a static label of the user input on the confirmation click instead of creating a new static label? And overwriting the static label with an empty entry field on the reset click?
Thank you for the help in advance.
from tkinter import *
root = Tk()
frame1 = Frame(root)
frame1.pack()
def reset():
set_cname.destroy()
cbtn['state'] = NORMAL
def confirm():
global set_cname
text1="Customer Name: " + entry1.get()
set_cname = Label(frame1, text=text1)
set_cname.grid(row=3, column=0, columnspan=1)
entry1.delete(0, 'end')
cbtn['state'] = DISABLED
cname = Label(frame1, text="Customer Name: ").grid(padx=5, pady=5, columnspan=2, sticky=W)
entry1 = Entry(frame1)
entry1.grid(row=0, column=2, padx=5)
cbtn = Button(frame1, text="Confirm", command=confirm, width=20)
cbtn.grid(row=1, column=4, padx=5, pady=5)
rbtn = Button(frame1, text="Reset Names", command=reset, width=20)
rbtn.grid(row=2, column=4, padx=5, pady=5)
root.mainloop()
You can replace the Entry with a Label by first creating both and then using pack() to switch between them. The trick is to not let their different sizes affect the application layout, which can be accomplished by disabling size propagation.
In my example I create a new frame (entry_frame) with a fixed size and then disable size propagation (.pack_propagate(False)). Then I use this new frame to contain the Entry/Label. Im giving the entry_frame the bg color khaki to let you see exactly where it is.
I fiddled a bit with the column numbers also.
from tkinter import *
root = Tk()
frame1 = Frame(root)
frame1.pack()
def reset():
text_label.pack_forget()
entry1.pack()
cbtn['state'] = NORMAL
def confirm():
global set_cname
entry1.pack_forget()
text_label.config(text=entry1.get())
text_label.pack(side='left')
entry1.delete(0, 'end')
cbtn['state'] = DISABLED
cname = Label(frame1, text="Customer Name: ")
cname.grid(row=0, column=0, padx=5, pady=5, sticky=W)
entry_frame = Frame(frame1, width=130, height=20, bg='khaki')
entry_frame.grid(row=0, column=1, padx=5, pady=5, sticky='nsew')
entry_frame.pack_propagate(False) # Disable size propagation
entry1 = Entry(entry_frame) # Customer name entry
entry1.pack()
text_label = Label(entry_frame) # Label to hold customer name
cbtn = Button(frame1, text="Confirm", command=confirm, width=20)
cbtn.grid(row=1, column=2, padx=5, pady=5)
rbtn = Button(frame1, text="Reset Names", command=reset, width=20)
rbtn.grid(row=2, column=2, padx=5, pady=5)
root.mainloop()
Be aware that this solution will be sensitive to font size changes.
I have created a chat application, in which i use ListBox for showing the chat history. It looks good until I enter a long sting which goes beyond the screen. Is there a way to break the string and show in new line or any other way to show the complete string. I'm new to Tkinter and im not aware of many widgets available.
Here is my sample code
from tkinter import *
class Actions:
def chatUpdate(chat):
chatlist.insert(Actions.chatLast,chat)
Actions.chatLast=Actions.chatLast+1
chatlist.pack( side=LEFT, fill=BOTH)
chatBox.config(command=chatlist.yview)
def callUpdater():
txt=textBox.get()
text_text.set("")
Actions.chatUpdate(txt)
root = Tk()
root.title("Chat App")
frame1 = Frame(root, bd=4)
frame1.pack(side=TOP)
frame2 = Frame(root, bd=4)
frame2.pack(side=TOP)
frame3 = Frame(root, bd=4)
frame3.pack(side=TOP)
# chat box
chatBox = Scrollbar(frame1)
chatBox.pack(side=RIGHT, fill=Y)
chatlist = Listbox(frame1, yscrollcommand = chatBox.set, width=50)
Actions.chatLast=0
Actions.chatUpdate(" ")
# text box
textView = Label(frame2, text="Input: ")
textView.pack(side=LEFT)
text_text = StringVar()
textBox = Entry(frame2, textvariable=text_text, bd=0, width=40, bg="pink")
textBox.pack(side=RIGHT)
# send button
button = Button(frame3, text="Send", fg="black", command=callUpdater)
button.pack(side=TOP)
root.mainloop()
You can replace the Listbox by a Text widget in 'disabled' mode which automatically wraps long lines. You will just need to put the widget back in 'normal' mode each time you insert text:
from tkinter import *
def callUpdater():
text = textBox.get()
textBox.delete(0, 'end')
chat.configure(state='normal')
chat.insert('end', text + '\n')
chat.configure(state='disabled')
root = Tk()
chatBox = Scrollbar(root)
chat = Text(root, wrap='word', state='disabled', width=50,
yscrollcommand=chatBox.set)
chatBox.configure(command=chat.yview)
chat.grid(row=0, columnspan=2, sticky='ewns')
chatBox.grid(row=0, column=2, sticky='ns')
Label(root, text="Input: ").grid(row=1, column=0)
textBox = Entry(root, bd=0, width=40, bg="pink")
textBox.grid(row=1, column=1)
Button(root, text="Send", command=callUpdater).grid(row=2, columnspan=2)
root.mainloop()
By the way, both the Listbox and Text widgets support the index 'end' so you don't have to keep track of how many lines you have inserted.
I have a Tkinter GUI and I would like to update the status of the script in a Label, writing which function is being called, but I am having problems with that.
I have already seen many answers on here, but still I cant come to a solution. This is the part of the code that I am working on:
run_script(username, password):
text = StringVar()
text.set('')
l=Label(master, text=text, fg='blue')
l.grid(row=6) #I would like the Label in the row 6
l.pack()
text.set('calling my function1')
my_file.my_function1(username, password)
text.set('calling my function2')
my_file.my_function2()
master = Tk()
username = Entry(master, name='username', width=30)
password = Entry(master, name='password', show='*', width=30)
username.grid(row=0, column=1, padx=10, pady=(10,2))
password.grid(row=1, column=1, padx=10, pady=2)
def call_report(username, password):
run_script(username, password)
Button(master, text='start script',
command= lambda:call_report(username.get(), password.get(),)).grid(row=6, column=1, sticky=W, pady=10)
mainloop()
The program run perfectly, just the label is not updated. Thanks
here is one way to do it, using the keyword argument textvariable:
import tkinter as tk
def run_script(username, password):
text = tk.StringVar()
text.set('')
lab = tk.Label(master, textvariable=text, fg='blue')
lab.grid(row=6)
text.set('calling my function1')
# call functions here
def call_report(username, password):
run_script(username, password)
if __name__ == '__main__':
master = tk.Tk()
username = tk.Entry(master, name='username', width=30)
password = tk.Entry(master, name='password', show='*', width=30)
username.grid(row=0, column=1, padx=10, pady=(10,2))
password.grid(row=1, column=1, padx=10, pady=2)
button = tk.Button(master, text='start script', command=lambda: call_report(username.get(), password.get(),))
button.grid(row=6, column=1, sticky=tk.W, pady=10)
master.mainloop()
Note:
The use of pack and grid geometry managers in the same widget is not encouraged.
Please import tkinter as tk: adding tk. is a small price to keep the namespace clean.
This is my solution that can be used as example:
from Tkinter import *
from time import sleep
def run_script():
text = StringVar()
l = Label(master, textvariable=text, fg='blue').grid(row=6)
text.set('calling my function1')
master.update()
sleep(2)
text.set('end of function1')
def call_report():
run_script()
if __name__ == '__main__':
master = Tk()
username = Entry(master, name='username', width=30)
password = Entry(master, name='password', show='*', width=30)
username.grid(row=0, column=1, padx=10, pady=(10,2))
password.grid(row=1, column=1, padx=10, pady=2)
button = Button(master, text='start script', command=lambda: call_report())
button.grid(row=6, column=1, sticky=W, pady=10)
master.mainloop()
I've changed text to textvariable in Label, and I added master.update(). In this way it force the GUI to redraw. Just to test if the GUI was changing, I tested with sleep. It is possible to update more time (for example before calling a function).
I'm having an alignment issue with radio buttons. I want three columns of form elements. For some reason, when I add radio buttons to the form, they appear to take up space for a new column on the left. I was hoping for a simple grid layout with each cell having equal size. That doesn't appear to be the case. Any suggestions would be greatly appreciated!
Here is part of my code:
self._mode_state = StringVar()
self._mode_radio_timelapse = Radiobutton(self, text="Timelapse", command=self._transition(), value=self._timelapse_mode, variable=self._mode_state)
self._mode_radio_continuous = Radiobutton(self, text="Continuous", command=self._transition(), value=self._continuous_mode, variable=self._mode_state)
self._mode_radio_ramphold = Radiobutton(self, text="Ramp and Hold", command=self._transition(), value=self._ramp_hold_mode, variable=self._mode_state)
self._mode_radio_timelapse.grid(row=0, column=0, pady=10)
self._mode_radio_continuous.grid(row=0, column=1, pady=10)
self._mode_radio_ramphold.grid(row=0, column=2, pady=10)
image_set_label = Label(text="Image Set Type: ")
image_set_label.grid(row=1, column=0, pady=10)
self._image_set_type = Entry()
self._image_set_type.insert(0, "Ramp")
self._image_set_type.grid(row=1, column=1, pady=10, columnspan=2)
The widgets are not all on the same grid. The radio buttons are specifically set with a parent of self, but your Label and Entry widgets are not created with any parent so the parent defaults to the root object.
Here's the fix:
image_set_label = Label(self, text="Image Set Type: ") # made self parent
image_set_label.grid(row=1, column=0, pady=10)
self._image_set_type = Entry(self) # made self parent
self._image_set_type.insert(0, "Ramp")
self._image_set_type.grid(row=1, column=1, pady=10, columnspan=2)