TKInter Entry is not exapanding along with Main Window - python

I am using the following code, I am having 2 issues,
1. When I try to maximize the window, the Entry widget is not aligned/maximized along with main window and see a gap between scrolled text and Entry widget.
2. Second I am trying to set my cursor in Entry widget when I try to open or whenever my app is active but it's not working for some reason. Any Idea what am I making mistakes?
import tkinter as tk
from tkinter import scrolledtext
class Main:
def __init__(self, master):
self.master = master
master.title("Main")
width = master.winfo_screenwidth()
height = master.winfo_screenheight()
master.minsize(width=1066, height=766)
master.maxsize(width=width, height=height)
self.frame = tk.Frame(self.master)
text_area = scrolledtext.ScrolledText(self.master,width=75,height=35)
text_area.pack(side="top",fill='both',expand=True)
text_entry = tk.Entry(self.master,width=65)
text_entry.pack(side="top",fill=X, expand=True,ipady=3, ipadx=3)
text_entry.configure(foreground="blue",font=('Arial', 10, 'bold', 'italic'))
text_entry.focus()
self.frame.pack()
def initial(self):
print ("initializing")
def main():
root = tk.Tk()
app = Main(root)
root.mainloop()
if __name__ == '__main__':
main()

I can address the issue of your entry field not expanding properly.
That is because you have fill=X and this is not a valid input for fill. Instead use fill="x". I believe your 2nd issue with the entry field having a large gap is because you have set expand = True instead change that to expand = False.
That said I prefer to use the grid() geometry manager instead. Take a look at my below example of how to do this with grid and weights.
When using the grid() manager you can tell each widget exactly where you want it along a grid. The use of weights is for telling a row or column how much if any it should expand with the window. This combined with sticky="nsew" will help us control stuff expands within the window.
import tkinter as tk
from tkinter import scrolledtext
class Main(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.title("Main")
width = self.winfo_screenwidth()
height = self.winfo_screenheight()
self.minsize(width=1066, height=766)
self.maxsize(width=width, height=height)
self.rowconfigure(0, weight=1)
self.rowconfigure(1, weight=0)
self.columnconfigure(0, weight=1)
text_area = scrolledtext.ScrolledText(self,width=75,height=35)
text_area.grid(row=0, column=0, ipady=3, ipadx=3, sticky="nsew")
text_entry = tk.Entry(self,width=65)
text_entry.grid(row=1, column=0, ipady=3, ipadx=3, sticky="ew")
text_entry.configure(foreground="blue",font=('Arial', 10, 'bold', 'italic'))
text_entry.focus()
def initial(self):
print ("initializing")
if __name__ == '__main__':
root = Main()
root.mainloop()
Update:
To clarify on your issue with fill and expand I have updated your code with the correction so you can see it working.
import tkinter as tk
from tkinter import scrolledtext
class Main:
def __init__(self, master):
self.master = master
master.title("Main")
width = master.winfo_screenwidth()
height = master.winfo_screenheight()
master.minsize(width=1066, height=766)
master.maxsize(width=width, height=height)
self.frame = tk.Frame(self.master)
text_area = scrolledtext.ScrolledText(self.master,width=75,height=35)
text_area.pack(side="top",fill='both',expand=True)
text_entry = tk.Entry(self.master,width=65)
text_entry.pack(side="top",fill="x", expand=False, ipady=3, ipadx=3)
text_entry.configure(foreground="blue",font=('Arial', 10, 'bold', 'italic'))
text_entry.focus()
self.frame.pack()
def initial(self):
print ("initializing")
def main():
root = tk.Tk()
app = Main(root)
root.mainloop()
if __name__ == '__main__':
main()

Related

How to create a sidebar with buttons to hide and show frames in Tkinter

I'm trying to create a basic application which has a sidebar that contains menu buttons. When each button is pressed, it changes the contents of the main content area to display the relevant content. I have created the layout, shown below. For reference, I have also added a wireframe of how I want the GUI to look.
The problem is that I cannot get the buttons to hide/unhide the relevant frames. How would this be done? And a further question, how would I embed a matplotlib chart into one of these frames? More specifically, when I press the 'Markets' button, the program would display a matplotlib chart of the Facebook stock, using an API. Any help would be appreciated.
import tkinter as tk
from tkinter import *
from tkinter import ttk
from tkinter.ttk import *
# Define the function for raising a frame ontop of another, in order for the
# respective frame to be displayed in the mainarea
def raise_frame(frame):
frame.tkraise()
# Initialise the tkinter root window, name it, and set its size
root = Tk()
root.geometry('500x500')
root.title('Stock Trading Simulator')
# Create the tkinter frame for the sidebar, and place it in the root window
sidebar = tk.Frame(root, width=200, bg='white', height=500, relief='raised', borderwidth=2)
sidebar.pack(expand=False, fill='both', side='left', anchor='nw')
# Create the tkinter frame for the main content area
mainarea = tk.LabelFrame(root, bg='#CCC', width=500, height=500)
mainarea.pack(expand=True, fill='both', side='right')
# Create the tkinter frame for the market
marketFrame = tk.Frame(mainarea, relief='sunken', bg='Red')
# Create the tkinter frame for the portfolio
portfolioFrame = Frame(mainarea, relief='sunken')
# Create the tkinter frame for the portfolio pending orders
pendingOrdersFrame = Frame(mainarea, relief='sunken')
# Create the tkinter frame for the portfolio trade history
tradeHistoryFrame = Frame(mainarea, relief='sunken')
for frame in (marketFrame, portfolioFrame, pendingOrdersFrame, tradeHistoryFrame):
frame.grid(row=0, column=0, sticky='news')
# Create button widgets for sidebar
btnMarket = Button(sidebar, text = 'Markets',
command=lambda:raise_frame(marketFrame)).grid(row = 0, column = 0,)
btnPortfolio = Button(sidebar, text = 'Portfolio',)
btnPortfolioSummary = Button(sidebar, text = 'Summary',)
btnPortfolioPendingOrders = Button(sidebar, text = 'Pending Orders',)
btnPortfolioTradeHistory = Button(sidebar, text = 'Trade History',)
# Map buttons to the tkinter grid to display them in the sidebar frame
btnPortfolio.grid(row = 2, column = 0)
btnPortfolioSummary.grid(row = 3, column = 0, padx=(15,0))
btnPortfolioPendingOrders.grid(row = 4, column = 0, padx=(15,0))
btnPortfolioTradeHistory.grid(row = 5, column = 0, padx=(15,0))
root.mainloop()
See the example, to make other frames just follow the model : frm_ctt_(...).py
Note: I suggest you install and use ttkbootstrap
python -m pip install git+https://github.com/israel-dryer/ttkbootstrap
main.py
from tkinter import *
#from tkinter import ttk
from ttkbootstrap import ttk
from frm_ctt_0 import *
#python -m pip install git+https://github.com/israel-dryer/ttkbootstrap
#pip3 install git+https://github.com/israel-dryer/ttkbootstrap
#https://ttkbootstrap.readthedocs.io/en/latest/gettingstarted/installation/
#class Functions(Tk):
class Functions(ttk.Window):
def unload_frame_content(self):
#self.panedwindow_left.remove(self.frame_content)
self.frame_content.pack_forget()
return
def load_content_0(self, event=None):
self.unload_frame_content()
self.frame_right0()
return
def load_content_1(self, event=None):
self.unload_frame_content()
self.frame_right1()
return
class MainFrame(Functions):
def __init__(self):
#Tk.__init__(self)
ttk.Window.__init__(self, themename='pulse')
self.geometry('500x300')
self.title('Tkinter')
self.set_frame_left()
self.frame_right0()
return
def set_frame_left(self):
self.frame_left = ttk.Frame(self)
self.frame_left.pack(side=LEFT, fill=Y)
self.frame_ctt_left = ttk.Frame(self.frame_left, bootstyle='info')
self.frame_ctt_left.pack(fill=BOTH, expand=1, ipadx=10)
self.btn0 = ttk.Button(self.frame_ctt_left, text='One', command=self.load_content_0)
self.btn0.pack(pady=2)
self.btn1 = ttk.Button(self.frame_ctt_left, text='Two', command=self.load_content_1)
self.btn1.pack(pady=2)
return
def frame_right0(self):
self.frame_content = ttk.Frame(self)
self.frame_content.pack(fill=BOTH, expand=1)
#self.panedwindow_left.add(self.frame_content)
data= {'var_text': 'Hellow World!'}
self.ctt = Content0(self.frame_content, data=data)
self.ctt.pack(fill=BOTH, expand=1)
return
def frame_right1(self):
self.frame_content = ttk.Frame(self)
self.frame_content.pack(fill=BOTH, expand=1)
#self.panedwindow_left.add(self.frame_content)
ttk.Label(self.frame_content, text='Content Two').pack()
return
if __name__== '__main__':
app = MainFrame()
app.mainloop()
frm_ctt_0.py
from tkinter import *
import ttkbootstrap as ttk
class Func(ttk.Frame):
def test(self):
print('hi')
class Content0(Func):
def __init__(self, parent, *args, **kwargs):
self.data = kwargs.pop('data', None)
ttk.Frame.__init__(self, parent, *args, **kwargs)
self.set_widgets()
return
def set_widgets(self):
self.frm_r = ttk.Frame(self)
self.frm_r.place(relx=0, rely=0, relwidth=1, relheight=1)
self.frm_r_top = ttk.Frame(self.frm_r)
self.frm_r_top.pack(side=TOP)
ttk.Label(self.frm_r_top, text=self.data['var_text']).pack()
self.btn = ttk.Button(self.frm_r_top, text='Click', command=self.test)
self.btn.pack()

How can I place a label of top of this frame? Tkinter

I am trying to place a label on top of a Frame, which is inside a 'Notebook' tab.
But when I run this code, the label always ends up in the center of the frame.
from tkinter import *
from tkinter import ttk
class Window:
def __init__(self,master):
self.master = master
master.title("Title")
master.resizable(1,1)
master.geometry('500x400')
self.load_UI()
def load_UI(self):
self.tabOptions = ttk.Notebook(self.master )
self.tab1 = Frame(self.tabOptions, padx=130, pady=80, bg='white')
self.tabOptions.add(self.tab1, text="Add Files")
self.tabOptions_AddFile()
self.tabOptions.pack()
def tabOptions_AddFile(self):
self.label = Label(self.tab1, text="Why is this in the center of the frame?")
self.label.grid(row=0, column=0)
root = Tk()
app = Window(root)
root.mainloop()
I tried to place the label using: pack(), grid(), place(). I also tried to place the label before adding the frame to the Notebook but it still looks the same :(
I am using python 3 btw.
This is because your Frame is padded in the line self.tab1 = Frame(self.tabOptions, padx=130, pady=80, bg='white'). Your Frame is here:
Just remove padx=130, pady=80 and all works. But to keep the size of tabOptions, replace
self.tabOptions.pack()
by
self.tabOptions.pack(fill=BOTH, expand=True)

Pararell instance of tkinter application window python

I want to create some simple tkinter python app (like StickyNotes on Windows), i have create the class mainApplication and i do not know how to by just simply triggering the button create another instance of this class which will be displayed pararell to other window (or even multiple windows). I know how to assigned function to pushButton, and other simple stuff but the problem is with this pararell window displaying. Thanks in advance for help.
class mainApplication(Frame):
_ids = count(0)
def __init__(self, parent):
""" """
self.id = next(self._ids)
Frame.__init__(self, parent)
self.parent = parent
self.parent.minsize(width=200,height=100)
self.parent.geometry(('%dx%d+%d+%d' % (200, 100, 1700, 0+self.id*100)))
self.initUI()
def initUI(self):
""" """
self.parent.title("a2l")
self.pack(fill=BOTH, expand=True)
style = Style()
style.configure("TFrame", background="#333")
frame1 = Frame(self, style="TFrame")
frame1.pack(fill=X)
self.lbl0 = Label(frame1, text="api", width=7, background="#333", foreground = "red")
self.lbl0.pack(side=TOP, padx=5, pady=5)
self.closeButton = Button(self, text="new", command = self.createNewInstance)
self.closeButton.pack(side=RIGHT, padx=5, pady=5)
#=======================================================================
# self.generateButton = Button(self, text="GENERATE", command = self.)
# self.generateButton.pack(side=RIGHT, padx=5, pady=5)
#=======================================================================
def createNewInstance(self):
y = mainApplication()
return y
if __name__ == "__main__":
root = Tk()
x = mainApplication(root).pack(side="top", expand=False)
Tk().mainloop()
You shouldn't create more than one Tk() window in one application with tkinter. Instead tkinter provides a widget called Toplevel which can be useful for this kind of thing.
It creates another window which can exist along side the Tk() window and alongside other Toplevel widgets.
You could use this to create a series of persistent windows with whatever text or widgets you wanted on them at any kind of trigger including a Button.
See my example below for a demonstration:
from tkinter import *
class App:
def __init__(self, root):
self.root = root
self.top = [] #list to contain the Toplevel widgets
self.entry = Entry(self.root)
self.button = Button(self.root, text="Create window", command=self.command)
self.entry.pack()
self.button.pack()
def command(self): #called when button is pressed
self.top.append(Toplevel(self.root)) #adds new Toplevel to the list
Label(self.top[len(self.top)-1], text=self.entry.get()).pack() #Adds label equal to the entry widget to the new toplevel
root = Tk()
App(root)
root.mainloop()

Scrollable Frame Python Tkinter

I am working n a project that has a scroll able frame. It lets me add widgets to the frame but I can not get the frame to scroll and show the rest of the widgets. I have compared my code to other scroll able frames online and I could not notice the difference. Any one see the solution.
Code:
from Tkinter import *
import ttk
import os
class GUI(Frame):
def __init__(self, parent):
Frame.__init__(self,parent)
self.pack(fill=BOTH, expand=YES)
def gameView(self):
self.mainFrame = Frame(self)
self.mainFrame.pack(side=TOP)
self.scroller = ttk.Scrollbar(self.mainFrame, orient=VERTICAL)
self.scroller.pack(side=RIGHT, fill=Y)
self.canvas = Canvas(self.mainFrame, bd=0)
self.canvas.pack(fill=BOTH, side=LEFT)
self.viewArea = Frame(self.canvas, bg="Pink")
self.viewArea.pack(side=TOP, fill=BOTH)
self.canvas.config(yscrollcommand=self.scroller.set)
self.scroller.config(command=self.canvas.yview)
self.canvas.create_window((0,0), window=self.viewArea, anchor=NW, width=783, height=650)
self.viewArea.bind("<Configure>", self.scrollCom)
self.itemHolder = Frame(self.viewArea, bg="Pink")
self.itemHolder.pack(side=TOP)
self.gameGather()
def scrollCom(self, event):
self.canvas.config(scrollregion=self.canvas.bbox("all"), width=783, height=650)
def gameGather(self):
for i in range(0, 50):
label = Label(self.viewArea, text="Pie")
label.pack(side=TOP)
root = Tk()
root.title("School Vortex 2.0")
root.geometry("800x650")
root.resizable(0,0)
gui = GUI(root)
gui.gameView()
root.mainloop()
When you put the window on the canvas you are explicitly giving it a height and a width. Because of that, the actual width and height of the frame is completely ignored. Because the frame is almost exactly the height of the canvas, there's nothing to scroll.
If you remove the width and height options from the call to create_window your frame will be scrollable.

The horizontal scrollbar didn't work in Tkinter

I want to create a GUI program base on tkinter. One of the widgets is Text. I want to add a horizontal scrollbar in it, but it didn't work.
Where did I make a mistake?
from Tkinter import *
import tkFont
class DpWin(object):
def run(self):
root=Tk()
root.geometry('768x612')
title='dp'
root.title(title)
xscrollbar = Scrollbar(root, orient=HORIZONTAL)
xscrollbar.pack(side=BOTTOM, fill=X)
yscrollbar = Scrollbar(root)
yscrollbar.pack(side=RIGHT, fill=Y)
text = Text(root,xscrollcommand=xscrollbar.set,yscrollcommand=yscrollbar.set)
text.pack()
xscrollbar.config(command=text.xview)
yscrollbar.config(command=text.yview)
text.insert(END,'a'*999)
mainloop()
def start(self):
self.b_start.config(state=DISABLED)
self.b_stop.config(state=ACTIVE)
def stop(self):
self.b_stop.config(state=DISABLED)
self.b_start.config(state=ACTIVE)
if __name__=='__main__':
win=DpWin()
win.run()
I've modified your code according to here. There are 2 main differences.
I made it so the textbox doesn't wrap. If you wrap text, there is nothing for the horizontal scrollbar to scroll to.
I used the grid geometry manager on a frame to keep the scrollbars and text widgets together. The advantage to using .grid is that you actually get scrollbars which are the correct width/height (something you can't achieve with pack).
...
from Tkinter import *
import tkFont
class DpWin(object):
def run(self):
root=Tk()
root.geometry('768x612')
title='dp'
root.title(title)
f = Frame(root)
f.pack()
xscrollbar = Scrollbar(f, orient=HORIZONTAL)
xscrollbar.grid(row=1, column=0, sticky=N+S+E+W)
yscrollbar = Scrollbar(f)
yscrollbar.grid(row=0, column=1, sticky=N+S+E+W)
text = Text(f, wrap=NONE,
xscrollcommand=xscrollbar.set,
yscrollcommand=yscrollbar.set)
text.grid(row=0, column=0)
xscrollbar.config(command=text.xview)
yscrollbar.config(command=text.yview)
text.insert(END, 'a'*999)
mainloop()
def start(self):
self.b_start.config(state=DISABLED)
self.b_stop.config(state=ACTIVE)
def stop(self):
self.b_stop.config(state=DISABLED)
self.b_start.config(state=ACTIVE)
if __name__=='__main__':
win=DpWin()
win.run()
There is one comment regarding making both x and y scrollbars work within the pack framework. Here is a minimal example:
import tkinter as tk
from tkinter import X, Y, BOTTOM, RIGHT, LEFT, Y, HORIZONTAL
class TextExample(tk.Frame):
def __init__(self, master=None):
super().__init__()
sy = tk.Scrollbar(self)
sx = tk.Scrollbar(self, orient=HORIZONTAL)
editor = tk.Text(self, height=500, width=300, wrap='none')
sx.pack(side=BOTTOM, fill=X)
sy.pack(side=RIGHT, fill=Y)
editor.pack(side=LEFT, fill=Y)
sy.config(command=editor.yview)
sx.config(command=editor.xview)
self.pack()
def main():
root = tk.Tk()
root.geometry("800x500+0+0")
app = TextExample(master=root)
root.mainloop()
if __name__ == '__main__':
main()

Categories

Resources