Tkinter python GUI issue - python

I am trying to create a menu for my term project and I am running into a issue.
I want a left pane for my controls and on the right there will be visulization but when i run the code an un wanted space is created on the top left area because of the t1.pack() and c1.pack()
Please help me how can i get two clear panes.
Let me know if you didnt get the issue.
Thanks in advance :)
__author__ = 'sagar'
try:
import tkinter as tk # for python 3
except:
#import Tkinter as tk # for python 2
from Tkinter import *
import ttk as ttk
import ctypes
import tkMessageBox
user32 = ctypes.windll.user32
WIDTH,HEIGHT = user32.GetSystemMetrics(0),user32.GetSystemMetrics(1)
WIDTH -= 50
HEIGHT -= 75
class Application: #pygubu.TkApplication
def __init__(self,root):
self.root = root
self.fr_main = Frame(self.root,background="grey",highlightcolor="red")
self.fr_main.grid(row=0,column=0,ipadx=(5*WIDTH)/100,ipady=HEIGHT)
# self.fr_main.pack()
self.btn_Simulator = Button(self.fr_main,text="Simulator")
self.btn_Simulator.grid(row=0,column=0,pady=10)
# self.btn_Simulator.pack()
self.btn_Analysis = Button(self.fr_main,text="Analysis")
self.btn_Analysis.grid(row=0,column=1,pady=10)
# self.btn_Analysis.pack()
self.fr_second = Frame(self.root,background="black",highlightcolor="red")
self.fr_second.grid(row=0,column=1,ipadx=(40*WIDTH)/100,ipady=HEIGHT)
self.nb_main = ttk.Notebook(self.fr_second)
self.nb_main.pack(expand=1,fill=BOTH)
f1 = Frame(self.nb_main)
f2 = Frame(self.nb_main)
self.nb_main.add(f2,text="Canvas")
self.nb_main.add(f1,text="Calculation")
t1 = Text(f1)
c1 = Canvas(f2)
c1.configure(background="black")
t1.pack(expand=1,fill=BOTH)
c1.pack(expand=1,fill=BOTH)
def __controlState__(self,control,state):
control.configure(state =state)
def showName(self,Enableframe,DisableFrame):
for child in Enableframe.winfo_children():
Enableframe.config(relief = RAISED)
self.__controlState__(child,"active")
for child in DisableFrame.winfo_children():
self.__controlState__(child,"disable")
if __name__ == '__main__':
root = Tk()
app = Application(root)
root.title("Network Simulator")
root.geometry('%dx%d+%d+%d' % (WIDTH,HEIGHT,0,0))
root.mainloop()

Please help me how can i get two clear panes.
The absolute simplest way to get two frames side-by-side that take up the whole height of the window is to use pack with appropriate options:
self.fr_main.pack(side="left", fill="both", expand=True)
self.fr_second.pack(side="left", fill="both", expand=True)
The key is that the first one needs to be on the left or right side, filling in the "y" direction. After that, the second one can be on any side as long as it fills in both directions.
If you want to use grid, make sure to include the sticky option so that the frames fill the space given to them:
self.fr_main.grid(row=0, column=0, sticky="nsew")
self.fr_second.grid(row=0, column=0, sticky="nsew")
With grid, you'll also want to give the columns weight so that grid knows how to allocate extra space
self.root.grid_rowconfigure(0, weight=1)
self.root.grid_columnconfigure(0, weight=1)
self.root.grid_columnconfigure(1, weight=1)

Related

TkinterVideoPlayer stops resizing the video when it's put inside a frame. How can I stop this?

I'm trying to make a video player that play's a video full screen. The user is also able to toggle onto another frame that I want to take up the full GUI and to be able to toggle in between them.. I have written some code and It works fine when I pack the video player to root but then when I put it inside a frame it shrinks down to a much smaller size than the GUI. Why is this happening and how can I fix it?
This is the code that has the video playing and resizing to the GUI size dynamically
import datetime
import tkinter as tk
from tkinter import *
from turtle import width
from tkVideoPlayer import TkinterVideo
#changing the visible frame on the screen
def showFrame (frame):
frame.tkraise()
root = tk.Tk()
root.title("Hology")
width1, height1= int(root.winfo_screenwidth()), int(root.winfo_screenheight())
root.geometry(str(width1-200) + "x" + str(height1-200))
vid_player = TkinterVideo(master=root, scaled=True)
# vid_player.set_size((width1-200, height1-200))
vid_player.pack(expand=True, fill=BOTH)
progress_value = tk.IntVar(root)
vid_player.bind("<<SecondChanged>>", loopVid)
load_file= "hol.mp4"
vid_player.load(load_file)
vid_player.play()
# vid_player.pack(expand=True, fill="both")
holo.tkraise()
root.mainloop()
This is where it is placed inside a frame
import datetime
import tkinter as tk
from tkinter import *
from turtle import width
from tkVideoPlayer import TkinterVideo
global vidVal
vidVal = 0
#changing the visible frame on the screen
def showFrame (frame):
frame.tkraise()
root = tk.Tk()
root.title("Hology")
width1, height1= int(root.winfo_screenwidth()), int(root.winfo_screenheight())
root.geometry(str(width1-200) + "x" + str(height1-200))
holo = Frame(root)
timeline = Frame(root)
holo.grid(row=0,column=0)
timeline.grid(row=0,column=0)
# root.attributes('-fullscreen',True)
# for frame in (holo, timeline):
# frame.master.geometry(str(width1-200) + "x" + str(height1-200))
# # frame.grid(row=1, column=1, columnspan=10, rowspan=8, sticky=tk.EW)
# # frame.pack_propagate(False)
# frame.pack()
vid_player = TkinterVideo(master=holo, scaled=True)
# vid_player.set_size((width1-200, height1-200))
vid_player.pack(expand=True, fill=BOTH)
load_file= "hol.mp4"
vid_player.load(load_file)
vid_player.play()
# vid_player.pack(expand=True, fill="both")
holo.tkraise()
root.mainloop()
Any help enabling me to keep the video at full size when inside a frame would be greatly appreciated. I have spent some time looking through the documentation and I know it will be a simple fix or something silly, I'm just stuck! :(
Thank you

Why isn't the label animation working till the last value of the loop?

I am new to python and I have been learning tkinter recently. So I thought with myself that using the grid_forget() function I can remove a widget and redefine it. I thought of this animation that changes the padding of a label so it would create space (kind of like moving the label but not exactly). However, the animation does not work at all. The program freezes until the label reaches the last value of the padding. How can I fix this? Or is there a better way to animate a label moving in the screen?
Here is my code:
from tkinter import *
import time
root = Tk()
lbl = Label(root, text='------')
lbl.grid(row=0, column=0)
def animation():
padding = 0
while padding < 31:
lbl.grid_forget()
padding += 1
lbl.grid(row=0, column=0, padx=padding)
time.sleep(0.2)
# alternative: root.after(200, lambda: lbl.grid(row=0, column=0, padx=padding))
btn = Button(root, text='Animate', command=animation)
btn.grid(row=1, column=1)
root.mainloop()
You need to update the screen for changes to be shown.
Here is a working version using the .update() method:
from tkinter import *
import time
root = Tk()
lbl = Label(root, text='------')
lbl.grid(row=0, column=0)
def animation():
padding = 0
while padding < 31:
lbl.grid_forget()
padding += 1
lbl.grid(row=0, column=0, padx=padding)
root.update()
time.sleep(0.2)
# alternative: root.after(200, lambda: lbl.grid(row=0, column=0, padx=padding))
btn = Button(root, text='Animate', command=animation)
btn.grid(row=1, column=1)
root.mainloop()
Here is a way I also use to animate stuff on the screen, I am not able to understand what you were trying to achieve with your code snippet above, I tried making some changes to it but I feel this way is much better and let's you get more control of your window.
This uses the widely used Canvas widget in the tkinter library.
The Canvas is a general purpose widget, You can use it for a lot of things. Visit the hyper link for more clarity
Here is a short example of how you would create text on the screen.
from tkinter import *
root = Tk()
root.title("My animation")
c = Canvas(root)
x = 20
y = 20 #Instead of using row and column, you simply use x and y co-ordinates
#We will use these co-ordinates to show where the text is in the starting
my_text = c.create_text(x,y,text = '-----')
c.pack()
# This is all you need to create this text on your screen!
root.mainloop()
The idea is that you put your canvas up on your window , and then place whatever you want on it.
There are a lot more attributes that you can add to make your text look even better. Here is an in-depth tutorial on it.
Now that we have made your text widget, It is now time to move it around. Let us move it to 90,20 From our initial position which is 20,20
Here is how we will do it. If we simply move to text object to 90,90, We won't see any animations, it will just directly have it there. So what we will do is first create it at 21,20. Then 22,20. And so on...
We do this really fast till we reach 90,20
This looks like we are moving the text
from tkinter import *
import time
root = Tk()
root.title("My animation")
c = Canvas(root)
x = 20
y = 20 #Instead of using row and column, you simply use x and y co-ordinates
#We will use these co-ordinates to show where the text is in the starting
my_text = c.create_text(x,y,text = 'weee')
c.pack()
def animation():
y = 0.1
x = 0
for _ in range(1000):
c.move(my_text,x,y)
root.update()
anlabel = Button(root,text = 'Animate!',command = animation).pack()
root.mainloop()
This is not only applicable to text, but everything (like other images)that is there on the canvas. The canvas also has Events which will let you use mouse-clicks and other keys on the computer too.
I have made some changes from the previous code, But it is executable and you can try it for yourself to see how it works. increasing the value in time.sleep() makes the animation slower, the lesser the value, the faster.
Are you sure you aren't trying to do something more like the below example? Animating the padding on one of your widgets is going to screw up the rest of your display.
from tkinter import *
import time
root = Tk()
lbl = Label(root, text='')
lbl.grid(row=0, column=0)
def animation(step=12):
step = 12 if step < 0 else step
lbl['text'] = ' ------ '[step:step+6]
root.after(200, lambda: animation(step-1))
Button(root, text='Animate', command=animation).grid(row=1, column=0, sticky='w')
root.mainloop()

Can't move object with grid

I've researched this issue, and found people with similar problem. However, the answers are not clear for me.
I'm trying to freely move my objects into X rows and columns. Right now, regardless of what value I put into column or row my object won't change position, it's always on the top-left corner.
According to other people's answers, empty rows and columns have zero size. How can I change that?
This is my current code:
from tkinter import *
class Application:
def __init__(self, master):
frame = Frame(master)
b = Button(text="This is a button")
b.grid(row=2, column=3)
root = Tk()
root.geometry('{}x{}'.format(500, 300))
app = Application(root)
root.mainloop()
Yes, empty rows and columns have zero size. So, without the help of any other options, your widget will be placed at the corner of the window. But with the help of options like padx, pady, sticky and functions like grid_columnconfigure() and grid_rowconfigure(), you can achieve what you want. As an example, look at this:
from tkinter import *
class Application:
def __init__(self, master):
frame = Frame(master)
b = Button(text="This is a button")
b.grid(row=0, column=0, pady=(20,0))
master.grid_columnconfigure(0, weight=1)
root = Tk()
root.geometry('{}x{}'.format(500, 300))
app = Application(root)
root.mainloop()

tkinter: simple scrollable text

Question
I'm trying to make a 'ttk Label' which a) is 20 pixels high by 300 pixels wide, b) is scrollable (in this case horizontally), and c) uses the simplest code possible within reason (except for the fact that the text and scrollbar are both within a frame*). I've found stackoverflow to be helpful in describing the processes I need to go through (put the label in a frame, put the frame in a canvas, put the scroll bar next to or underneath the canvas and 'bind' them together somehow), but despite looking at a fair few docs and stackoverflow questions, I can't figure out why my code isn't working properly. Please could someone a) update the code so that it satisfies the conditions above, and b) let me know if I've done anything unnecessary? Thanks
*the frame will be going in a project of mine, with text that is relevant
Current code
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
myframe_outer = ttk.Frame(root)
mycanvas = tk.Canvas(myframe_outer, height=20, width=300)
myframe_inner = ttk.Frame(mycanvas)
myscroll = ttk.Scrollbar(myframe_outer, orient='horizontal', command=mycanvas.xview)
mycanvas.configure(xscrollcommand=myscroll.set)
myframe_outer.grid()
mycanvas.grid(row=1, sticky='nesw')
myscroll.grid(row=2, sticky='ew')
mycanvas.create_window(0, 0, window=myframe_inner, anchor='nw')
ttk.Label(myframe_inner, text='test ' * 30).grid(sticky='w')
root.mainloop()
Edit:
Current result
Answer
Use a readonly 'entry' widget - it looks the same as a label, and doesn't need to be put in a canvas.
Code
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
mytext = tk.StringVar(value='test ' * 30)
myframe = ttk.Frame(root)
myentry = ttk.Entry(myframe, textvariable=mytext, state='readonly')
myscroll = ttk.Scrollbar(myframe, orient='horizontal', command=myentry.xview)
myentry.config(xscrollcommand=myscroll.set)
myframe.grid()
myentry.grid(row=1, sticky='ew')
myscroll.grid(row=2, sticky='ew')
root.mainloop()
Result

Python Tkinter button not appearing?

I'm new to tkinter and I have this code in python:
#import the tkinter module
from tkinter import *
import tkinter
calc_window = tkinter.Tk()
calc_window.title('Calculator Program')
button_1 = tkinter.Button(text = '1', width = '30', height = '20')
button_1 = '1'
calc_window.mainloop()
But when I run it, the button doesn't appear. Does anyone know why? Thank you!
Getting a widget to appear requires two steps: you must create the widget, and you must add it to a layout. That means you need to use one of the geometry managers pack, place or grid to position it somewhere in its container.
For example, here is one way to get your code to work:
button_1 = tkinter.Button(text = '1', width = '30', height = '20')
button_1.pack(side="top")
The choice of grid or pack is up to you. If you're laying things out in rows and columns, grid makes sense because you can specify rows and columns when you call grid. If you are aligning things left-to-right or top-to-bottom, pack is a little simpler and designed for such a purpose.
Note: place is rarely used because it is designed for precise control, which means you must manually calculate x and y coordinates, and widget widths and heights. It is tedious, and usually results in widgets that don't respond well to changes in the main window (such as when a user resizes). You also end up with code that is somewhat inflexible.
An important thing to know is that you can use both pack and grid together in the same program, but you cannot use both on different widgets that have the same parent.
from tkinter import *
import tkinter
calc_window = tkinter.Tk()
calc_window.title('Calculator Program')
frame = Frame(calc_window )
frame.pack()
button_1 = tkinter.Button(frame,text = '1', width = '30', height = '20')
button_1.pack(side=LEFT)
calc_window.mainloop()
try adding the button using pack(). i donno why u tried to assign button_1 = '1' in your code
a neat example:
from Tkinter import *
class App:
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.button = Button(
frame, text="QUIT", fg="red", command=frame.quit
)
self.button.pack(side=LEFT)
self.hi_there = Button(frame, text="Hello", command=self.say_hi)
self.hi_there.pack(side=LEFT)
def say_hi(self):
print "hi there, everyone!"
root = Tk()
app = App(root)
root.mainloop()
You're not packing the button_1. The code is:
from tkinter import *
root = Tk()
root.title('Calculator Program')
button_1 = Button(root, text='1', width='30', height='20')
button_1.pack()
root.mainloop()
It's simple!
Hope this helps!
from tkinter import *
calc_window = Tk()
calc_window.title('Calculator Program')
button_1 = Button(text = '1')
button_1.place(x=0,y=0,width = 30, height = 20)
calc_window.mainloop()

Categories