I'm currently calling up a class from my robot framework script and it opens up two windows of Tkinter. I've tried running my python object via PyCharm and through the cmd and i only get one Tkinter window through that. However when i call my object through RobotFramework it opens up a blank Tk window and the expected Tk window. Any ideas?
My Hello.py is:
from Tkinter import *
class hello(object):
def __init__(self, question="Not today"):
self.question = question
self.master = Tk()
self.lbl = Label(self.master, text=self.question)
self.lbl.pack()
self.btn = Button(self.master, text="Yes", command=self.yes_command)
self.btn.pack()
self.master.mainloop()
def yes_command(self):
print("User pressed Yes")
self.master.quit()
self.master.destroy()
My tk_hello file contents are:
from Tkinter import *
class tk_hello(object):
def __init__(self, question):
self.question = question
self.master = Tk()
self.lbl = Label(self.master, text=self.question)
self.lbl.pack()
self.btn = Button(self.master, text="Yes", command=self.yes_command)
self.btn.pack()
self.master.mainloop()
def yes_command(self):
print("User pressed Yes")
self.master.quit()
self.master.destroy()
My Robot Framework script is:
*** Settings ***
Library hello.py
*** Variables ***
*** Test Cases ***
Example_1
Import Library ${CURDIR}\\..\\work_project\\tk_hello.py "Worked" WITH NAME Try_This
Log To Console \r ${CURDIR}
When you import Hello.py, robot detects a class named hello so it automatically instantiates it. It creates a root window in the __init__ function, so that's your first window.
When you import tk_hello.py, robot detects a class named tk_hello, so it automatically instantiates it. It creates a root window in the __init__ function, that's your second window.
Related
I have a python script which has an object of a class which basically opens a Tkinter window. The problem is that when I create the object, the rest of the program stops running because when I create the Tkinter object, it basically starts an infinite while loop.
The thing is that I want to change, i.e. the text in a label, but from my other class.
My two files look roughly like this:
from tkinter import *
class Panel():
def __init__(self):
self.root = Tk()
width = 300
screen_width = int(self.root.winfo_screenwidth())
screen_height = int(self.root.winfo_screenheight())
self.root.geometry(str(width)+"x50+"+str(screen_width-width)+"+0")
self.root.overrideredirect(True)
#Create Label
self.label = Label(self.root, text="Text")
self.label.pack()
self.root.mainloop()
def closePanel(self):
self.root.quit()
def editText(self,new_text):
self.label.configure(text=new_text)
And my other class:
from Panel import *
outputPanel = Panel()
outputPanel.editText("New Text")
When you create a tkinter application, your whole application should run as a tkinter application. Therefore you need to create the main window at the highest level. Everything else must run within the mainloop of the tkinter program.
In your case, the Panel module instantiates a class which instantiates a tkinter window. You must move that instantiation to the the Panel module itself. Here is my version of you modified code, just to give a basic idea:
from tkinter import *
class Panel():
def __init__(self, root): # root is passed when instantiating Panel()
self.root=root # make root an instance variable
width = 300
screen_width = int(self.root.winfo_screenwidth())
screen_height = int(self.root.winfo_screenheight())
self.root.geometry(str(width)+"x50+"+str(screen_width-width)+"+0")
self.root.overrideredirect(True)
#Create Label
self.label = Label(self.root, text="Text")
self.label.pack()
def closePanel(self):
self.root.quit()
def editText(self,new_text):
self.label.configure(text=new_text)
root = Tk() # create a window at highest level
outputPanel = Panel(root) # Panel may be imported and accessed here
outputPanel.editText("New Text")
outputPanel.editText("New Text")
root.mainloop()
There is an excellent post about how to structure a tkinter application here: Best way to structure a tkinter application?
Put outputPanel.root.mainloop() after outputPanel.editText("New Text") and remove self.root.mainloop().
There are some similar questions already on this site. The difference is that I'm coding the Tkinter window as a class. Then making an instance in another file. For example:
import file
gui = file.Window()
gui.mainloop()
# The program continues, using the variables chosen by the user in the previous window.
while file is another file that contains the window code:
import tkinter as tk
class Window(tk.Tk):
def __init__(self, master):
# some code
def mainWidgets(self):
self.body = Body(self)
self.body.grid(row=0, column=0)
class Body(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
self.master = master
self.widgets()
def widgets(self):
# Labels entries and selections
self.boton_enviar = tk.Button(self, text='Send', command=self.send)
self.boton_enviar.grid()
def send(self):
variables = self.variables
# What code do I add here?
self.quit()
So I want to close the window when clicking the 'Send' button but I need to retrieve some variables to use in the main program. How can I do this ?
I'm trying to write a program that I can hide and show via hotkeys. I managed to get the application to show and hide using the library "keyboard", however due to the "wait" function of the library, it prevents the Text box from functioning correctly. I have tried using the key bindings within Tkinter, however I had a different problem, whereby once the program was hidden or another application was selected, I couldn't return the focus to the hidden window via the hotkey.
import Tkinter as Tk
import keyboard
class MyApp(object):
def __init__(self, parent):
self.root = parent
self.root.title("Main frame")
self.frame = Tk.Frame(parent)
self.frame.pack()
self.editor = Tk.Text(self.frame)
self.editor.pack()
self.editor.config(font="Courier 12")
self.editor.focus_set()
keyboard.add_hotkey('ctrl+alt+s', self.show)
keyboard.add_hotkey('ctrl+alt+h', self.hide)
keyboard.wait()
self.root.withdraw()
def show(self):
self.root.update()
self.root.deiconify()
def hide(self):
self.root.withdraw()
if __name__ == "__main__":
root = Tk.Tk()
root.geometry("800x600")
app = MyApp(root)
root.mainloop()
Any assistance would be great :)
Just drop this wait command, its an additional mainloop, which is not needed as Tkinter does its job. I tried to fix your problem with threading, but as I wanted to check exactly what is NOT working, I accidentially made what I suppose you wanted to. So the Code is:
import tkinter as tk
import keyboard
class App(tk.Tk):
def __init__(self):
super().__init__()
self.geometry("800x600")
self.title("Main frame")
self.editor = Tk.Text(self)
self.editor.pack()
self.editor.config(font="Courier 12")
self.editor.focus_set()
keyboard.add_hotkey('ctrl+alt+s', self.show)
keyboard.add_hotkey('ctrl+alt+h', self.hide)
def show(self):
self.update()
self.deiconify()
def hide(self):
self.update()
self.withdraw()
if __name__ == "__main__":
App().mainloop()
I hope this works for you. I'd also recommend changing this key settings. Testing with those in PyZo is IMPOSSIBLE! It always tries to "save as...", which I don't want to...
I have a tkinter GUI python code that creates a gui interface to my code, in the code later snack sound toolkit is used (which also uses Tk and creates an instance using root = Tk()). As, mainloop of the previously GUI application is already running to everytime snack function is called a new empty default tk window pops up. As this happens quite a lot, there are hundreds of empty tk windows on screen when this code executes. I have tried to close them using numerous methods root.destroy,root.withdraw, WM_DELETE_WINDOW etc. but to no solution.
Is there any way this can be done in tkinter?
import tkSnack
import thread
import Tkinter as tk
class my_gui(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.button = tk.Button(self, text="Get", command=self.on_button)
self.button.grid(row=8)
def on_button(self):
thread1 = thread.start_new_thread(run, (PATH_TO_WAVE_FILE,))
def run(path):
for k in range(10):
PITCH_VALUES = snack_work(path)
print PITCH_VALUES
def snack_work(INPUT_WAVE_FILE):
# initializing the snack tool
root = tk.Tk()
tkSnack.initializeSnack(root)
# root.withdraw()
mysound = tkSnack.Sound()
# processing original wave file
mysound.read(INPUT_WAVE_FILE)
PITCH_VALUES = mysound.pitch()
return PITCH_VALUES
app = my_gui()
app.mainloop()
Make run() and snack_work() into instance methods of your app object, so that they can easily access that object's attributes. To work with a more minimal MCVE that doesn't rely on external libraries or files, I tested the following with simple print() (I'm on Python 3) and after() calls rather than snack stuff, as all I wanted to check was that the other functions could access a tkinter object.
import tkSnack
import thread
import Tkinter as tk
class my_gui(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.button = tk.Button(self, text="Get", command=self.on_button)
self.button.grid(row=8)
def on_button(self):
thread1=thread.start_new_thread(self.run,(PATH_TO_WAVE_FILE,))
def run(self, path):
for k in range(10):
PITCH_VALUES = self.snack_work(path)
print PITCH_VALUES
def snack_work(self, INPUT_WAVE_FILE):
## initializing the snack tool
tkSnack.initializeSnack(self) # use self instead of the separate root object
# self.withdraw()
mysound=tkSnack.Sound()
## processing original wave file
mysound.read(INPUT_WAVE_FILE)
PITCH_VALUES= mysound.pitch()
return PITCH_VALUES
app = my_gui()
app.mainloop()
I have a tkinter menu that lets the user choose some functions. I would like if the output of that functions was presented on a texbox in Tkinter instead of the Shell. Im very unexperienced with Tkinter. I donĀ“t have any ideia how to do it..
Some of the functions require inputs of the user, is it possible for the user to input directly from Tkinter Gui?
The code for the menu of the program:
the functions: situacaocorrente(), findfuncionario(), verhistorico() are not presented here.
CODE
from Tkinter import Tk, Frame, Menu, Label, Text
import sys
class Example(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.output = Text(self)
self.output.pack()
sys.stdout = self
self.initUI()
def initUI(self):
self.parent.title("High Flex")
menubar = Menu(self.parent)
self.parent.config(menu=menubar)
fileMenu = Menu(menubar)
fileMenu.add_command(label="Procurar funcionario", command=self.procurarfuncionario)
fileMenu.add_command(label="Ver Historico", command=self.historico)
fileMenu.add_command(label="Verificar Onde se encontram os funcionarios", command=self.funcionariosturno)
fileMenu.add_command(label="Sair", command=self.onExit)
menubar.add_cascade(label="INICIAR", menu=fileMenu)
def funcionariosturno(self):
situacaocorrente()
def procurarfuncionario(self):
findfuncionario()
def historico (self):
verhistorico()
def onExit(self):
self.quit()
def write(self, txt):
self.output.insert(END,str(txt))
def main():
root = Tk()
root.geometry("250x150+300+300")
app = Example(root)
root.mainloop()
You can use Entry() to get user input. See more on: An Introduction to Tkinter
I don't know what functions output you try to put in self.output - from external program in shell or from python function.
sys.stdout = self works only with Python functions like print