I am building a script having one counter and an image. Both are in different canvas on single window. I am trying to update the canvas image once the timer stops. Below is my code. I am not getting whats wrong with this
from Tkinter import *
import Tkinter as tk
import stopwatch
import stone_image
class App():
def __init__(self, root):
self.root = root
self.root.configure(background="yellow")
global stoneImagePanel
stopwatchPanel = tk.Canvas(self.root, background="yellow")
stoneImagePanel = tk.Canvas(self.root, background="yellow")
stopwatchPanel.grid(row=0, column=0, columnspan=4, sticky="e")
stoneImagePanel.grid(row=1, column=0, rowspan=2, columnspan=4, sticky="news")
self.stoneImage_canvas(stoneImagePanel)
self.stopWatch_canvas(stopwatchPanel)
def stopWatch_canvas(self, parent):
stopwatch.timerStart(parent, 500)
stoneImagePanel.after(500, self.update(stoneImagePanel))
def stoneImage_canvas (self, parent):
displayImage = stone_image.DisplayImage(parent)
displayImage.stoneImg('images/stone.jpg')
def update(self, parent):
displayImage = stone_image.DisplayImage(parent)
displayImage.stoneImg('images/UP.png')
if __name__ == "__main__":
root = Tk()
app = App(root)
root.mainloop()
Neither the stopwatch is working smoothly nor the image is updating. Please help.
Related
My problem is, that then i open a second window with a button in the first window, the spinbox in the second window does not give an output. If i start the second one individually, it works as expectet. I used the pygub designer to design the windows.
Here is my Code from the first (main) window:
import tkinter.ttk as ttk
from tkinter import messagebox
import Test2
class NewprojectApp:
def __init__(self, master=None):
# build ui
toplevel1 = tk.Tk() if master is None else tk.Toplevel(master)
toplevel1.configure(height=500, width=500)
entry1 = ttk.Entry(toplevel1)
self.Entrytest1 = tk.StringVar()
entry1.configure(textvariable=self.Entrytest1)
entry1.pack(padx=10, pady=10, side="top")
spinbox1 = ttk.Spinbox(toplevel1)
self.Spinbox1 = tk.IntVar()
spinbox1.configure(from_=0, increment=1, textvariable=self.Spinbox1, to=10)
spinbox1.pack(padx=10, pady=10, side="top")
button2 = ttk.Button(toplevel1)
button2.configure(text="Neuesfenster")
button2.pack(padx=10, pady=10, side="top")
button2.bind("<ButtonPress>", self.ereignisbehandler, add="")
# Main widget
self.mainwindow = toplevel1
def run(self):
self.mainwindow.mainloop()
def ereignisbehandler(self, event=None):
messagebox.showinfo("Test", self.Spinbox1.get())
Test2.secondwindow()
if __name__ == "__main__":
app = NewprojectApp()
app.run()
And the second window:
import tkinter as tk
import tkinter.ttk as ttk
from tkinter import messagebox
class NewprojectApp2:
def __init__(self, master=None):
# build ui
toplevel2 = tk.Tk() if master is None else tk.Toplevel(master)
toplevel2.configure(height=500, width=500)
entry2 = ttk.Entry(toplevel2)
self.Entrytest1 = tk.StringVar()
entry2.configure(textvariable=self.Entrytest1)
entry2.pack(padx=10, pady=10, side="top")
spinbox2 = ttk.Spinbox(toplevel2)
self.Spinbox2 = tk.IntVar()
spinbox2.configure(from_=0, increment=1, state="normal", textvariable=self.Spinbox2, to=10)
spinbox2.pack(padx=10, pady=10, side="top")
button4 = ttk.Button(toplevel2)
button4.configure(text="Neuesfenster")
button4.pack(padx=10, pady=10, side="top")
button4.bind("<ButtonPress>", self.ereignisbehandler, add="")
# Main widget
self.mainwindow = toplevel2
def run(self):
self.mainwindow.mainloop()
def ereignisbehandler(self, event=None):
messagebox.showinfo("Test", self.Spinbox2.get())
if __name__ == "__main__":
app = NewprojectApp2()
app.run()
def secondwindow():
app = NewprojectApp2()
app.run()
Thank you for helping!
I want to have several Checkboxes in an CustomFrame, but currently have the following missbehaviour:
If I click on a Checkbox, the whole column gets active and I want to have one the clicked one to be active. Is it possible to "reuse" Checkboxes in tk-derived classes and declare them in Subclasses?
Mainwindow which uses SubFrames:
import tkinter as tk
import zmq
from time import sleep
import time
from threading import Thread
from glmPygameGlue import *
from networkRenderGlue import *
from quatLTI import *
import guiWidgets as gw
class Window(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master)
#super().__init__()
self.accWidget = gw.Widget_Vector(self, "ACC")
self.gyroWidget = gw.Widget_Vector(self, "GYRO")
self.magWidget = gw.Widget_Vector(self, "MAG")
self.accWidget.grid(column=0, row=0)
self.gyroWidget.grid(column=0, row=1)
self.magWidget.grid(column=0, row=2)
self.grid(column=0, row=0)
def AccBiasEnable(self):
print("window accBiasEnable")
def onClose(self):
exit()
root = tk.Tk()
app = Window(root)
root.protocol("WM_DELETE_WINDOW", app.onClose)
root.wm_title("Input-Gui Quaternion-HP")
root.geometry("500x500")
root.mainloop()
SubFrames:
import tkinter as tk
class TripleCheckboxVertical(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master)
self.xBias = tk.Checkbutton(self, text='bias', command=master.master.AccBiasEnable)
self.yBias = tk.Checkbutton(self, text='cos')
self.zBias = tk.Checkbutton(self, text='noise')
self.xBias.grid(column=0, row=0)
self.yBias.grid(column=1, row=0)
self.zBias.grid(column=2, row=0)
def callBackFunc(self, event=None):
print("cb event!1")
class Widget_Vector(tk.LabelFrame):
def __init__(self, master=None, text_=""):
tk.LabelFrame.__init__(self, master, text=text_)
self.master = master
self.labelX = tk.Label(self, text="x")
self.labelY = tk.Label(self, text="y")
self.labelZ = tk.Label(self, text="z")
self.cb3X = TripleCheckboxVertical(self)
self.cb3Y = TripleCheckboxVertical(self)
self.cb3Z = TripleCheckboxVertical(self)
self.labelX.grid(column=0, row=0)
self.labelY.grid(column=0, row=1)
self.labelZ.grid(column=0, row=2)
self.cb3X.grid(column=1,row=0)
self.cb3Y.grid(column=1,row=1)
self.cb3Z.grid(column=1,row=2)
Any ideas?
Thank you
To resolve your issue, add a variable to each checkbutton. I've created 3 BooleanVar which store the value of the checkbutton and makes them behave independently. I've also added a get method to return the value of each checkbox:
class TripleCheckboxVertical(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master)
self.xBiasVar = tk.BooleanVar()
self.yBiasVar = tk.BooleanVar()
self.zBiasVar = tk.BooleanVar()
self.xBias = tk.Checkbutton(self, text='bias', variable = self.xBiasVar, command=master.master.AccBiasEnable)
self.yBias = tk.Checkbutton(self, text='cos', variable = self.yBiasVar)
self.zBias = tk.Checkbutton(self, text='noise', variable = self.zBiasVar)
self.xBias.grid(column=0, row=0)
self.yBias.grid(column=1, row=0)
self.zBias.grid(column=2, row=0)
def get(self):
return {"bias":self.xBiasVar.get(), "cos":self.yBiasVar.get(), "noise":self.zBiasVar.get()}
I also added a get method to Widget_Vector:
def get(self):
return {"x":self.cb3X.get(), "y":self.cb3Y.get(), "z":self.cb3Z.get()}
If you wanted the value of x bias for GYRO, for example, you can do self.gyroWidget.get()["x"]["bias"]
For my program I want the user to select a file, and I am using the tkinter.filedialog library to do this. However, when the askopenfilename dialog is opened, the TopLevelwindow disappears behind the main Tk() window.
How would I stop this from happening?
Here is the code that I have written so far:
from tkinter import *
from tkinter.filedialog import askopenfilename
class MainWin(Tk):
def __init__(self):
super(MainWin, self).__init__()
self.update()
pu = PopUp(self)
self.configure(width=500, height=300)
class PopUp(Toplevel):
def __init__(self, master):
super(PopUp, self).__init__(master)
def entry_set(entry, text):
entry.delete(0, 'end')
entry.insert(END, text)
item_file = StringVar()
item_entry = Entry(self, textvariable=item_file)
item_entry.place(x=80, y=60, height=20, width=300)
item_label = Label(self, text="item file: ", bg="gray74", relief="groove")
item_label.place(x=20, y=60, height=20, width=60)
item_button = Button(self, text="\uD83D\uDCC2", relief="groove",
command=lambda: entry_set(item_entry, askopenfilename()))
item_button.place(x=380, y=60, height=20, width=20)
self.configure(width=460, height=180)
if __name__ == '__main__':
win = MainWin()
win.mainloop()
Edit:
I have realised that using the .grab_set() method works, and will make the
TopLevel() window appear back on top of the Tk() after the file is chosen.
However, this still means the window disappears behind the Tk() window whilst picking a file, I would still love to find a solution to this, even though this is now just a visual problem, not a functional one.
You can just make the Toplevel window a transient window, it will then be kept on top of its parent window:
class PopUp(Toplevel):
def __init__(self, master):
super(PopUp, self).__init__(master)
self.transient(master)
I'm just getting started coding in Python/Tkinter for a small Pymol plugin. Here I'm trying to have a toggle button and report its status when it is clicked. The button goes up and down, but toggleAVA never gets called. Any ideas why?
from Tkinter import *
import tkMessageBox
class AVAGnome:
def __init__(self, master):
# create frames
self.F1 = Frame(rootGnome, padx=5, pady=5, bg='red')
# checkbuttons
self.AVAselected = IntVar()
self.AVAselected.trace("w", self.toggleAVA)
self.AVAbutton = Checkbutton(self.F1, text='AVA', indicatoron=0, variable=self.AVAselected)
# start layout procedure
self.layout()
def layout(self):
self.F1.pack(side=TOP, fill=BOTH, anchor=NW)
#entry and buttons
self.AVAbutton.pack(side=LEFT)
def toggleAVA(self, *args):
if (self.AVAselected.get()):
avastatus = "selected"
else:
avastatus = "unselected"
tkMessageBox.showinfo("AVA status", avastatus)
def __init__(self):
open_GnomeUI()
def open_GnomeUI():
# initialize window
global rootGnome
rootGnome = Tk()
rootGnome.title('AVAGnome')
global gnomeUI
gnomeUI = AVAGnome(rootGnome)
I tested your code with Pymol.
Problem is because you use Tk() to create your window. You have to use Toplevel() and then it will work correctly with trace() or with command=.
Pymol is created with tkinter which can have only one window created with Tk() - it is main window in program. Every other window has to be created with Toplevel().
I have attached a working version of your code below. You can refer to it to learn where you went wrong. Generally, you have to mind how you structure your code if you are using a class format.This will help you visualize your code and debug better. You can read this discussion to help you.
from Tkinter import *
import tkMessageBox
class AVAGnome(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
# create frames
self.F1 = Frame(self, padx=5, pady=5, bg='red')
# checkbutton
self.AVAselected = IntVar()
self.AVAselected.trace("w", self.toggleAVA)
self.AVAbutton = Checkbutton(
self.F1, text='AVA', indicatoron=0, width=10,
variable=self.AVAselected)
# start layout procedure
self.F1.pack(side=TOP, fill=BOTH, anchor=NW)
self.AVAbutton.pack(side=LEFT) #entry and buttons
def toggleAVA(self, *args):
if (self.AVAselected.get()):
avastatus = "selected"
else:
avastatus = "unselected"
tkMessageBox.showinfo("AVA status", avastatus)
if __name__ == '__main__':
rootGnome = Tk()
rootGnome.title('AVAGnome')
gnomeUI = AVAGnome(rootGnome)
gnomeUI.pack(fill="both", expand=True)
gnomeUI.mainloop()
Update: The above code structure is for standalone tkinter programme. I am attempting to convert this working code to follow Pymol plugin example. Revised code is posted below and is susceptible to further revision.
# https://pymolwiki.org/index.php/Plugins_Tutorial
# I adapted from the example in the above link and converted my previous code to
#
from Tkinter import *
import tkMessageBox
def __init__(self): # The example had a self term here.
self.open_GnomeUI()
class AVAGnome(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
# create frames
self.F1 = Frame(self, padx=5, pady=5, bg='red')
# checkbutton
self.AVAselected = IntVar()
self.AVAselected.trace("w", self.toggleAVA)
self.AVAbutton = Checkbutton(
self.F1, text='AVA', indicatoron=0, width=10,
variable=self.AVAselected)
# start layout procedure
self.F1.pack(side=TOP, fill=BOTH, anchor=NW)
self.AVAbutton.pack(side=LEFT) #entry and buttons
def toggleAVA(self, *args):
if (self.AVAselected.get()):
avastatus = "selected"
else:
avastatus = "unselected"
tkMessageBox.showinfo("AVA status", avastatus)
# Note, I added a "self" term throughout function.
# Try w/ & w/o "self" to see which works.
def open_GnomeUI(self):
self.rootGnome = Tk()
self.rootGnome.title('AVAGnome')
self.gnomeUI = AVAGnome(self.rootGnome)
self.gnomeUI.pack(fill="both", expand=True)
self.gnomeUI.mainloop()
I am trying to create a program in tkinter which allows me to open an initial window then to keep it throughout all classes used. For example, if I was to create a button in a window then when I click this button, it would exuecute a method that destroys the widget, and then executes a new class that builds a new screen within the same window, such as text opposed to a button.
from tkinter import *
class Window1:
def __init__(self, master):
self.master = master
self.label = Button(self.master, text = "Example", command = self.load_new)
self.label.pack()
def load_new(self):
self.label.destroy()
## Code to execute next class
class Window2:
def __init__(self, master):
self.master = master
self.label = Label(self.master, text = "Example")
self.label.pack()
def main():
root = Tk()
run = Window1(root)
root.mainloop()
if __name__ == '__main__':
main()
I understand this is less practical, but I am curious. Cheers.
Tk() creates main window and variable root gives you access to this window. You can use root as argument for Window2 and you will have access to main window inside Window2
from tkinter import *
class Window1:
def __init__(self, master):
# keep `root` in `self.master`
self.master = master
self.label = Button(self.master, text="Example", command=self.load_new)
self.label.pack()
def load_new(self):
self.label.destroy()
# use `root` with another class
self.another = Window2(self.master)
class Window2:
def __init__(self, master):
# keep `root` in `self.master`
self.master = master
self.label = Label(self.master, text="Example")
self.label.pack()
root = Tk()
run = Window1(root)
root.mainloop()
--
Probably nobody use another class to create Label in place of Button ;)
--
EDIT: In this example using names Window1 and Windows2 is misleading because there is only one window and two classes which use this window. I would rather use names FirstOwner, SecondOwner
Everything is implemented in one Tk class and in this case there always is only one window.
from tkinter import *
from tkinter import ttk
class MainWindow():
def __init__(self, mainWidget):
self.main_frame = ttk.Frame(mainWidget, width=300, height=150, padding=(0, 0, 0, 0))
self.main_frame.grid(row=0, column=0)
self.some_kind_of_controler = 0
self.main_gui()
def main_gui(self):
root.title('My Window')
self.main_label_1 = ttk.Label(self.main_frame, text='Object_1')
self.main_label_1.grid(row=0, column=0)
self.main_label_2 = ttk.Label(self.main_frame, text='Object_2')
self.main_label_2.grid(row=1, column=0)
self.main_label_3 = ttk.Label(self.main_frame, text='Object_3')
self.main_label_3.grid(row=2, column=0)
self.setings_button = ttk.Button(self.main_frame, text='Setings')
self.setings_button.grid(row=0, column=1)
self.setings_button.bind('<Button-1>', self.setings_gui)
self.gui_elements = [self.main_label_1,
self.main_label_2,
self.main_label_3,
self.setings_button]
def setings_gui(self, event):
self.gui_elements_remove(self.gui_elements)
root.title('Setings')
self.main_label_1 = ttk.Label(self.main_frame, text='Object_1')
self.main_label_1.grid(row=2, column=0)
self.main_menu_button = ttk.Button(self.main_frame, text='Main menu')
self.main_menu_button.grid(row=0, column=1)
self.main_menu_button.bind('<Button-1>', self.back_to_main)
self.some_kind_of_controler = 1
self.gui_elements = [self.main_label_1,
self.main_menu_button]
def back_to_main(self, event):
if self.some_kind_of_controler == 1:
self.gui_elements_remove(self.gui_elements)
else:
pass
self.main_gui()
def gui_elements_remove(self, elements):
for element in elements:
element.destroy()
def main():
global root
root = Tk()
root.geometry('300x150+50+50')
window = MainWindow(root)
root.mainloop()
if __name__ == '__main__':
main()