I am trying to create couple of windows classed using Tkinter. I get no error when I run the code but it doesn't display anything. Am I missing anything?
def main():
root = Tk()
app = startpage(root)
class startpage:
def __init__(self, master):
self.master = master
self.master.title("Main Page")
self.master.geometry('1350x750+0+0')
self.master.config(bg = "blue")
self.frame = Frame(self.master, bg = 'blue')
self.frame.pack()
def EntryWin(self):
self.Entry_win = Toplevel(self.master)
self.app = Entrypage(self.Entry_win)
class Entrypage:
def __init__(self, master):
self.master = master
self.master.title("Entry Page")
self.master.geometry('1350x750+0+0')
self.master.config(bg = "green")
self.frame = Frame(self.master, bg = 'blue')
self.frame.pack()
if __name__ == 'main__':
main()
You have misspelt __main__ as main__ when you call the main function.
Also import tkinter at the beginning of the code, and add root.mainloop() in the main().
from tkinter import *
Here is the corrected code:
from tkinter import *
def main():
root = Tk()
app = startpage(root)
root.mainloop()
class startpage:
def __init__(self, master):
self.master = master
self.master.title("Main Page")
self.master.geometry('1350x750+0+0')
self.master.config(bg = "blue")
self.frame = Frame(self.master, bg = 'blue')
self.frame.pack()
def EntryWin(self):
self.Entry_win = Toplevel(self.master)
self.app = Entrypage(self.Entry_win)
self.master.mainloop()
class Entrypage:
def __init__(self, master):
self.master = master
self.master.title("Entry Page")
self.master.geometry('1350x750+0+0')
self.master.config(bg = "green")
self.frame = Frame(self.master, bg = 'blue')
self.frame.pack()
self.master.mainloop()
if __name__ == '__main__':
main()
Related
file1.py
from tkinter import *
from file2 import fun1
class Frame1(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.LabelFrame1 = LabelFrame(self, bg="#caf0f8", fg="#000000", relief="flat")
self.LabelFrame1.place(relx=0.0, rely=0.0, relheight=1.0, relwidth=1.0)
fun1(self.LabelFrame1)
class MainWindow(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.MainWindow1 = LabelFrame(self, bg="#eaf4f4", fg="#000000", relief="flat")
self.MainWindow1.place(relx=0.0, rely=0.0, relheight=1.0, relwidth=1.0)
class Main:
def __init__(self, master):
super().__init__()
self.Frame1 = Frame1(master)
self.Frame1.place(relx=0.0, rely=0.0, relheight=1.0, relwidth=0.125)
self.MainWindow = MainWindow(master)
self.MainWindow.place(relx=0.127, rely=0.0, relheight=1.0, relwidth=0.873)
if __name__ == "__main__":
root = Tk()
app = Main(root)
root.mainloop()
file2.py
from tkinter import *
from file3 import fun2
def fun1(LabelFrame1):
btn1 = Button(LabelFrame1)
btn1.configure(text="Button 1")
btn1.place(relx=0.1, rely=0.1, relheight=0.2, relwidth=0.8)
btn2 = Button(LabelFrame1)
btn2.configure(text="Button 2")
btn2.place(relx=0.1, rely=0.5, relheight=0.2, relwidth=0.8)
btn2.bind('<Button-1>', lambda e: fun2)
file3.py
from tkinter import *
def fun2(MainWindow1):
lframe1 = LabelFrame(MainWindow1)
lframe1.place(relx=0.0, rely=0.0, relheight=1.0, relwidth=1.0)
lbl1 = Label(lframe1, bg="#fdfdfd", fg="#000000", anchor="w", text="Name\t\t:")
lbl1.place(relx=0.1, rely=0.1, relheight=0.2, relwidth=0.4)
ent1 = Entry(lframe1, bg="#fdfdfd", fg="#000000", relief="flat", highlightthickness="1",
highlightcolor="#147efb")
ent1.place(relx=0.6, rely=0.1, relheight=0.2, relwidth=0.4)
lbl2 = Label(lframe1, bg="#fdfdfd", fg="#000000", anchor="w", text="Address\t\t:")
lbl2.place(relx=0.1, rely=0.5, relheight=0.2, relwidth=0.4)
ent2 = Entry(lframe1, bg="#fdfdfd", fg="#000000", relief="flat", highlightthickness="1",
highlightcolor="#147efb")
ent2.place(relx=0.6, rely=0.5, relheight=0.2, relwidth=0.4)
Here the problem m getting is, if I'm calling file3 inside class MainWindow(Frame) as
fun2(self.MainWindow1)
it is displaying without use of button i.e. before I click on btn2
can anyone help me with how I can make it work.
m trying to make desktop application for which I had to create so many files
I am working with python 3.8, macos Big Sur.
from tkinter import *
def test(window):
window.iconify()
def onclick():
window = Toplevel()
window.geometry("+300+300")
window.title("child window")
Button(window, text="click", command=lambda: test(window)).pack()
window.mainloop()
root = Tk()
root.title("parent window")
root.geometry("300x200+200+200")
root.resizable(False, False)
root.iconbitmap("tools.ico")
Button(root, text="open child window", command=onclick).pack()
root.mainloop()
I am trying to rewrite the code above as a class, like:
import tkinter as tk
from tkinter import ttk
class GUI:
def __init__(self):
self.root = tk.Tk()
self.root.title('title')
self.root.geometry("300x200+500+250")
self.root.resizable(False, False)
self.interface()
self.root.iconbitmap("tools.ico")
def interface(self):
self.btn = tk.Button(self.root, text="open child window", command=self.onclick).pack()
def onclick(self):
window = tk.Toplevel()
window.geometry('200x100+500+250')
window.title('child window')
self.btn = tk.Button(window, text="click", command=lambda window: self.test(*window)).pack()
window.mainloop()
def test(self, window):
window.iconify()
if __name__ == '__main__':
gui = GUI()
gui.root.mainloop()
however, it ends with
Traceback (most recent call last):
File "/Applications/miniconda3/lib/python3.8/tkinter/__init__.py", line 1892, in __call__
return self.func(*args)
TypeError: <lambda>() missing 1 required positional argument: 'window'
I also have tried binding an iconify event with button, like:
import tkinter as tk
from tkinter import ttk
class GUI:
def __init__(self):
self.root = tk.Tk()
self.root.title('title')
self.root.geometry("300x200+500+250")
self.root.resizable(False, False)
self.interface()
self.root.iconbitmap("tools.ico")
def interface(self):
self.btn = tk.Button(self.root, text="open child window", command=self.onclick).pack()
def onclick(self):
window = tk.Toplevel()
window.geometry('200x100+500+250')
window.title('child window')
self.btn = tk.Button(window, text="click")
self.btn.pack()
self.btn.bind("<Button-1>", self.test(window=window))
window.mainloop()
def test(self, window):
window.iconify()
if __name__ == '__main__':
gui = GUI()
gui.root.mainloop()
just did not work either.
I would appreciate if anyone point out how I could work with lambda: window in the first example code given above.
==2022/8/13==:
class GUI:
def __init__(self):
self.root = tk.Tk()
self.root.title('title')
self.root.geometry("300x200+500+250")
self.root.resizable(False, False)
self.interface()
self.root.iconbitmap("tools.ico")
def interface(self):
btnopen = tk.Button(self.root, text="open child window", command=self.onclick).pack()
def onclick(self):
window = tk.Toplevel()
window.geometry('200x100+500+250')
window.title('child window')
btnclick = tk.Button(window, text="click", command=lambda: self.test(window)).pack()
window.mainloop()
def test(self, window):
window.iconify()
window.deiconify()
if __name__ == '__main__':
gui = GUI()
gui.root.mainloop()
pass with the code above...
a low class mistake I made is that I defined 2 self.btn. Besides, it should work with lambda: self.test(window).
If all you are looking to do is iconify() the window then why not just use that in the command? No need to separate it as its own method. Is this what you are looking for?
import tkinter as tk
from tkinter import ttk
class GUI:
def __init__(self):
self.root = tk.Tk()
self.root.title('title')
self.root.geometry("300x200+500+250")
self.root.resizable(False, False)
self.interface()
#self.root.iconbitmap("tools.ico")
def interface(self):
self.btn = tk.Button(self.root, text="open child window", command=self.onclick)
self.btn.pack()
def onclick(self):
window = tk.Toplevel()
window.geometry('200x100+500+250')
window.title('child window')
self.btn = tk.Button(window, text="click", command=lambda: window.iconify())
self.btn.pack()
if __name__ == '__main__':
gui = GUI()
gui.root.mainloop()
I want the main frame refresh to update the label When I click the "done" button on MyDialog, But now it doesn't work.
Does there anything wrong? Thanks.
This is the code:
MyDialog: the child dialog where there is a button on it to update the label of the main frame
MainFrame: the main Frame, there is a button on it to start my dialog
# -*- coding: utf-8 -*-
import wx
#Dialog
class MyDialog(wx.Dialog):
"""setting MyDialog."""
def __init__(self):
self.dlg_main = wx.Dialog.__init__(self, None, -1, title="setting", size=(300, 300))
self.btn_ok = wx.Button(self, label="done", pos=(30, 30), size=(50, 26))
self.Bind(wx.EVT_BUTTON, self.__OnButtonClick_save, self.btn_ok,)
def __OnButtonClick_save(self, event):
self.Destroy()
main = MainFrame()
**main.set_label_name('test')**
main.Destroy()
def start_dialog():
my_dialog = MyDialog()
my_dialog.ShowModal()
my_dialog.Destroy()
#Main Frame
class MainFrame(wx.Frame):
def __init__(self):
self.main_frame = wx.Frame.__init__(self, None, -1, title='simple', size=(400, 400))
self.Centre()
self.label_name = wx.StaticText(self, label="Hello,everyone", pos=(30, 30))
self.btn_set = wx.Button(self, label="set", pos=(30, 60))
self.Bind(wx.EVT_BUTTON, self.on_button_click, self.btn_set)
def set_label_name(self, str):
print(str)
self.label_name.SetLabel('hello, Boys')
def on_button_click(self, event):
start_dialog()
def show_main():
main = wx.App()
main_win = MainFrame()
main_win.Show()
main.MainLoop()
if __name__ == '__main__':
show_main()
I have got the method, thanks all!
The point is how to call the parent method, so , use self.parent.xxx to fix the problem.
The code like this:
# -*- coding: utf-8 -*-
import wx
#Dialog
class MyDialog(wx.Dialog):
"""setting MyDialog."""
def __init__(self, parent, title):
super(MyDialog, self).__init__(parent, title=title, size=(300, 300))
self.parent = parent
panel = wx.Panel(self)
btn_ok = wx.Button(panel, label="done", pos=(30, 30), size=(50, 26))
btn_ok.Bind(wx.EVT_BUTTON, self.__OnButtonClick_save)
def __OnButtonClick_save(self, event):
#THis is the different
self.parent.set_label_name('test')
self.Destroy()
def start_dialog():
my_dialog = MyDialog()
my_dialog.ShowModal()
my_dialog.Destroy()
#Main Frame
class MainFrame(wx.Frame):
def __init__(self):
self.main_frame = wx.Frame.__init__(self, None, -1, title='simple', size=(400, 400))
self.init_ui()
def init_ui(self):
self.label_name = wx.StaticText(self, label="Hello,everyone", pos=(30, 30))
btn_set = wx.Button(self, label="set", pos=(30, 60))
btn_set.Bind(wx.EVT_BUTTON, self.on_button_click)
self.Centre()
def set_label_name(self, str):
self.label_name.SetLabel('hello, Boys')
def on_button_click(self, event):
my_dialog = MyDialog(self, "setting")
my_dialog.ShowModal()
my_dialog.Destroy()
def show_main():
main = wx.App()
main_win = MainFrame()
main_win.Show()
main.MainLoop()
if __name__ == '__main__':
show_main()
Thanks for the idea in this answer Wxpython show dialog on main frame startup
I've got this simple program. Its has a button and when you press it a second window will come up.
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
import urllib.request
class second_window(QDialog):
def __init__(self, parent=None):
QDialog.__init__(self)
super(second_window, self).__init__(parent)
layout = QVBoxLayout()
button = QPushButton("close")
button.clicked.connect(self.button_clicked)
layout.addWidget(button)
self.setLayout(layout)
def button_clicked(self):
self.close()
class Main_window(QDialog):
def __init__(self):
QDialog.__init__(self)
layout = QVBoxLayout()
button = QPushButton("Second Window")
self.sec_window = second_window(self)
layout.addWidget(button)
button.clicked.connect(self.button_clicked)
self.setLayout(layout)
def button_clicked(self):
self.sec_window.exec_()
if __name__ == "__main__":
app = QApplication(sys.argv)
dl = window()
dl.show()
app.exec()
But sometimes if you close the Main_window just after you close the second_window it crashes and I get a message saying "Python.exe has stopped working".
can anyone help?
First Solution: Change self.sec_window = second_window(self) to self.sec_window = second_window() since it will not be necessary to clean because there is no relationship between second_window and Main_window. As the following code shows
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
class second_window(QDialog):
def __init__(self, parent=None):
QDialog.__init__(self)
super(second_window, self).__init__(parent)
layout = QVBoxLayout()
button = QPushButton("close")
button.clicked.connect(self.button_clicked)
layout.addWidget(button)
self.setLayout(layout)
def button_clicked(self):
self.close()
class Main_window(QDialog):
def __init__(self):
QDialog.__init__(self)
layout = QVBoxLayout()
button = QPushButton("Second Window")
self.sec_window = second_window()
layout.addWidget(button)
button.clicked.connect(self.button_clicked)
self.setLayout(layout)
def button_clicked(self):
self.sec_window.exec_()
if __name__ == "__main__":
app = QApplication(sys.argv)
dl = Main_window()
dl.show()
app.exec()
Second Solution: Add self.sec_window.deleteLater() on closeEvent(self, event) to be able to delete second_window
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
class second_window(QDialog):
def __init__(self, parent=None):
QDialog.__init__(self)
super(second_window, self).__init__(parent)
layout = QVBoxLayout()
button = QPushButton("close")
button.clicked.connect(self.button_clicked)
layout.addWidget(button)
self.setLayout(layout)
def button_clicked(self):
self.close()
class Main_window(QDialog):
def __init__(self):
QDialog.__init__(self)
layout = QVBoxLayout()
button = QPushButton("Second Window")
self.sec_window = second_window(self)
layout.addWidget(button)
button.clicked.connect(self.button_clicked)
self.setLayout(layout)
def button_clicked(self):
self.sec_window.exec_()
def closeEvent(self, event):
self.sec_window.deleteLater()
super().closeEvent(event)
if __name__ == "__main__":
app = QApplication(sys.argv)
dl = Main_window()
dl.show()
app.exec()
I am trying to build a simple GUI using tkinter to read in CSV's and then run some text mining functions. I am having difficulty understand tkinter's callback function. The following code was created using this ToyMVC code.
I am able to get the GUI to pop up but am having trouble getting the rightmost Entry widget (variable name = finalPathEntry) to update with the user-inputted text from the left Widget once the user presses the button.
I would greatly appreciate any advice on how to move forward and what I am doing wrong.
Best,
import tkinter as tk
class Observable:
def __init__(self, initialValue=None):
self.data = initialValue
self.callbacks = {}
def addCallback(self, func):
self.callbacks[func] = 1
def delCallback(self, func):
del self.callback[func]
def _docallbacks(self):
for func in self.callbacks:
func(self.data)
def set(self, data):
self.data = data
self._docallbacks()
def get(self):
return self.data
def unset(self):
self.data = None
class Model:
def __init__(self):
self.csvPath = Observable("")
def addPath(self, value):
self.csvPath.set(self.csvPath.get())
class View(tk.Toplevel):
def __init__(self, master):
tk.Toplevel.__init__(self, master)
self.protocol('WM_DELETE_WINDOW', self.master.destroy)
tk.Label(self, text='Please input path to CSV').pack(side='left')
self.pathEntry = tk.Entry(self, width=50)
self.pathEntry.pack(side='left')
self.addButton = tk.Button(self, text='Read CSV', width=8)
self.addButton.pack(side='left')
self.path = tk.StringVar()
self.finalPathEntry = tk.Entry(self, width = 30, textvariable = self.path)
self.finalPathEntry.pack(side='left')
def setPath(self, value):
self.path.set(str(value))
class Controller:
def __init__(self, root):
self.model = Model()
self.model.csvPath.addCallback(self.pathChanged)
self.view1 = View(root)
self.view1.minsize(width = 500, height = 500)
self.view1.addButton.config(command=self.addPath)
self.pathChanged(self.model.csvPath.get())
def addPath(self):
self.model.addPath(self.view1.pathEntry.get())
def pathChanged(self, val):
self.view1.setPath(val)
if __name__ == '__main__':
root = tk.Tk()
root.withdraw()
app = Controller(root)
root.mainloop()
EDIT: Using the answer below, I have fixed my code. Here is the updated and working snippet:
import tkinter as tk
class Observable:
def __init__(self, initialValue = None):
self.data = initialValue
self.callbacks = {}
def addCallback(self, func):
self.callbacks[func] = 1
def delCallback(self, func):
del self.callback[func]
def _docallbacks(self):
for func in self.callbacks:
func(self.data)
def set(self, data):
self.data = data
self._docallbacks()
def get(self):
return self.data
def unset(self):
self.data = None
class Model:
def __init__(self):
self.csvPath = Observable("")
def addPath(self, value):
self.csvPath.set(self.csvPath.get())
class View(tk.Toplevel):
def __init__(self, master):
tk.Toplevel.__init__(self, master)
self.protocol('WM_DELETE_WINDOW', self.master.destroy)
tk.Label(self, text='Please input path to CSV').pack(side='left')
self.pathEntry = tk.Entry(self, width=50)
self.pathEntry.pack(side='left')
self.addButton = tk.Button(self, text='Read CSV', width=8)
self.addButton.pack(side='left')
self.path = tk.StringVar()
self.finalPathEntry = tk.Entry(self, width = 30, textvariable = self.path)
self.finalPathEntry.pack(side='left')
def setPath(self, value):
self.path.set(str(value))
class Controller:
def __init__(self, root):
self.model = Model()
self.model.csvPath.addCallback(self.pathChanged)
self.view1 = View(root)
self.view1.minsize(width = 500, height = 500)
self.view1.addButton.config(command = self.addPath)
self.pathChanged(self.model.csvPath.get())
def addPath(self):
self.model.addPath(self.view1.pathEntry.get())
def pathChanged(self, val):
self.view1.setPath(val)
if __name__ == '__main__':
root = tk.Tk()
root.withdraw()
app = Controller(root)
root.mainloop()
One thing about this code seems obvious: The functions beginning at
def addcallback(self, func):
until
def unset(self):
are not part of the Observable class. So the "self" argument is not what you expect it to be. You should indent these functions.