I've no idea why I haven't been able to find a good solution to this problem yet, it seems very elementary to me .. though not elementary enough to figure it out satisfactorily.
A chapter project in a cryptology book Im reading instructs to write a simple mono-alphabetic cipher in your preferred language ... I chose Python.
It starts with a simple tkinter app. with some widgets, lol ... duh. Anyways here's the relevant code:
from tkinter import *
from tkinter.filedialog import askopenfilename
from tkinter.messagebox import showerror
class Application(Frame):
def __init__(self, master):
""" Initialize Frame. """
super(Application, self).__init__(master)
self.grid()
self.create_widgets()
def create_widgets(self):
""" Set all program widgets. """
# set all labels
Label(self, text = "Plaintext File: ")\
.grid(row=0, column=0, sticky=W)
Label(self, text = "Ciphertext: ")\
.grid(row=3, column=0, sticky=W)
Label(self, text = "Offset: ")\
.grid(row=2, column=0, sticky=W)
# set buttons
Button(self, text = "Browse", command=self.load_file, width=10)\
.grid(row=1, column=0, sticky=W)
# set entry field
self.file_name = Text(self, width=39, height=1, wrap=WORD)
self.file_name.grid(row=1, column=1, columnspan=4, sticky=W)
# set display field
self.output_display = Text(self, width=50, height=5, wrap=WORD)
self.output_display.grid(row=4, column=0, columnspan=4, sticky=W)
# set offset amount spinbox
self.offset_amt = IntVar()
self.offset_amt = Spinbox(self, from_=1, to=13)
self.offset_amt.grid(row=2, column=1, sticky=W)
# set shift direction
self.shift_dir = StringVar()
self.shift_dir.set('r')
Radiobutton(self, text="Shift Right", variable=self.shift_dir, value='r')\
.grid(row=2, column=2, sticky=W)
Radiobutton(self, text="Shift Left", variable=self.shift_dir, value='l')\
.grid(row=2, column=3, sticky=W)
def load_file(self):
self.filename = askopenfilename(initialdir='~')
if self.filename:
try:
#self.settings.set(self.filename)
self.file_name.delete(0.0, END)
self.file_name.insert(0.0, open(self.filename, 'r'))
except IOError:
showerror("Open Source File", "Failed to read file \n'%s'"%self.filename)
return
def main():
root = Tk()
root.title("simple mono-alpha encrypter")
root.geometry('450x250')
app = Application(root)
for child in app.winfo_children():
child.grid_configure(padx=3, pady=3)
root.mainloop()
main()
There's only a very little of it that actually does anything besides create widgets right now, I decided to post it all since its not that involved yet and someone can get a good idea of where Im at.
My problem that I haven't solved is that when I press use the 'Browse' button to choose a file to encrypt and then choose the file, the file content is displayed in the 'file_name' text widget, rather than the file name itself.
Im thinking that I have to change the 'filename' variable to not the actual file name but the file instead and then load the content of the File Name field from the open file dialog box in a 'filename' variable. I just haven't been able to figure out how to do that yet.
Nor have I come across an appropriate method to do it.
Any guidance??
Thanks
F
Displaying the Filename
self.file_name.insert(0.0, self.filename)
Displaying the File Contents
You just need to read the data in from the file. See http://docs.python.org/library/stdtypes.html#file-objects
with open(self.filename, 'r') as inp_file:
self.file_name.insert(0.0, inp_file.read())
Related
In this code I am displaying a window with a label and two buttons, the user can read the file path currently in use in the label and decide if he wants to change it or continue with the buttons.
If he wants to change the path then I change the value inside the textvariable inside the label. The issue is when I do this for example 3 times, then I have to kill the program manually pressing CTRL + C 3 times. If I do it once then I only need to do it once, like there is something preventing the program to terminate. Thanks for the help.
def select_file():
#OPEN TKINTER DIALOG LETTING ME TO CHOOSE A FILE AND RETURNS ITS PATH.
tkinter.Tk().withdraw() # prevents an empty tkinter window from appearing
folder_path = filedialog.askopenfilename()
return folder_path
def change_file():
file_path = select_file()
with open(os.path.expanduser('~/Documents/Squad Generator/excel_file_path.txt'), 'w') as f:
f.write(file_path)
#WRITES THE FILE PATH IN THE VARIABLE AND CHANGES THE LABEL
var.set(file_path)
def homepage():
app.geometry("450x200")
app.title("Squad Generator")
label_1 = tkinter.Label(master=app, justify=tkinter.LEFT,textvariable=var, font =
("JetBrains Mono", 15))
label_1.grid(row=0, column=0, columnspan=2, padx=20, pady=(20, 0), sticky="nsew")
button1 = tkinter.Button(master=app, text="Continua", command=main)
button1.grid(row=1, column=0, padx=20, pady=20, sticky="ew")
#BUTTON CAUSING THE ISSUE.
button2 = tkinter.Button(master=app, command=change_file, text="Cambia file")
button2.grid(row=1, column=1, padx=0, pady=20, sticky="ew")
#CREATING APP MAINLOOP
app.mainloop()
if __name__ == '__main__':
app = tkinter.Tk()
var = tkinter.StringVar(None, check_path_file())
homepage()
I've reorganized your application a bit. I've wrapped everything in a basic class named App which serves as the root of your application. This should work as expected and keep everything contained within a single instance of Tk.
import tkinter
from tkinter.filedialog import askopenfilename
class App(tkinter.Tk): # the App class inherits from Tk
def __init__(self):
super().__init__() # initialize Tk
self.geometry("450x200")
self.title("Squad Generator")
self.label_var=tkinter.StringVar(self, 'Select a file path')
self.label_1 = tkinter.Label(
master=self,
justify=tkinter.LEFT,
textvariable=self.label_var,
font=("JetBrains Mono", 15)
)
self.label_1.grid(row=0, column=0, columnspan=2, padx=20, pady=(20, 0), sticky="nsew")
self.button1 = tkinter.Button(master=self, text="Continua", command=main)
self.button1.grid(row=1, column=0, padx=20, pady=20, sticky="ew")
self.button2 = tkinter.Button(
master=self,
command=self.change_file,
text="Cambia file"
)
self.button2.grid(row=1, column=1, padx=0, pady=20, sticky="ew")
self.change_file() # call this function when the app starts
def change_file(self):
file_path = askopenfilename()
if file_path: # if a file is selected and not cancelled by the user
input_file = '~/Documents/Squad Generator/excel_file_path.txt'
with open(os.path.expanduser(input_file), 'w') as f:
f.write(file_path) # write out 'file_path' to the 'input_file'
#WRITES THE FILE PATH IN THE VARIABLE AND CHANGES THE LABEL
self.label_var.set(file_path)
else:
self.label_var.set('Select a file path') # fallback text if user cancels
if __name__ == '__main__':
app = App() # instantiate your App class
app.mainloop() # run the app
If you're not familiar with classes, the word self here can be confusing. All you need to know is that self refers to the App class. So any widgets you define within that class, like button1 have self as their master - i.e., they are children of the App class!
Also, any methods you define within the class (like change_file(self)) will be callable within the class via self.change_file, and will have access to any variables in the class, like self.label_var!
From what I see you just did
app.destroy()
But you actually need to do
app.master.destroy()
With the first line you're just destroying the current frame, not the the top level container.
I have difficulties trying to get the input from Entry widget stored as a instance variable, so I can use it as input outside this class:
class CreateGUI:
def __init__(self, master):
self.master = master
self.master.geometry("275x325")
self.master.columnconfigure(0, weight=1)
self.master.columnconfigure(1, weight=2)
self.checkbutton_var1 = IntVar()
self.checkbutton_var2 = IntVar()
self.path = ''
self.type = []
def add_labels(self):
Label(self.master, text="Provide path to file:").grid(column=0, row=0, padx=10, pady=10, sticky="N")
def add_entries(self):
user_input = Entry(self.master)
user_input.grid(column=0, row=1, padx=5, pady=5, ipadx=60)
return user_input
def add_buttons(self, user_input):
checkbutton1 = Checkbutton(self.master, text="test1", variable=self.checkbutton_var1, onvalue=1,offvalue=0,height=2,width=10)
checkbutton1.grid(column=1, row=0)
checkbutton2 = Checkbutton(self.master, text="test2", variable=self.checkbutton_var2, onvalue=1, offvalue=0,height=2, width=10)
checkbutton2.grid(column=1, row=1)
button = Button(self.master, text="push", bg="pink", bd=100, fg="white",
command=lambda: self.retrieve_input(user_input.get(), self.checkbutton_var1.get(), self.checkbutton_var2.get()))
button.grid(column=0, row=3, padx=20, pady=20, sticky="NEWS")
def retrieve_input(self, p, *args):
self.path = p
#print(self.path)
for el in args:
self.type.append(el)
#print(self.type)
def main():
tk = Tk()
app = CreateGUI(tk)
app.add_labels()
user_input = app.add_entries()
app.add_buttons(user_input)
print(app.type)
print(app.path)
tk.mainloop()
When I start the program, write the input and press the button, it does not print anything. There are empty brackets printed the moment the program is initiated. The prints inside the retrieve_input are printing exactly what I need, but I need this inputs outside of the class, because they will be an input to another class.
I tried everything related to this problem, but it is not working and I would really appriciate any kind of help. Thanks!
You are getting the input for the Entry widget right before anyone can have a chance to type in it. As a result, user_input.get() will return an empty string. One thing you can do is make some sort of trigger for calling add_buttons() that the user activates when they are done filling out user_input. Further tweaking after that should make it work.
Please tell me if you have any more trouble.
Below is the the code that I currently have. I am beginner programmer and am writing a small program that will automate some workflow for primer design (biologist / bioinformaticists represent).
The issue I have right now is that my lack of understanding of how OOP works with TKinter. I have read numerous stackoverflow posts and watched youtube videos and read guides that try to explain it but I am still somewhat at a loss. My current understanding is that each window should be its own object, with the window above it as its parent. I've attempted to do this with my program.
Currently I have two classes, AUTOPRIMER, and BlastAPI. AUTOPRIMER is the main window. There is a button in that window that I have created that should open up a new window when clicked. From my understanding, I have created a new object for that window called BlastAPI which deals with that particular requirement of my program. I see many guides that suggest the parent should be put in the init of the new object, but there are so many initialization variations I have seen from parent to master to args*, kwargs**. What is appropriate when? Also, currently the stack trace provides this feedback as it doesn't even compile properly.
Traceback (most recent call last):
File "/Users/Thunderpurtz/Desktop/CGIStuff/AUTOPRIMER/autoprimercode/test1.py", line 201, in <module>
autoprimer = AUTOPRIMER(root)
File "/Users/Thunderpurtz/Desktop/CGIStuff/AUTOPRIMER/autoprimercode/test1.py", line 105, in __init__
self.blast = BlastAPI(self)
File "/Users/Thunderpurtz/Desktop/CGIStuff/AUTOPRIMER/autoprimercode/test1.py", line 150, in __init__
eValueSetting = Entry(parent)
File "/anaconda3/lib/python3.6/tkinter/__init__.py", line 2673, in __init__
Widget.__init__(self, master, 'entry', cnf, kw)
File "/anaconda3/lib/python3.6/tkinter/__init__.py", line 2289, in __init__
BaseWidget._setup(self, master, cnf)
File "/anaconda3/lib/python3.6/tkinter/__init__.py", line 2259, in _setup
self.tk = master.tk
AttributeError: 'AUTOPRIMER' object has no attribute 'tk'
[Finished in 0.289s]
Fundamentally, I think my understanding of gui programming isn't solid so if anyone can provide some insight that would be great. If this question is sort of broad, I'll be happy to clarify in the comments.
import subprocess
from tkinter import *
from tkinter.filedialog import *
import tkinter.messagebox
class AUTOPRIMER:
def __init__(self, master):
#some functions, their content is removed as i do not believe they are relevant
def button1():
pass
def button2():
pass
def button3():
pass
def getPrimers():
pass
def PrimerParser():
pass
def poolPrimers():
pass
self.master = master
self.input = ""
self.output = ""
self.param = ""
self.inputbool = False
self.outputbool = False
self.parambool = False
self.p3filestring = '-p3_settings_file='
self.blast = BlastAPI(self)
master.title("Complete Genomics Inc.")
########## WIDGETS ##########
entry_1 = Entry(master) #input
entry_2 = Entry(master) #output
entry_3 = Entry(master) #parameters
label_1 = Label(master, text="AUTOPRIMER")
button_1 = Button(master, text="Input Filepath: ", command=button1)
button_2 = Button(master, text="Output Filepath: ", command=button2)
button_3 = Button(master, text="Parameters Filepath: ", command=button3)
button_get = Button(master, text="Get Primers", command=getPrimers)
button_parse = Button(master, text="Parse Primers", command = PrimerParser)
button_pool = Button(master, text="Pool Primers", command=poolPrimers)
button_blast = Button(master, text="Blast Primers", command=self.blast)
button_quit = Button(master, text="Quit", command=master.destroy)
########## LAYOUT ##########
label_1.grid(row=0, columnspan=4) #grid doesnt take left right, it takes NSEW directions
button_1.grid(row=1, sticky=E, padx=1, pady=1)
button_2.grid(row=2, sticky=E, padx=1, pady=1)
button_3.grid(row=3, sticky=E, padx=1, pady=1)
button_get.grid(row=4)
button_parse.grid(row=4, sticky=W, column=1)
button_pool.grid(row=4, sticky=W, column=2)
button_blast.grid(row=4, sticky=W, column=3)
button_quit.grid(row=4, sticky=W, column=4)
entry_1.grid(row=1, column=1, sticky=W, padx=1, pady=1)
entry_2.grid(row=2, column=1, sticky=W, padx=1, pady=1)
entry_3.grid(row=3, column=1, sticky=W, padx=1, pady=1)
class BlastAPI:
#class that does blast alignment on primers
from Bio.Blast import NCBIWWW
from Bio.Blast import NCBIXML
def __init__(self, parent):
self.parent = parent
super(BlastAPI, self).__init__() #saw this on another stackoverflow don't truly understand what it means
eValueSetting = Entry(parent)
closeButton = Button(parent, text="Close", command=self.destroy)
inputButton = Button(parent, text="Input file", command=doNothing)
entryField = Entry(parent)
#layout
self.title('Complete Genomics Inc.')
def blastPrimers():
filename = askopenfilename()
with open(filename) as file:
string = file.read()
fasta = fasta_string
result_handle = NCBIWW.qblast("blastn", "nt", fasta)
with open("my_blast.xml", "w") as out_handle:
out_handle.write(result_handle.read())
result_handle.close()
result_handle = open('my_blast.xml')
blast_record = NCBIXML.parse(result_handle)
evalue = 1 #add make it a GUI alterable value blastPrimers
item = next(blast_record)
E_VALUE_THRESH = eValueSetting
while True:
with open('BlastResults.txt', w) as blast:
try:
for alignment in item.alignments:
for hsp in alignment.hsps:
if hsp.expect < E_VALUE_THRESH: #use this to determine if the result will be applicable / HAVE USER SET / default value?
blast.write("****Alignment****")
blast.write("sequence:", alignment.title)
blast.write("length:", alignment.length)
blast.write("e value:", hsp.expect)
blast.write(hsp.query[0:75] + "...")
blast.write(hsp.match[0:75] + "...")
blast.write(hsp.sbjct[0:75] + "...")
item = next(blast_record)
except StopIteration:
print("Done!")
break
root = Tk()
autoprimer = AUTOPRIMER(root)
root.mainloop()
Thanks guys.
Ok so there is a lot that needs work here. I imagine the missing bits are part of your main code but without them testing your code is just not possible. I work with what I could and set up your class's to inherit from the tkinter objects they needed to be. Judging by your button command in your BlastAPI class I am assuming this class should be a Toplevel() window.
I have made some changes to your code and without having Bio.Blast I have changed some things to what I think you might need to do.
import subprocess
import tkinter as tk # import tkinter as tk is good for compatibility and maintainability. Don't use *
from tkinter.filedialog import *
import tkinter.messagebox
from Bio.Blast import NCBIWWW
from Bio.Blast import NCBIXML
class AutoPrimer(tk.Tk): # Class names should normally use the CapWords convention.
def __init__(self):
#initialization
tk.Tk.__init__(self)
self.title("Complete Genomics Inc.")
self.input = ""
self.output = ""
self.param = ""
self.inputbool = False
self.outputbool = False
self.parambool = False
self.p3filestring = '-p3_settings_file='
self.entry_input = tk.Entry(self)
self.entry_output = tk.Entry(self)
self.entry_parameters = tk.Entry(self)
self.entry_input.grid(row=1, column=1, padx=1, pady=1, sticky="w")
self.entry_output.grid(row=2, column=1, padx=1, pady=1, sticky="w")
self.entry_parameters.grid(row=3, column=1, padx=1, pady=1, sticky="w")
self.label1 = tk.Label(self, text="AUTOPRIMER").grid(row=0, columnspan=4)
tk.Button(self, text="Input Filepath: ", command=lambda: self.button1).grid(row=1, padx=1, pady=1, sticky="e")
tk.Button(self, text="Output Filepath: ", command=lambda: self.button2).grid(row=2, padx=1, pady=1, sticky="e")
tk.Button(self, text="Parameters Filepath: ", command=lambda: self.button3).grid(row=3, padx=1, pady=1, sticky="e")
tk.Button(self, text="Get Primers",).grid(row=4)
tk.Button(self, text="Parse Primers",).grid(row=4, column=1, sticky="w")
tk.Button(self, text="Pool Primers",).grid(row=4, column=2, sticky="w")
tk.Button(self, text="Blast Primers", command=lambda: BlastAPI(self)).grid(row=4, column=3, sticky="w")
tk.Button(self, text="Quit", command=self.destroy).grid(row=4, column=4, sticky="w")
#CLASS METHODS
#Series of buttons methods that take in the filepath and displays it in the text widget to the user
def button1(self):
self.entry_input.delete(0,END)
ifp = askopenfilename()
self.setInput(ifp)
self.entry_input.insert(0, ifp)
self.setInputBool(True)
def button2(self):
self.entry_output.delete(0,END)
ofp = asksavefilename()
self.setOutput(ofp)
self.entry_output.insert(0, ofp)
self.setOutputBool(True)
def button3(self):
self.entry_parameters.delete(0,END)
pfp = askopenfilename()
self.entry_parameters.insert(0, pfp)
self.setParameterBool(True)
#Methods that rely on class attributes after using above buttons to set
def get_primers(self):
pass
def primer_parser(self):
pass
def pool_primers(self):
pass
#Setters and Getters
def setInput(self, value):
self.input = value
def setOutput(self, value):
self.output = value
def setParam(self, value):
self.param = value
def setInputBool(self, value):
self.inputbool = value
def setOutputBool(self, value):
self.outputbool = value
def setParameterBool(self, value):
self.parambool = value
class BlastAPI(tk.Toplevel):
def __init__(self, parent):
tk.Toplevel.__init__(self, parent)
self.title('Complete Genomics Inc.')
self.e_value_thresh = ""
self.e_value_setting = tk.Entry(self)
self.e_value_setting.pack() # Used pack here for quick testing. You will need to work on geometry yourself.
tk.Button(self, text="Close", command=self.destroy).pack()
tk.Button(self, text="Input file").pack()
self.entry_field = tk.Entry(self)
self.entry_field.pack()
def blast_primers(self): # Nothing is calling this function in your example.
filename = askopenfilename()
with open(filename) as file:
string = file.read() # string is not being used here.
fasta = string # No such var name in code.
result_handle = NCBIWWW.qblast("blastn", "nt", fasta) # This had a typo NCBIWW instead of NCBIWWW.
with open("my_blast.xml", "w") as out_handle:
out_handle.write(result_handle.read())
result_handle.close()
result_handle = open('my_blast.xml')
self.blast_record = NCBIXML.parse(result_handle)
evalue = 1 # Is not being used here.
self.item = next(self.blast_record)
self.e_value_thresh = self.e_value_setting.get()
self.blast_write_loop()
def blast_write_loop(self):
# I don't really like while loops and they have problems in event based GUI's.
# I don't think a while loop is needed here anyway.
with open('BlastResults.txt', 'w') as blast:
try:
for alignment in self.item.alignments:
for hsp in alignment.hsps:
if hsp.expect < self.e_value_thresh:
blast.write("****Alignment****")
blast.write("sequence:", alignment.title)
blast.write("length:", alignment.length)
blast.write("e value:", hsp.expect)
blast.write(hsp.query[0:75] + "...")
blast.write(hsp.match[0:75] + "...")
blast.write(hsp.sbjct[0:75] + "...")
self.item = next(self.blast_record)
except StopIteration:
print("Done!")
autoprimer = AutoPrimer()
autoprimer.mainloop()
What I want to get: change of checkbox state changes the state of the Entry widget from 'disabled' into 'normal'. (checkbox off = Entry disabled, checkbox on = Entry normal).
My problem is that I don't know how to access and update the state of entry.
My code:
from tkinter import *
from tkinter import ttk
class App(Frame):
def __init__(self, master):
ttk.Frame.__init__(self, master, padding='20')
self.grid()
self.create_checkbox()
self.create_entry()
def create_checkbox(self):
self.limit = BooleanVar()
Checkbutton(self,
text='Limit length',
variable= self.limit,
command= self.state_update,
).grid(row=1, column=1, sticky=W)
def create_entry(self):
self.entry_low = StringVar()
Entry(self,
width=6,
textvariable=self.entry_low,
state='disabled',
).grid(row=1, column=2, sticky=W)
def state_update(self):
self.entry_low.config(state="normal") #THIS OBVIOUSLY DOES NOT WORK
root = Tk()
root.title("Lottery")
app = App(root)
root.mainloop()
I'm beginner, so I'd be especially grateful for simple solutions.
Save a reference to the entry widget, then call the configure method. To make things easy, give your checkbutton the values for the states. That isn't strictly necessary, you can use a boolean and then translate that to the appropriate state.
def create_checkbox(self):
self.limit = StringVar(value="normal")
checkbutton = Checkbutton(..., onvalue="normal", offvalue="disabled", ...)
checkbutton.grid(...)
def create_entry(self):
self.entry_low = StringVar()
self.entry = Entry(self,
width=6,
textvariable=self.entry_low,
state='disabled',
)
self.entry.grid(row=1, column=2, sticky=W)
def state_update(self):
self.entry.config(state="normal") #THIS OBVIOUSLY DOES NOT WORK
Note: you need to call grid in a second step. grid(...) (as well as place) returns None. If you do x=Entry(...).grid(...), x will always be None.
I have been a programmer for 40 years, but mostly command-line and system programming. I am converting a tcl/tk gui that I wrote to Python because much of the stuff I did in shell scripts can be done effectively in Python, but I'm having a bit of trouble making the wigets line up (using grid) the way I want them. In my example, note the buttons line up perfectly. But the label/entry widget pairs are not lining up the way I want them: Note the workspace/project in row 3. I want the label to be adjacent to the entry widget and center. Also at the bottom I would like to have the scroll text widen to it fills the width of the screen. I just need a couple of pointer, maybe how best to group things in multiple frames. Also, I am assuming that the grid rows and columns are relational to the root windows and not the frame.
"""
PYGUITEST - This is a GUI test to test alignments of fields
Author: Jerry Feldman
"""
import sys
import os
import Tix
import tkMessageBox
import ScrolledText
import getpass
from Tkconstants import *
class pyguitest:
def __init__(self):
self.mainWindow = Tix.Tk()
self.mainWindow.tk.eval('package require Tix')
def __createUI(self, mainWindow):
mainWindow.protocol("WM_DELETE_WINDOW", self.OnExitWindow)
###### major class variables
self.username = getpass.getuser()
self.topFrame = Tix.Frame(self.mainWindow)
self.topRight = Tix.Frame(self.mainWindow)
### define buttons
self.butn01 = Tix.Button(self.topFrame,text=u"Butn01",
command=self.OnButn01ButtonClick)
self.butn02 = Tix.Button(self.topFrame,text=u"Butn02",
command=self.OnButn02ButtonClick)
self.butn03 = Tix.Button(self.topFrame,text=u"Butn03",
command=self.OnButn03ButtonClick)
self.butn04 = Tix.Button(self.topFrame,text=u"Butn04",
command=self.OnButn04ButtonClick)
self.butn05 = Tix.Button(self.topFrame,text=u"Butn05",
command=self.OnButn05ButtonClick)
self.butn06 = Tix.Button(self.topFrame,text=u"Butn06",
command=self.OnButn06ButtonClick)
self.butn07 = Tix.Button(self.topFrame,text=u"Butn07",
command=self.OnButn07ButtonClick)
self.butn08 = Tix.Button(self.topFrame,text=u"Butn08",
command=self.OnButn08ButtonClick)
self.Butn09 = Tix.Button(self.topFrame,text=u"Butn09",
command=self.OnButn09ButtonClick)
self.kwit = Tix.Button(self.topRight,text=u"quit !",
command=lambda:self.mainWindow.destroy())
### Set up the buttons grids for row 0
self.butn01.grid(column=0,row=0, sticky="nw")
self.butn02.grid(column=1,row=0, sticky="nw")
self.butn03.grid(column=2,row=0, sticky="nw")
self.butn04.grid(column=3,row=0, sticky="nw")
self.butn05.grid(column=4,row=0, sticky="nw")
self.butn06.grid(column=5,row=0, sticky="nw")
self.butn07.grid(column=6,row=0, sticky="nw")
self.butn08.grid(column=7,row=0, sticky="nw")
self.Butn09.grid(column=8,row=0, sticky="nw")
self.topFrame.grid(column=0,row=1,columnspan=8,sticky="NW")
self.kwit.grid(column=0,row=0,sticky="NE")
self.topRight.grid(column=10,row=1,columnspan=1,sticky="NE")
Tix.Label(mainWindow,text="This label should be centered").grid(row=2,sticky="nwes",columnspan=8)
wsFrame=Tix.Frame(mainWindow).grid(row=3, columnspan=9)
Tix.Label(wsFrame,text="Workspace:").grid(row=3,column=0, sticky="e")
wsEntry=Tix.Entry(wsFrame)
ws="/home/myuser/workspaces/pyguitest"
wsEntry.config(width=len(ws))
wsEntry.insert(0, ws)
wsEntry.grid(row=3, column=1)
Tix.Label(wsFrame,text="Project: ").grid(row=3,column=2, sticky="e")
self.prEntry=Tix.Entry(wsFrame)
pr=ws+"/project"
self.prEntry.grid(row=3,column=3, sticky="w")
self.prEntry.insert(0, pr)
self.prEntry.config(width=len(pr)+1)
Tix.Label(mainWindow,text="This should also be centered" ).grid(row=4,columnspan=8)
Tix.Label(mainWindow, text="ProductHome: ").grid(row=5)
ProductHome="/pmount/groupname/ProductHome/homeversion"
self.ProductHomeEntry = Tix.Entry(self.mainWindow)
self.ProductHomeEntry.delete(0, END)
self.ProductHomeEntry.insert(0, ProductHome)
self.ProductHomeEntry.configure(width=len(ProductHome)+1)
self.ProductHomeEntry.grid(row=5, column=1)
Tix.Label(mainWindow, text="Starting Port: ").grid(row=5,column=3, sticky="e")
portEntry=Tix.Entry(mainWindow)
portEntry.grid(row=5,column=4, sticky="w")
startingPort="20000"
portEntry.insert(0,startingPort)
portEntry.config(width=len(startingPort)+1)
Tix.Label(mainWindow, text="Product Version: ").grid(row=5,column=5, sticky="e")
pVersion="10.12.8 beta"
self.productVersionEntry=Tix.Entry(mainWindow)
self.productVersionEntry.grid(row=5, column=6, sticky="w")
self.productVersionEntry.insert(0, pVersion)
self.productVersionEntry.config(width=len(pVersion))
Tix.Label(mainWindow,text="Another centered label").grid(row=6, columnspan=8)
Tix.Label(mainWindow, text="Delta:").grid(row=7, column=0)
delta=ProductHome+"/delta"
self.deltaEntry=Tix.Entry(mainWindow)
self.deltaEntry.insert(0, delta)
self.deltaEntry.grid(row=7, column=1, sticky="w")
self.deltaEntry.configure(width=len(delta))
Tix.Label(mainWindow, text="Job to run: ").grid(row=7, column=2, sticky="e")
defaultJob=ProductHome+"/jobs/default.sh"
self.jobToRunEntry=Tix.Entry(mainWindow)
self.jobToRunEntry.grid(row=7, column=3, sticky="w")
self.jobToRunEntry.delete(0,END)
self.jobToRunEntry.insert(0, defaultJob)
self.jobToRunEntry.config(width=len(defaultJob))
defaultLauncher=ProductHome+"/launcher/default.sh"
Tix.Label(mainWindow, text="Launcher: ").grid(row=7, column=4, sticky="e")
self.launcherEntry=Tix.Entry(mainWindow)
self.launcherEntry.grid(row=7, column=5, sticky="w")
self.launcherEntry.delete(0,END)
self.launcherEntry.insert(0, defaultLauncher)
self.launcherEntry.config(width=len(defaultLauncher))
self.logger = ScrolledText.ScrolledText(self.mainWindow,
width = 160,
height = 60,
wrap=Tix.WORD,
relief="sunken")
self.logger.grid(row=10,columnspan=8)
def doLog(self, file):
for line in file.read().splitlines():
self.logger.insert(END, line+"\n")
txt.insert(END, "\nEnd of command\n\n")
def startpyguitest(self):
self.__createUI(self.mainWindow)
self.mainWindow.mainloop()
## Button Actions
def OnExitWindow(self):
self.mainWindow.destroy()
def OnButn01ButtonClick(self):
pass
def OnButn02ButtonClick(self):
pass
def OnButn03ButtonClick(self):
pass
def OnButn04ButtonClick(self):
pass
def OnButn05ButtonClick(self):
pass
def OnButn06ButtonClick(self):
pass
def OnButn07ButtonClick(self):
pass
def OnButn08ButtonClick(self):
pass
def OnButn09ButtonClick(self):
pass
def logIt(self, stdout):
for line in stdout.read().splitlines():
self.logger.insert(END, line+"\n")
self.logger.see(END)
if __name__ == "__main__":
pyguitest = pyguitest()
pyguitest.startpyguitest()
You need to make more use of the sticky option. There are a few widgets -- such as the scrolled text widget -- where they aren't told to stick to the edges of their cell.
You'll also want to use the grid_rowconfigure and grid_columnconfigure methods to get your GUI to resize properly.
You are incorrect about the grid rows and columns. They are relative to the frame. For example, you can have things in column 0 of an inner frame, and have that inner frame at column 2 of the root window.
I would use a .grid
btn.grid(row=0, column=0)
(change the #s as needed)