Two windows in python, freaking me out - python

++_+++_+++_+++_+++_+++_+++
** Never mind! ** This question is answered! it just needed this at the bottom instead of that root beezwax...
yup. it was the bottom. it just needed a little code cleaning :).... never mind. thanks anyway!
#omit root
app = App()
app.mainloop()
++_+++_+++_+++_+++_+++_++++
I've tried hard for two hours to get rid of this second window. After I implemented the popup to ask for the folder name, I suddenly had two windows open when the program runs. I just want one, it's really quite aggravating. I want this program to open one window with four buttons, and have a title above them. one of the buttons asks for input, and then it goes away. can someone help me get back to one window? thank you. i apologize for the messy code, it's my first script of this style.
#!/usr/bin/python
#from Tkinter import *
import Tkinter as tk
import os
import tkFileDialog
class App(tk.Tk):
#class App:
#def __init__(self, master):
def __init__(self):
tk.Tk.__init__(self)
frame = tk.Frame(self)
frame.pack()
self.button = tk.Button(frame, text="leave", fg="red", command=frame.quit)
self.button.pack(side=tk.LEFT)
self.fetch = tk.Button(frame,text="Choose Folder for Pictures",fg="salmon",command=self.choose)
self.fetch.pack(side=tk.LEFT)
self.fetch = tk.Button(frame,text="Name folder on site (public)",command=self.on_click)
self.fetch.pack(side=tk.LEFT)
self.hi_there = tk.Button(frame, text="Create code for images", fg="brown", command=self.generate)
self.hi_there.pack(side=tk.LEFT)
#oroville dam is the highest in the country
w = tk.Label(text="MSP Art File Fetcher")
w.pack()
# Toplevel window
top = self.top = tk.Toplevel(self)
myLabel = tk.Label(top, text='Name of image directory:')
myLabel.pack()
self.myEntryBox = tk.Entry(top)
self.myEntryBox.pack()
mySubmitButton = tk.Button(top, text='Done', command=self.submit_name)
mySubmitButton.pack()
top.protocol("WM_DELETE_WINDOW", self.save_top)
top.withdraw()
def save_top(self):
self.top.withdraw()
def choose(self):
self.foldername=tkFileDialog.askdirectory()
print self.foldername
def name(self):
print self.foldername
def generate(self):
print self.foldername
self.path=self.foldername # failing, works
self.dirlist=os.listdir(self.path)
yoz = file('demcode.txt','wt')#totally works
f=open('demcode.txt', 'r+')
f.write(self.foldername)
f.write('\ndo not be a crack addic\n')
f.write('\n')
print self.dirlist
print self.dirlist[0]
self.y=len(self.dirlist)
print self.y
for x in range(0,self.y): #works great
#for x in range(0,4):#self.y: #failing
print 'We\'re on image %d' % (x)
#print in self.dirlist
f.write('\n'.join(self.dirlist[0]))#returns a vertical word!?
f.write('\n')
f.write(self.dirlist[0])
f.write('\n')
f.write('\n')
f.write('\n')
f.write(', '.join(self.dirlist))#CAUTION, will write over existing data
def say_hi(self):
print "don't be a crack addic"
def submit_name(self):
if self.myEntryBox.get() != "":
self.username = self.myEntryBox.get()
self.myEntryBox.delete(0, 'end')
self.top.withdraw()
def on_click(self):
self.top.deiconify()
"""
def show_name(self):
self.mainText.delete('1.0', 'end')
self.mainText.insert('end', 'Welcome ' + self.username + '!')
"""
root = tk.Tk()
app = App()
root.mainloop()
"""
"""
achieve this format of html. python program will loop every file in the directory, placing the name of the file in the set path (asked directory name), and write the approiate code for lightbox
"""
<h1>MSP (Acorns) Gallery</h1>
#http://www.mspart.com/lightbox.html
<div id="page">
<div id="images">
<ul class="gallery">
<li><img src="images/Pastels/alpha_farm.jpg" alt="description"></li>
<li><img src="images/Pastels/_day_island.jpg" alt="description">
</li></ul>
</div>
</div>

In your app class, you have already defined a Tk. So, when you define an app and another Tk, you are creating two windows. Removing one or the other should create only one window.

Related

How to Refresh a Tab in Tkinter after Interacting with a Database?

I have a python script for teachers that works very well on my terminal and I'm trying to use Tkinter so I can share this script with other people. In the script, the user uploads a file and other information to an SQLite database.
Below is part of the script that shows just the content for the 1st tab (of 3). The problem is that when people interact with the database the tab needs to get refreshed to show something has happened and that the list of files in the database has changed.
Everything I've read shows you need a button to refresh. But that is not user-friendly. What people want to do is upload a file and then see that file in the list. Is this possible with Tkinter and if so how?
class AppWindow():
my_list = [4]
def __init__(self, parent):
global my_list
# Create the window
self.window = parent
self.window.geometry("700x600")
#self.center_window()
self.window.title("Test app")
# Create a text label and place it in the window
self.hello_label = tk.Label(self.window, text="Hello world!")
self.hello_label.place(x=20, y=20)
# Create 3 tabs
self.tab_container = tk.Frame(self.window)
self.tab_container.place(x=0,y=0,width=700,height=400)
self.tabs = ttk.Notebook(self.tab_container)
self.tab_2 = tk.Frame(self.tabs)
self.tabs.add(self.tab_2, text="Parameters")
self.tabs.place(x=0,y=0,height=400,width=700)
# Content for tab 2
self.label2 = tk.Label(self.tab_2, text="")
self.label201=tk.Label(self.tab_2, text="Put in your target GPA")
self.label201.place(x=50, y=50)
btn1 = tk.Button(self.tab_2,text="Target GPA", command=self.getGPA)
btn1.place(x=50, y=80)
for lst in self.my_list:
btn99=tk.Button(self.tab_2,text=lst)
btn99.grid()
def getGPA(self):
userInput = sd.askstring('User Input','Enter target GPA')
self.my_list.append(userInput)
if __name__ == "__main__":
root = tk.Tk()
app = AppWindow(root)
root.mainloop()
This is merely a guess because of the all the reasons I've already mentioned in comments under your question. Generally speaking, to update or what you call "refresh" a tab requires adding, changing, or deleting the widgets you put on it.
The code below is based what's currently in your code. Every time the Target GP button is clicked another Button is added to the self.tab_2 frame as well as appended to my_list. Changing the widgets doesn't have to be triggered by clicking on a button, it could be the result of some other event (such as the completion of a file upload in the background for example).
import tkinter as tk
import tkinter.ttk as ttk
import tkinter.simpledialog as sd
class AppWindow():
def __init__(self, parent):
# Create the window
self.window = parent
self.window.geometry("700x600")
#self.center_window()
self.window.title("Test app")
# Create and initialize data list.
self.my_list = [4]
# Create a text label and place it in the window
self.hello_label = tk.Label(self.window, text="Hello world!")
self.hello_label.place(x=20, y=20)
# Create 3 tabs
self.tab_container = tk.Frame(self.window)
self.tab_container.place(x=0, y=0, width=700, height=400)
self.tabs = ttk.Notebook(self.tab_container)
self.tab_2 = tk.Frame(self.tabs)
self.tabs.add(self.tab_2, text="Parameters")
self.tabs.place(x=0, y=0, height=400, width=700)
# Content for tab 2
self.label201 = tk.Label(self.tab_2, text="Put in your target GPA")
self.label201.place(x=50, y=50)
btn1 = tk.Button(self.tab_2, text="Target GPA", command=self.getGPA)
btn1.place(x=50, y=80)
# Create a Button for each item currently in list.
for item in self.my_list:
btn = tk.Button(self.tab_2, text=item)
btn.grid()
def getGPA(self):
userInput = sd.askstring('User Input', 'Enter target GPA')
if userInput is None: # User closed the dialog or clicked Cancel?
return
self.my_list.append(userInput)
btn = tk.Button(self.tab_2, text=userInput) # Create another Button.
btn.grid()
if __name__ == "__main__":
root = tk.Tk()
app = AppWindow(root)
root.mainloop()

Display output of print in python GUI?

Hello I created this function that allows you to count the top X words in the Macbeth play however I want to display the results in a gui of my creation and was wondering if someone could show me how to? I already created the function and tested it but I don't understand python gui and whenever I try to create it, I run into a host of errors.
#Imports
import tkinter as tk
from tkinter import *
from tkinter import filedialog
from collections import Counter
import collections
# Initialize the dictionary
wordcount = {}
#Function
#open Macbeth text file
file = open('Macbeth Entire Play.txt', encoding="utf8")
a= file.read()
n_print = int(input("How many most common words are: "))
print("\nThe {} most common words are as follows\n".format(n_print))
word_counter = collections.Counter(wordcount)
for word, count in word_counter.most_common(n_print):
print(word, ": ", count)
# Close the file
file.close()
#Graphics
fullString = ""
root = tk.Tk()
root.title("Count words")
root.geometry('400x400')
#Background Image Label
bg = PhotoImage(file = "./guibackground.gif")
# Show image using label
label1 = Label( root, image = bg)
label1.place(relx=0.5, rely=0.5, anchor=CENTER)
#Class Window
class Window:
def __init__(self):
self.root = tk.Tk()
self.btn = tk.Button(text='Open File', command=self.open_file)
self.btn.pack()
self.btn = tk.Button(text='Exit', command=root.quit)
self.btn.pack()
self.lbl.pack()
self.root.mainloop()
def open_file(self):
file = open('Macbeth Entire Play.txt', encoding="utf8")
a= file.read()
def word_count(self):
for word in a.lower().split():
word = word.replace(".","")
word = word.replace(",","")
word = word.replace(":","")
word = word.replace("\"","")
word = word.replace("!","")
word = word.replace("“","")
word = word.replace("‘","")
word = word.replace("*","")
if word not in wordcount:
wordcount[word] = 1
else:
wordcount[word] += 1
if __name__ == '__main__':
mainWindow = Window()
# root.mainloop()
I'll present a general example for you to start with in building your GUI. There are a few items I'd like to comment.
It's not a good idea to import tkinter as tk as well as from tkinter import * as this may lead to confuson later in the development. In general it's preferred to import tkinter as tk as you then always can see which module a widget comes from.
I would advise against the mix of flat and OOP programming styles. As above, it may lead to confusion later.
It's a good idea to use descriptive names, even if you just create and forget widgets, because an error message will tell you the name of the offending object. And also just in general it's easier to get a grip of the application with descriptive names. For example the GUI Buttons could instead be called: self.open_btn and self.exit_btn.
When you are working with files you may consider using the with statement as this adds a layer of security; it won't leave files open even if there is an error.
My example uses a program structure which I often use myself, depending on how I intend to use the program. Pros and cons for different structures are discussed in the thread Best way to structure a tkinter application?
Below is an example you can use as a cornerstone for your efforts if you wish.
import tkinter as tk
class Application(tk.Frame):
def __init__(self, master):
super().__init__() # Call __init__() method in parent (tk.Frame)
self.bg_image = tk.PhotoImage(file = "images/pilner.png")
self.background = tk.Label( root, image=self.bg_image)
self.background.place(relx=0.5, rely=0.5, anchor=tk.CENTER)
self.open_btn = tk.Button(text='Open File', command=self.open_file)
self.open_btn.pack(pady=(30,10))
self.exit_btn = tk.Button(text='Exit', command=master.destroy)
self.exit_btn.pack()
def open_file(self):
with open('Macbeth Entire Play.txt', encoding="utf8") as file:
self.file_text = file.read()
# Etc, etc.
if __name__ == '__main__':
root = tk.Tk()
root.title("Count words")
root.geometry('400x400+900+50')
app = Application(root)
app.pack(expand=True, fill='both')
root.mainloop()
Hope this is of help.

How to Clear the window in tkinter (Python)?

I want to hide/remove all the buttons from my window (temporarily) with the "hide_widgets" function so I can put them back after but its just not working for me, I have tried using grid_hide() and destroy() and anything I have tried so for from searching stackoverflow as not worked either.
Here is my program so far:
from tkinter import *
class Application(Frame):
#GUI Application
def __init__(self, master):
#Initialize the Frame
Frame.__init__(self,master)
self.grid()
self.create_widgets()
def create_widgets(self):
#Create new game etc...
#Title
self.title = Label(self,text = "Gnome")
self.title.grid()
#New Game
self.new_game = Button(self,text = "New Game")
self.new_game ["command"] = self.create_new_game
self.new_game.grid()
#Load Game
self.load_game = Button(self,text = "Load Game")
self.load_game ["command"] = self.display_saves
self.load_game.grid()
#Settings
self.settings = Button(self,text = "Settings")
self.settings ["command"] = self.display_settings
self.settings.grid()
#Story
self.story = Button(self,text = "Story")
self.story ["command"] = self.display_story
self.story.grid()
#Credits
self.credits = Button(self,text = "Credits")
self.credits ["command"] = self.display_credits
self.credits.grid()
def hide_widgets(self):
#clear window
new_game.grid_forget()
def create_new_game(self):
#Create new game file
self.hide_widgets
self.instruction = Label(self, text = "Name World:")
self.instruction.grid()
self.world_name = Entry(self)
self.world_name.grid()
def display_saves(self):
#display saved games and allow to run
print("saves")
def display_settings(self):
#display settings and allow to alter
print("settings")
def display_story(self):
#display story
print("story")
def display_credits(self):
#display credits
print("credits")
root = Tk()
root.title("Welcome")
width, height = root.winfo_screenwidth(), root.winfo_screenheight()
root.geometry('%dx%d+0+0' % (width,height))
app = Application(root)
root.mainloop()
Thank you in advance.
You can hide the Buttons by calling each one's grid_forget() method.
To make that easier you might want to create a self.buttons list or dictionary that contains them all.
Alternatively there's also a grid_slaves() method you might be able to use on the Application instance that will give you a list of all the widgest it manages (or just the ones in a specified row or column). The Buttons should be in one of these lists. I've never used it, so I don't know how easy it would be to identify them in the list returned however.
Ok I got it working now, silly me forgot "()" in self.hide_widgets(), i just never thought about it because there was no error as it was creating a variable instead.
Have you tried replacing new_game.grid_forget() with self.new_game.grid_forget()?
Check this answer out for an explanation as to why self needs to be referenced explicitly. I ran a very simple script to test this behavior and it worked fine.

Allow user to change default text in tkinter entry widget.

I'm writing a python script that requires the user to enter the name of a folder. For most cases, the default will suffice, but I want an entry box to appear that allows the user to over-ride the default. Here's what I have:
from Tkinter import *
import time
def main():
#some stuff
def getFolderName():
master = Tk()
folderName = Entry(master)
folderName.pack()
folderName.insert(END, 'dat' + time.strftime('%m%d%Y'))
folderName.focus_set()
createDirectoryName = folderName.get()
def callback():
global createDirectoryName
createDirectoryName = folderName.get()
return
b = Button(master, text="OK and Close", width=10, command=callback)
b.pack()
mainloop()
return createDirectoryName
getFolderName()
#other stuff happens....
return
if __name__ == '__main__':
main()
I know next to nothing about tkInter and have 2 questions.
Is over-riding the default entry using global createDirectoryName within the callback function the best way to do this?
How can I make the button close the window when you press it.
I've tried
def callback():
global createDirectoryName
createDirectoryName = folderName.get()
master.destroy
but that simply destroys the window upon running the script.
I don't know how experienced are you in Tkinter, but I suggest you use classes.
try:
from tkinter import * #3.x
except:
from Tkinter import * #2.x
class anynamehere(Tk): #you can make the class inherit from Tk directly,
def __init__(self): #__init__ is a special methoed that gets called anytime the class does
Tk.__init__(self) #it has to be called __init__
#further code here e.g.
self.frame = Frame()
self.frame.pack()
self.makeUI()
self.number = 0 # this will work in the class anywhere so you don't need global all the time
def makeUI(self):
#code to make the UI
self.number = 1 # no need for global
#answer to question No.2
Button(frame, command = self.destroy).pack()
anyname = anynamehere() #remember it alredy has Tk
anyname.mainloop()
Also why do you want to override the deafult Entry behavior ?
The solution would be to make another button and bind a command to it like this
self.enteredtext = StringVar()
self.entry = Entry(frame, textvariable = self.enteredtext)
self.entry.pack()
self.button = Button(frame, text = "Submit", command = self.getfolder, #someother options, check tkitner documentation for full list)
self.button.pack()
def getfolder(self): #make the UI in one method, command in other I suggest
text = self.enteredtext.get()
#text now has whats been entered to the entry, do what you need to with it

Creating a popup message box with an Entry field

I want to create a popup message box which prompts user to enter an input. I have this method inside a class. I am basing my code on this guide by java2s.
class MyDialog:
def __init__(self, parent):
top = self.top = Toplevel(parent)
Label(top, text="Value").pack()
self.e = Entry(top)
self.e.pack(padx=5)
b = Button(top, text="OK", command=self.ok)
b.pack(pady=5)
def ok(self):
print "value is", self.e.get()
self.top.destroy()
root = Tk()
d = MyDialog(root)
root.wait_window(d.top)
But in this, top = self.top = Toplevel(parent) doesn't work for me.
I have a mockup of what I am trying to accomplish.
My program structure looks something like this:
class MainUI:
def__int__(self):
...
self.initUI()
def initUI(self):
.......
Popup = Button(self, text="Enter Value", command=self.showPopup)
def showPopup(self):
#create the popup with an Entry here
How can I create a message box in Python which accepts user input?
I'm a little confused about your two different blocks of code. Just addressing the first block of code, nothing happens because you never enter the mainloop. To do that, you need to call root.mainloop(). The typical way of doing this is to add a button to root widget and bind a callback function to the Button (which includes d=MyDialog() and root.wait_window(d.top))
Here's some basic code which I hope does what you want ...
from Tkinter import *
import sys
class popupWindow(object):
def __init__(self,master):
top=self.top=Toplevel(master)
self.l=Label(top,text="Hello World")
self.l.pack()
self.e=Entry(top)
self.e.pack()
self.b=Button(top,text='Ok',command=self.cleanup)
self.b.pack()
def cleanup(self):
self.value=self.e.get()
self.top.destroy()
class mainWindow(object):
def __init__(self,master):
self.master=master
self.b=Button(master,text="click me!",command=self.popup)
self.b.pack()
self.b2=Button(master,text="print value",command=lambda: sys.stdout.write(self.entryValue()+'\n'))
self.b2.pack()
def popup(self):
self.w=popupWindow(self.master)
self.b["state"] = "disabled"
self.master.wait_window(self.w.top)
self.b["state"] = "normal"
def entryValue(self):
return self.w.value
if __name__ == "__main__":
root=Tk()
m=mainWindow(root)
root.mainloop()
I get the value from the popupWindow and use it in the main program (take a look at the lambda function associated with b2).
Main window:
"Click me" window:
Main window while "click me" is open:
import tkinter as tk
from tkinter import simpledialog
ROOT = tk.Tk()
ROOT.withdraw()
# the input dialog
USER_INP = simpledialog.askstring(title="Test",
prompt="What's your Name?:")
# check it out
print("Hello", USER_INP)
Enjoy ...
I did it in Tkinter without any classes. I created a function that starts a new window.
popup.Tk()
popup.mainloop()
In that window there is an Entry field from where I get the text with a variable which value is: entry.get()
Then you can use that variable for whatever you need and it will take the text from that Entry field.
I just tried this:
def get_me():
s = simpledialog.askstring("input string", "please input your added text")
Source: https://www.youtube.com/watch?v=43vzP1FyAF8

Categories

Resources