So I'm making a programming language in Python.
This is the code I have so far:
import tkinter as tk
import tkinter.messagebox as m
import sys
class IOscriptError(Exception):
pass
class Std:
def __init__(self):
self.root = tk.Tk()
self.root.title("STDOUT")
self.stdouttext = [""]
self.outstd = tk.Label(self.root, text=self.stdouttext)
self.outstd.pack()
def out(self, value):
self.stdouttext.append(value + "\n")
self.outstd.config(text=''.join(self.stdouttext))
def start(self):
self.root.mainloop()
std = Std()
class Gui:
def __init__(self):
pass
def newButton(self, val, command="m.showinfo('title', 'message')"):
self.b=tk.Button(std.root, text=val, command=command).pack()
gui = Gui()
std.out("Hello!")
std.out("How are you?")
gui.newButton("Hello!")
std.start()
The problem is that the button gui.b's command is not running.
I've also tried with the use of lambda.
It just doesn't work!
Can you please tell me why this is happening and how to fix it?
Thanks!
The problem is that you are trying to pass a string as the command instead of a function. Instead of command="m.showinfo('title', 'message')", try something like this:
def TestCommand():
m.showinfo('title', 'message')
class Gui:
def __init__(self):
pass
def newButton(self, val, command=TestCommand):
self.b=tk.Button(std.root, text=val, command=command).pack()
Remember that the Button constructor takes a function as the command parameter and not a string.
Related
This attempt is try to get the value from a function in class One which is retrieve when the function is call. Then the value [string1] would be passed as a parameter for class Two's method call which's within tkinter, any idea on how can it be attain
from tkinter import Tk, Label, Button
from tkinter import *
from tkinter.ttk import *
class One:
def __init__(self, master):
self.master = master
master.title("Test")
self.greet_button = Button(master, text="Test", command=self.do)
self.greet_button.pack()
def do(self):
...some action...
string1='test'
return string1
class Two:
def write(self, str):
...some action...
#object instantiate within tkinter
root = Tk()
p0 = One(root)
p0.do()
p1 = Two()
p1.write(string1)
root.mainloop()
##from tkinter import Tk, Label, Button
##
##from tkinter import *
##from tkinter.ttk import *
####why are you importing some and then everything?
import tkinter as tk
class Reader_Class(tk.Frame):
def __init__(self, master, writer_class):
tk.Frame.__init__(self,master)
self.master = master
master.title("Test")
self.writer = writer_class
self.greet_button = tk.Button(self, text="Test", command=self.do)
self.greet_button.pack()
def do(self):
string1='test'
self.writer.write(string1)
class Writer_Class(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self,master)
def write(self, test):
print(test)
root = tk.Tk()
writer = Writer_Class(root)
writer.pack()
reader = Reader_Class(root, writer)
reader.pack()
root.mainloop()
Explaination:
So first of all, it isnt necessary to import stuff twice.
Second you need to pass through the interface a reference, therefor you need to have reference. Thats why it makes sense to use the construktor first on the writer_class.
Next you give the reference as a parameter to the reader_class.
reader = Reader_Class(root, writer)
In the reader_class you keep a reference in the local_scope by using the syntax self..
self.writer = writer_class
Finally you use the reference of that class and calling a method of this class, where you can pass through a parameter of your choice.
self.writer.write(string1)
I am trying to inherit some values from one class to a another one. I am using the function super to inherit. Below is a simplfied version of my problem. Thank you for help.
from tkinter import *
import random
class First(object):
def __init__(self,master):
super(First, self).__init__(master)
def random(self):
self._y = random.randint(11,20)
self._x = random.randint(1,10)
def random2(self):
s = First(root)
s.random()
class Second(Frame,First):
def __init__(self,master):
super(Second, self).__init__(master)
self.grid()
self.menuFrame = Frame(self)
self.create_menu_widgets()
self.menuFrame.grid()
def create_menu_widgets(self):
btnMainMenu = Button(self.menuFrame,font=("consolas",18,"bold"),text="Main Menu")
btnMainMenu.pack()
def print(self):
print(self._y,self._x)
root = Tk()
x = Second(root)
x.random()
x.random2()
x.print()
root.configure(background = 'green')
root.mainloop()
I keep on getting the error:
super(First, self).__init__(master)
TypeError: object.__init__() takes no parameters
Please help me, I think the problem is where I have s=First(root). Thanks for help.
When you call super on a class that is the highest in your hierarchy it will go object. object is the super class of all objects in Python. So super(First, self).__init__(master) will try to initialize the object not any of your classes. You can see this inheritance using the Class.__mro__. To figure out what I'm talking about.
And inheriting from object? That happens by default even if you don't specify anything. So I guess you wanted to inherit from Frame as object doesn't make any sense.
So change your code to this and it should be fixed.
from tkinter import *
import random
class First(Frame): # changed here
def random(self):
self._y = random.randint(11,20)
self._x = random.randint(1,10)
def random2(self):
s = First(root)
s.random()
class Second(First): # changed here
def __init__(self,master):
super(Second, self).__init__(master)
self.grid()
self.menuFrame = Frame(self)
self.create_menu_widgets()
self.menuFrame.grid()
def create_menu_widgets(self):
btnMainMenu = Button(self.menuFrame,font=("consolas",18,"bold"),text="Main Menu")
btnMainMenu.pack()
def print(self):
print(self._y,self._x)
root = Tk()
x = Second(root)
x.random()
x.random2()
x.print()
root.configure(background = 'green') # you cannot see this as your button fills everything
root.mainloop()
I see several issues in your example.
1:
you are assigning Second() to x but then calling x.random() and x.random2(). This will not work as your random methods only exist in the First() class.
2:
Don't name a function, method, variable or attribute the same thing as a built in method. This will cause problems.
Change your def print(self) to something like def my_print(self) or anything that is not exactly print. While we are talking about this print statement you only define self._x and self._y in your First() class but try to print them in your Second() class. This will never work. self is always a reference to the class object and never a reference to a class controller that was passed to the class.
Now I get what you are trying to do here and I will rebuild your code to show how to share information between classes.
You should not use a geometry manager fro inside the Frame class. Instead use it on the class variable name. This will allow you chose between any geometry manager for the class instead of sticking to just one kind.
As Vineeth pointed out you do not use supper for an object class.
The below code will run the Second() class and then when you want to reference the random methods on the First() class you can do so with the new methods I added to Second(). Let me know if you have any questions.
One last change is to import tkinter as tk this will help prevent accidentally overwriting an imported method from tkinter.
Here is a working example of your code:
import tkinter as tk
import random
class First(object):
def random(self):
return "From First.Random!", random.randint(11,20), random.randint(1,10)
def random2(self):
return "From First.Random2!", self.random()
class Second(tk.Frame):
def __init__(self, master):
super(Second, self).__init__(master)
self.menuFrame = tk.Frame(self)
self.menuFrame.grid()
tk.Button(self.menuFrame, font=("consolas", 18, "bold"), text="Main Menu").pack()
def random(self):
print(First().random())
def random2(self):
print(First().random2())
root = tk.Tk()
root.configure(background='green')
x = Second(root)
x.pack()
x.random()
x.random2()
root.mainloop()
I'm having an issue trying to call a class's method from a command on tkinters button. I have tried:
command = Alarm_clock.save_alarm()
command = self.save_alarm()
command = Alarm_clock.save_alarm(self.hour_count, self.min_count)
command = Alarm_clock.save_alarm(self)
I think I'm missing something obvious because I have managed to 'command' methods within the same class.
Here is a snippet of my code: It's for an alarm clock:
import tkinter as tk
import time
import vlc
import pygame
from mutagen.mp3 import MP3
class Alarm_clock():
def __init__(self):
alarm_list = []
def save_alarm(self):
print(init_alarm_gui.hour_count.get())
print(init_alarm_gui.min_count.get())
#get the hour and minute and append it to the alarm_list to be checked on real time
class init_alarm_gui():
def __init__(self, root):
self.root = root
self.hour_count = 0
self.min_count = 0
def make_widgets(self, root):
self.hour_count = tk.IntVar()
self.min_count = tk.IntVar()
self.time_label = tk.Label(text="")
self.time_label.pack()
self.Save_but = tk.Button(root, text = "Save Alarm", command=Alarm_clock.save_alarm)
self.Save_but.pack()
def main():
root = tk.Tk()
gui = init_alarm_gui(root)
gui.make_widgets(root)
root.mainloop()
if __name__ == "__main__":
main()
TyperError: save_alarm() missing 1 required positional argument: 'self'
You must create an instance of the class, and then call the method of the instance. This will automatically fill in the self parameter. This isn't unique to tkinter, it's just how python works.
alarm = Alarm_clock()
alarm.save_alarm()
in my code, the main window is emitting event signals, which are to be caught by the child windows, which will show the change in a label. But only the last child window catches the event signal, and changes it's label. what's wrong?
from Tkinter import *
from threading import Timer as tt
class main(Tk):
def __init__(self):
Tk.__init__(self)
tt(.5,self.timedsig).start()
for i in range (5):
child(self,i)
def timedsig(self):
self.event_generate("<<timedsig>>")
tt(.5,self.timedsig).start()
class child(Toplevel):
def __init__(self,master,num):
Toplevel.__init__(self)
self.title(str(num))
self.num=num
self.var=IntVar()
self.var.set(0)
Label(self,textvariable=self.var).pack()
self.master=master
self.master.bind("<<timedsig>>",self.changelabel)
def changelabel(self,e):
print self.num,self.var.get()
self.var.set(self.var.get()+1)
if __name__=="__main__":
main().mainloop()
Calling bind also unbinds all previous functions. To bind an additional function, you need to use the optional 3rd argument:
self.master.bind("<<timedsig>>",self.changelabel, '+')
But that's pretty silly to do in your case when you can simply pass the variable to the instances:
import Tkinter as tk
class Main(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.var = tk.IntVar(value=0)
for i in range (5):
Popup(self, i, self.var)
self.timedsig() # start the looping
def timedsig(self):
self.var.set(self.var.get() + 1)
self.after(500, self.timedsig) # call this again in 500 ms
class Popup(tk.Toplevel):
def __init__(self, master, num, var):
tk.Toplevel.__init__(self)
self.title(str(num))
lbl = tk.Label(self,textvariable=var)
lbl.pack()
if __name__=="__main__":
root = Main()
root.mainloop()
Also, that's not what we usually call a "child". It's just a different object.
From what I read, it is best practice to wrap code for a GUI in a class. How do I do this? I have come up with the following code based on some examples I have looked at, but this does not work as apparently DropdownMenu isn't defined? I have used this function successfully without the class wrapping.
import Tkinter as tk
import tkFileDialog
import os
class Window(tk.Frame):
def DropdownMenu(options,status,name):
optionFrame = tk.Frame(root)
optionLabel = tk.Label(optionFrame)
optionLabel["text"] = name
optionLabel.pack(side=LEFT)
var = StringVar(root)
var.set(status)
w = tk.OptionMenu(optionFrame, var, *options)
w.pack(side=LEFT)
optionFrame.pack()
return w
def __init__(self,parent):
tk.Frame.__init__(self,parent)
ndim_options = DropdownMenu(("1","2","3"),'-',"Number of dimensions")
if __name__ == "__main__":
root = tk.Tk()
Window(root).pack()
root.mainloop()
When you call DropdownMenu (inside the class), use self ...
ndim_options = self.DropdownMenu((...