tkinter Notebook tabs, scrolling horizontal through tabs - python

I would like to have a fixed window size and then scroll through tabs like in this example, each tab is a new page with many entries. But if I add a tab the window size gets bigger and if I add the scrollbar from the example it isn't working because I am using grid instead of pack. Any ideas how I can fix this two problems?
My main.py:
#libraries
import tkinter as tk
from tkinter import ttk
from ScrollableNotebook import *
from XXXXXXXXXXXX import createUI0
from YYYYYYYYYYYY import createUI1
from ZZZZZZZZZZZZ import createUI2
from XYXYXYXYXYXY import createUI3
from XYZXYZXYZXYZ import createUI4
# class MainFrame that inherits from ttk.Frame
class MainFrame(ttk.Frame):
def __init__(self, container): #init method
super().__init__(container)
# noteboook
self.notebook = ttk.Notebook()
self.notebook.grid()
# Frames
self.Frame0 = createUI0(self.notebook)
self.Frame1 = createUI1(self.notebook)
self.Frame2 = createUI2(self.notebook)
self.Frame3 = createUI3(self.notebook)
self.Frame4 = createUI4(self.notebook)
self.notebook.add(self.Frame0, text='XXXXXXXXXXXX')
self.notebook.add(self.Frame1, text='YYYYYYYYYYYY')
self.notebook.add(self.Frame2, text='ZZZZZZZZZZZZ')
self.notebook.add(self.Frame3, text='XYXYXYXYXYXY')
self.notebook.add(self.Frame4, text='XYZXYZXYZXYZ')
# class App that inherits from tk.Tk
class App(tk.Tk):
def __init__(self): #method
super().__init__()
#configure the root window
self.title('PDF XYZ Creater')
self.geometry('670x650')
#self.resizable(0, 0)
if __name__ == "__main__":
app = App() # Create Class App
MainFrame(app)
app.mainloop()
One of my tabs in a new file (XXXXXXXXXXXX.py) without content:
#libraries
import tkinter as tk
from tkinter import ttk
class createUI0(ttk.Frame):
def __init__(self, container): #init method
super().__init__(container)

Related

How to change whole app's theme when used within Class, Tkinter, ttkThemes, ThemedTk Python

Summary:
I searched the internet about additional themes for tkinter. I found ttkthemes - ThemedTk option. However, my app is created within class. The difference between the example shown in the module website, the themedtk example is applied with root method. Here is the code:
import os
from tkinter import *
import tkinter as tk
from tkinter import ttk, filedialog
from PIL import ImageTk, Image
from ttkthemes import ThemedTk,THEMES
class App(tk.Tk):
def __init__(self):
super().__init__()
self.style = ThemedTk
self.title(dil_sec[0])
self.geometry("800x600")
self.my_notebook = ttk.Notebook(self)
self.my_notebook.pack(pady=15)
self.my_menu = Menu(self)
self.config(menu=self.my_menu)
rec = None
id_num = None
self.first_lane = Menu(self.my_menu)
self.my_menu.add_cascade(label=dil_sec[6], menu=self.first_lane)
self.first_lane.add_command(label=dil_sec[2], command=self.customer_list)
self.first_lane.add_command(label=dil_sec[1], command=lambda: self.customer_add(rec, id_num))
self.second_lane = Menu(self.my_menu)
self.my_menu.add_cascade(label=dil_sec[3], menu=self.second_lane)
self.third_lane = Menu(self.my_menu)
self.my_menu.add_cascade(label= dil_sec[65], menu=self.third_lane)
self.third_lane.add_command(label=THEMES[0],command=lambda: self.stil_changer(still=THEMES[0]))
self.third_lane.add_command(label=THEMES[1],command=lambda: self.stil_changer(still=THEMES[1]))
def stil_changer(self,still):
print(still)
self.style.set_theme(self,theme_name=still)
if __name__ == "__main__":
app = App()
app.mainloop()
When I run the application and the click the style and choose a style. I receive this error:
AttributeError: '_tkinter.tkapp' object has no attribute '_toplevel'
It took so much time of me to solve it. Thanks in advance.
You forgot () in line
self.style = ThemedTk()
and later you have to remove self in
self.style.set_theme(theme_name=still)
and now it runs without error but still it doesn't change theme.
Maybe it needs to use widgets from ttk.
EDIT:
You have to use ThemedTk in place of tk.Tk. And use directly self.set_theme()
And of course you need some widgets from ttk.
import tkinter as tk
import tkinter.ttk as ttk
from ttkthemes import ThemedTk
class App(ThemedTk):
def __init__(self):
super().__init__()
self.geometry("800x600")
self.my_notebook = ttk.Notebook(self)
self.my_notebook.pack(pady=15, fill='both', expand=True)
self.frame = ttk.Frame(self.my_notebook)
self.my_notebook.add(self.frame, text='Buttons')
for number in range(10):
b = ttk.Button(self.frame, text=str(number))
b.pack()
self.my_menu = tk.Menu(self)
self.config(menu=self.my_menu)
self.first_lane = tk.Menu(self.my_menu)
self.first_lane.add_command(label='a')
self.first_lane.add_command(label='b')
self.my_menu.add_cascade(label='Menu1', menu=self.first_lane)
self.second_lane = tk.Menu(self.my_menu)
self.my_menu.add_cascade(label='Menu2', menu=self.second_lane)
self.third_lane = tk.Menu(self.my_menu)
self.my_menu.add_cascade(label='Style', menu=self.third_lane)
for item in sorted(self.get_themes()):
self.third_lane.add_command(label=item, command=lambda name=item: self.changer_theme(name))
def changer_theme(self, name):
print('theme:', name)
self.set_theme(name)
if __name__ == "__main__":
app = App()
app.mainloop()
Or you can use Tk with ThemedStyle (instead of ThemedTk)
and then you can set self.style = ThemedStyle()
but you have to use self.style.theme_use(name) instead of self.set_theme(name)
And it needs self.style.get_themes() instead of self.get_themes().
import tkinter as tk
import tkinter.ttk as ttk
from ttkthemes import ThemedStyle
class App(tk.Tk):
def __init__(self):
super().__init__()
self.geometry("800x600")
self.style = ThemedStyle() # with Tk and ThemedStyle
self.my_notebook = ttk.Notebook(self)
self.my_notebook.pack(pady=15, fill='both', expand=True)
self.frame = ttk.Frame(self.my_notebook)
self.my_notebook.add(self.frame, text='Buttons')
for number in range(10):
b = ttk.Button(self.frame, text=str(number))
b.pack()
self.my_menu = tk.Menu(self)
self.config(menu=self.my_menu)
self.first_lane = tk.Menu(self.my_menu)
self.first_lane.add_command(label='a')
self.first_lane.add_command(label='b')
self.my_menu.add_cascade(label='Menu1', menu=self.first_lane)
self.second_lane = tk.Menu(self.my_menu)
self.my_menu.add_cascade(label='Menu2', menu=self.second_lane)
self.third_lane = tk.Menu(self.my_menu)
self.my_menu.add_cascade(label='Style', menu=self.third_lane)
#for item in sorted(self.get_themes()): # with ThemedTk
for item in sorted(self.style.get_themes()): # with Tk and ThemedStyle
self.third_lane.add_command(label=item, command=lambda name=item: self.changer_theme(name))
def changer_theme(self, name):
print('theme:', name)
#self.set_theme(name) # with ThemedTk
self.style.theme_use(name) # with Tk and ThemedStyle
if __name__ == "__main__":
app = App()
app.mainloop()
I found screenshots for all themes: List of ttk Themes
OLD ANSWER
I have only working example with ttk.Buttons
import tkinter as tk
from tkinter import ttk
import ttkthemes
root = tk.Tk()
root.style = ttkthemes.ThemedStyle()
for i, name in enumerate(sorted(root.style.theme_names())):
b = ttk.Button(root, text=name, command=lambda name=name:root.style.theme_use(name))
b.pack(fill='x')
root.mainloop()
Default:
Blue:
Kroc:
Radiance or Ubuntu:
Winxpblue:
Source keep on GitHub: furas / python-examples / tkinter / themes-change-ttkthemes / buttons

tkinter simpledialog giving focus to parent of window it was called from when submitted

I am attempting to open window2 from window1 and asking for a string in between.
On a successful (or unsuccessful) input, window1, seems to take focus back from window2. Even if focus_set is called on window2 after the dialogue is closed.
window2 takes focus on creation if he askstring is omitted
import os
import tkinter as tk
from tkinter import ttk
from tkinter import simpledialog
class window2:
def __init__(self,root):
self.root = root
self.root.withdraw()
simpledialog.askstring("askstring","askstring")
self.root.deiconify()
class window1:
def __init__(self,root):
self.root = root
self.button = tk.Button(self.root,text = "Test", command = self.newwindow)
self.button.grid()
def newwindow(self):
newin = window2(tk.Toplevel(self.root))
if __name__ == "__main__":
toproot = tk.Tk()
win = window1(toproot)
win.root.mainloop()
I'm wondering if it is doing this because of the way I've setup the classes or simply if its something simpledialogue does which triggers this effect.
After noticing my simplified code was missing the withdraw() and the deiconify() I figured I could bring the window back to front once the window was visible again.
import tkinter as tk
from tkinter import ttk
from tkinter import simpledialog
class window2:
def __init__(self,root:tk.Tk):
self.root = root
self.root.withdraw()
simpledialog.askstring("this","sucks",parent = self.root)
self.root.deiconify()
self.root.wait_visibility()
self.root.lift()
class window1:
def __init__(self,root):
self.root = root
self.button = tk.Button(self.root,text = "Test", command = self.newwindow)
self.button.grid()
def newwindow(self):
newin = window2(tk.Toplevel(self.root))
if __name__ == "__main__":
toproot = tk.Tk()
win = window1(toproot)
win.root.mainloop()
Not exactly elegant, but it works.

python: My Tkinter code sometimes does not change font family and size

I have this python code for make GUI through tkinter.
I'm trying to activate a new form(form2) on the top when I press the button on Form 1.
I developed based on the inheritance of tkinter class.
My code usually works well, but I found one problem.
If I run Form 2 through the button event on Form 1, the font on Form 2 is not changed.
Errors do not occur at all.
but, if I run it right from the main as below, the font will be changed successfully.
if __name__ == '__main__':
form2 = Form2()
form2.mainloop() # execute GUI
This is my Code:
from tkinter.ttk import *
import tkinter as tk
from tkinter import messagebox
from tkinter import *
import tkinter.font as tkFont
class Form2(tk.Tk):
def __init__(self):
super().__init__() # Inheritance from tkinter class
self.title("Form2")
self.geometry("350x600")
self.resizable(0, 0)
self.label = tk.Label(self, text='form2',
font=tkFont.Font(family="Roboto", size=18))
self.label.pack()
class Form1(tk.Tk):
def __init__(self):
super().__init__() # Inheritance from tkinter class
self.title("Form1")
self.geometry("350x600")
self.resizable(0, 0)
# Get Language Data
self.label = tk.Label(self, text='form1',
font=tkFont.Font(family="Roboto", size=18))
self.label.pack()
# preferences button design
self.button: object = tk.Button(self, overrelief="solid", width=10, height=2,
repeatdelay=1000, repeatinterval=100,
text="Preferences",
font=tkFont.Font(family="Roboto", size=9),
command=lambda: self.button_clicked())
self.button.pack()
#staticmethod
def button_clicked():
form2 = Form2()
form2.mainloop()
if __name__ == '__main__':
form1 = Form1()
form1.mainloop()
Please give me some advice.

Import pandas table into tkinter project

I have used tkinter and its treeview widget thus far in my project to import and view some data from a csv file. However Im finding its functions limited as to what Im trying to achieve.
I have read in other SO questions that a Pandas data-frame can be imported to Tkinter project and display in the tkinter GUI. I have found some code online # https://gist.github.com/gugat/7cf57eb628f3bb0a3d54b3f8d0023b63 but I cant work out how to migrate this into my existing tkinter code.
import tkinter as tk
from tkinter import *
import tkinter.ttk as tkrttk
from PIL import Image, ImageFont, ImageTk
import csv
from tkinter import filedialog
import pandas as pd
from pandastable import Table, TableModel
root = tk.Tk()
root.geometry("2000x1000")
filepath = (r"C:/Users\James\Desktop\test_data.csv")
root.title('Workshop Manager')
style = tkrttk.Style()
style.configure("Treeview.Heading", foreground='Red', font=('Helvetica', 10))
df = pd.read_csv(filepath)
pt = Table(parent)
class TestApp(Frame):
"""Basic test frame for the table"""
def __init__(self, parent=root):
self.parent = parent
Frame.__init__(self)
self.main = self.master
self.main.geometry('600x400+200+100')
self.main.title('Table app')
f = Frame(self.main)
f.pack(fill=BOTH,expand=1)
df = TableModel.getSampleData()
self.table = pt = Table(f, dataframe=df,
showtoolbar=True, showstatusbar=True)
pt.show()
return
app = TestApp()
root.mainloop()
I get an error NameError name parent is not defined im assuming this pt = Table(parent) is my issue. I have tried pt = Table(root) as I thought this would place it on the tkinter root window. But this didnt work.
Part of your code is from the example used in the document of pandastable, but it is not a good example.
If you just want to show your CSV file using pandastable, below is a simple example:
import tkinter as tk
from pandastable import Table, TableModel
filepath = 'C:/Users/James/Desktop/test_data.csv'
root = tk.Tk()
root.geometry('1600x900+10+10')
root.title('Workshop Manager')
class TestApp(tk.Frame):
def __init__(self, parent, filepath):
super().__init__(parent)
self.table = Table(self, showtoolbar=True, showstatusbar=True)
self.table.importCSV(filepath)
self.table.show()
app = TestApp(root, filepath)
app.pack(fill=tk.BOTH, expand=1)
root.mainloop()

Want to display two string value in two different tkinter label

I make code for displaying two serial read string in two different label using tkinter GUI..
My code is running and window also popped up but values are not displaying..
Help me to solve this issue..
Here is my code
import serial
import tkinter
from tkinter import *
import time
class SerialViewer(Tk):
def _init_(self):
self.win = Tk()
self.ser=serial.Serial('/dev/ttyS0',9600)
def makewindow (self):
frame1 =Frame(self.win)
frame1.pack()
self.v=StringVar()
self.v.set=('default')
label=Label(frame1,textvariable=self.v,relief=RAISED)
label.pack(side=LEFT)
frame2 = Frame(self.win)
frame2.pack()
self.d=StringVar()
self.d.set=('default')
label=Label(frame2,textvariable=self.d,relief=RAISED)
label.pack(side=RIGHT)
def update(self):
print(self.ser.write("*01T%"))
data=self.ser.readline(self.ser.inWaiting())
self.v.set(data)
time.sleep(2)
print(self.ser.write('*00T%'))
data1=self.ser.readline(self.ser.inWaiting())
self.d.set(data1)
self.win.after(100,self.update)
def run (self):
self.makewindow()
self.update()
self.win.mainloop()
app=SerialViewer()
app.mainloop()
As said in comment that the method _init_ needs to be changed to __init__ and the recursion error is coming because the __init__ method of parent class wasn't called. Please add that call like below:
class SerialViewer(Tk):
def _init_(self):
super(SerialViewer, self).__init__() # Call the initializer method of parent class
self.win = Tk()
self.ser=serial.Serial('/dev/ttyS0',9600)
Hope this helps!!

Categories