Only open 1 window when button clicked multiple times - python

I am trying to create a basic invoicing system. However i have encountered an issue as you can tell from my the title, is there any way to achieve this. I have been using a counter to determine if the window should open or not but i dont think it is right.
from tkinter import *
window = Tk()
count = 0
def openNewWindow():
global count
count = count + 1
if count == 1:
newWindow = Toplevel(window)
newWindow.title("New Window")
newWindow.geometry("800x800")
newWindow.title('test ©') # Frame title
newWindow.iconbitmap('icon4.ico') # Frame logo
if 'normal' == newWindow.state():
count = 2
else:
count = 0
width = window.winfo_screenwidth()
height = window.winfo_screenheight()
window.geometry("%dx%d" % (width, height))
bg = PhotoImage(file="bsor.gif")
label_image = Label(window, image=bg)
label_image.place(x=0, y=0)
title_label = Label(window, text="Job Management System", bg="black", fg="white")
title_label.config(font=("Courier", 70))
title_label.place(x=65, y=3)
customer_database_button = Button(window, text="Customer Database", width="23", height="2",
font=('Courier', 13, 'bold'), command=openNewWindow)
customer_database_button.grid(row=3, column=0, pady=185, padx=(110, 0))
employee_database_button = Button(window, text="Employee Database", width="23", height="2",
font=('Courier', 13, 'bold'))
employee_database_button.grid(row=3, column=1, pady=10, padx=(50, 0))
job_category_button = Button(window, text="Job Category (Pricing)", width="23", height="2",
font=('Courier', 13, 'bold'))
job_category_button.grid(row=3, column=2, pady=10, padx=(50, 0))
quote_sale_button = Button(window, text="Quotes / Sales", width="23", height="2", font=
('Courier', 13, 'bold'))
quote_sale_button.grid(row=3, column=3, pady=10, padx=(50, 0))
cash_management_button = Button(window, text="Cash Management", width="23", height="2", font=
('Courier', 13, 'bold'))
cash_management_button.grid(row=3, column=4, pady=10, padx=(50, 0))
analysis_mode_button = Button(window, text="Analysis Mode", width="23", height="2", font=
('Courier', 13, 'bold'))
analysis_mode_button.grid(row=3, column=5, pady=10, padx=(50, 0))
window.title('test') # Frame title
window.iconbitmap('icon4.ico') # Frame logo
window.mainloop()

Here is a minimal example on how to do it (works best with only one additional allowed window):
from tkinter import Tk, Toplevel, Button
def open_window(button):
button.config(state='disabled')
top = Toplevel(root)
top.transient(root)
top.focus_set()
top.bind('<Destroy>', lambda _: btn.config(state='normal'))
root = Tk()
root.geometry('300x200')
btn = Button(root, text='Open new window!', command=lambda: open_window(btn))
btn.pack(expand=True)
root.mainloop()
Just have the function disable the button and bind a <Destroy> event to the Toplevel to set the button's state back to normal. (Also you may want to use .transient on the Toplevel to make it appear above its master so that people don't forget that they haven't closed the window and wonder why they can't press the button (it will also not display additional icon in the taskbar))
Also:
I strongly advise against using wildcard (*) when importing something, You should either import what You need, e.g. from module import Class1, func_1, var_2 and so on or import the whole module: import module then You can also use an alias: import module as md or sth like that, the point is that don't import everything unless You actually know what You are doing; name clashes are the issue.
I strongly suggest following PEP 8 - Style Guide for Python Code. Function and variable names should be in snake_case, class names in CapitalCase. Don't have space around = if it is used as a part of keyword argument (func(arg='value')) but have space around = if it is used for assigning a value (variable = 'some value'). Have space around operators (+-/ etc.: value = x + y(except here value += x + y)). Have two blank lines around function and class declarations.

Related

Tkinter lable config dynamically

i want dynamic lable.config is it possible ? because the result doesn't fix with the screen size and the rest of the text are cut off and cannot see. Here is the code. i know my code is not effective but i am a beginner and i have no idea and dont know anything about GUI in python
def link_GUI(graph):
def btn_click():
data1 = str(txtDataEntry.get()) # get data from test box
data2 = str(txtDataEntry2.get())
r_edge = link(graph, data1, data2)
lblResult.config(text="" + data1 + " and " + data2 + " are linked")
lblResult2.config(text="" + str(r_edge))
root = Tk()
root.title("SSM Application")
root.geometry("1500x600")
lblTitle = Label(text=" Link a station to another station", font=('arial', 20, 'bold'), fg='Black')
lblTitle.pack()
lblTitle = Label(text=" *Close the box to choose another option* ", font=('arial', 10, 'bold'), fg='Black')
lblTitle.pack()
frame1 = Frame()
lblDataentry = Label(frame1, text="Enter first station name:", pady=1, fg='black') # 1111111111111111
lblDataentry.grid(row=0, column=0)
txtDataEntry = Entry(frame1) # 111111111111111
txtDataEntry.grid(row=0, column=1)
lblDataentry = Label(frame1, text="Enter second station name:", pady=1, fg='black') # 2222222222222
lblDataentry.grid(row=1, column=0)
txtDataEntry2 = Entry(frame1) # 222222222222222
txtDataEntry2.grid(row=1, column=1)
btnSubmit = Button(frame1, text="Link", bg='grey', fg='black', command=btn_click)
btnSubmit.grid(row=2, column=1)
frame1.pack() # add frame to gui
lblResult = Label(font=('arial', 18, 'bold'), fg='darkblue')
lblResult.pack()
lblResult2 = Label(font=('arial', 18, 'bold'), fg='darkblue')
lblResult2.pack()
root.mainloop()
the original output result1: https://i.stack.imgur.com/ErzL6.png
here is the result after i tried with wrap length but it also cannot help too is there any other ways to do?
https://i.stack.imgur.com/J3eBd.png
change root.geometry("1500x600") to root.minsize(1500, 600) in order to let the root window to expand.
change lblResult2.pack() to lblResult2.pack(fill="both", expand=1), so that lblResult2 will fill the root window width and adjust the root window height in order to show all its content.
change lblResult2.config(text=""+str(r_edge)) to lblResult2.config(text=str(r_edget), wraplength=lblResult2.winfo_width(), justify='left') in order to wrap its content to fit its width.
Edit: Another solution is to use Text widget instead of Label:
change the following lines
lblResult2 = Label(font=('arial', 18, 'bold'), fg='darkblue')
lblResult2.pack()
to
txtResult2 = Text(font=('arial', 18, 'bold'), fg='darkblue')
txtResult2.pack(fill='both', expand=1)
change the following line in btn_click():
lblResult2.config(text=""+str(r_edge))
to
txtResult2.delete(1.0, 'end')
txtResult2.insert('end', str(r_edge))

How to checkbox to enable a button in Tkinter

self.label_5 = tk.Checkbutton(self.master, text="I agree to the", bg='white', width=14,font=("Arial", 8), command= activator)
self.label_5.place(x=112, y=410)
self.button_2 = tk.Button(text='Proceed', width=20, bg='white', state = tk.DISABLED, bd=1,
highlightbackground='black', font=("Arial", 10)).place(x=208, y = 512)
def activator(button):
if (self.button_2 ['state'] == tk.DISABLED):
self.button_2 ['state'] = tk.NORMAL
else:
self.button_2['state'] = tk.DISABLED
I want to enable the proceed button after I checked the checkbutton but I can't seem to figure it out.
You have to make the following changes to your code:
You have to refer to the function named activator as self.activator when giving it to the Button(button_2) as command.
You have to change the parameter named button of the function named activator to self.
And the most important thing you need to do is move the part of code where you are placing the Button(button_2) and the Checkbutton(label_5), to a new line. Like I have done in the code below. The reason for doing so is that pack, grid and place always return None. And when you do it in the same line where you have created your widgets and assigned them to a variable i.e. button_2 and label_5, the value None gets stored in that widget.
Here's the corrected code:
import tkinter as tk
class Test:
def __init__(self):
self.master = tk.Tk()
self.master.geometry('550x550')
self.label_5 = tk.Checkbutton(self.master, text="I agree to the", bg='white', width=14, font=("Arial", 8),
command=self.activator)
self.label_5.place(x=112, y=410)
self.button_2 = tk.Button(text='Proceed', width=20, bg='white', state=tk.DISABLED, bd=1,
highlightbackground='black', font=("Arial", 10))
self.button_2.place(x=208, y=512)
self.master.mainloop()
def activator(self):
if self.button_2['state'] == tk.DISABLED:
self.button_2['state'] = tk.NORMAL
else:
self.button_2['state'] = tk.DISABLED
if __name__ == '__main__':
Test()

Having frames next to each other in Tkinter

Basically I want to place a clock at one side of the screen and text at the other, I use frames. How can I do this. Here's a picture of what it looks like now:
I want to make it so the clock is in line with the text on the same row but seperate labels. Take a look at my code and see if you could help me in someway, please!
from tkinter import *
from tkinter import ttk
import time
root = Tk()
root.state("zoomed") #to make it full screen
root.title("Vehicle Window Fitting - Management System")
root.configure(bg="grey80")
Title = Frame(root, width=675, height=50, bd=4, relief="ridge")
Title.pack(side=TOP, anchor='w')
titleLabel = Label(Title, font=('arial', 12, 'bold'), text="Vehicle Window Fitting - Management System", bd=5, anchor='w')
titleLabel.grid(row=0, column=0)
clockFrame = Frame(root, width=675, height=50, bd=4, relief="ridge")
clockFrame.pack(side=TOP, anchor='e')
clockLabel = Label(clockFrame, font=('arial', 12, 'bold'), bd=5, anchor='e')
clockLabel.grid(row=0, column=1)
curtime = ""
def tick():
global curtime
newtime = time.strftime('%H:%M:%S')
if newtime != curtime:
curtime = newtime
clockLabel.config(text=curtime)
clockLabel.after(200, tick)
tick()
Bottom = Frame(root, width=1350, height=50, bd=4, relief="ridge")
Bottom.pack(side=TOP)
root.mainloop()
One issue is trying to mix the pack and grid layout managers as they don't play well together. Below is something that just uses pack. (Note you can use either one within a frame, just not both at the same time.)
To get the two items on the same "line", another Frame named topFrame has been added and the titleLabel and clockFrame widgets nested inside that. This grouping allows them both to be acted-upon as a single unit when moved or positioned — automatically affecting both of them but retaining their relative positions (LEFT and RIGHT) to one another.
I also removed the curtime global variable because it wasn't really necessary (as you can see by the modified tick() function).
from tkinter import *
from tkinter import ttk
import time
root = Tk()
root.state("zoomed") #to make it full screen
root.title("Vehicle Window Fitting - Management System")
root.configure(bg="grey80")
topFrame = Frame(root, width=1350, height=50) # Added "container" Frame.
topFrame.pack(side=TOP, fill=X, expand=1, anchor=N)
titleLabel = Label(topFrame, font=('arial', 12, 'bold'),
text="Vehicle Window Fitting - Management System",
bd=5, anchor=W)
titleLabel.pack(side=LEFT)
clockFrame = Frame(topFrame, width=100, height=50, bd=4, relief="ridge")
clockFrame.pack(side=RIGHT)
clockLabel = Label(clockFrame, font=('arial', 12, 'bold'), bd=5, anchor=E)
clockLabel.pack()
Bottom = Frame(root, width=1350, height=50, bd=4, relief="ridge")
Bottom.pack(side=BOTTOM, fill=X, expand=1, anchor=S)
def tick(curtime=''): #acts as a clock, changing the label when the time goes up
newtime = time.strftime('%H:%M:%S')
if newtime != curtime:
curtime = newtime
clockLabel.config(text=curtime)
clockLabel.after(200, tick, curtime)
tick() #start clock
root.mainloop()
Here's what it looks like running:
I would create a frame for the header, and use something like header.pack(side="top", fill="x"). Then, I would put the two labels in that frame, packing one to the left and one to the right.
I would then add a second frame to fill the rest of the GUI, and all other widgets would go in that space.
Use grid(row=x, column=y). It makes adjacent object placing much easier.
Also, consider using just one frame for something.
You also don't need to specify width, really (unless if you use pack/grid_propagate(0)).
frame_1 = Frame(root, width=675, height=50)
frame_1.pack(side=TOP)
title_lbl = Label(frame_1, text="Lol whateva", height=50, bd=4, font=('arial', 12, 'bold'), relief="ridge", anchor=wherever_you_need_this_to_be)
title_lbl.grid(row=n, column=n)
clock_lbl = Label(clockFrame, font=('arial', 12, 'bold'), bd=5, anchor=wherever_you_need_this_to_be)
clock_lbl.grid(row=n, column=n)
You also didn't need more than one frame, just one frame for each label. It's a bad idea, really and it also consumes more time and typing.

Highlight text when clicked in tkinter

I'm working on my Python program (on an Ubuntu system), and I have little idea of what I am doing: I am importing media filenames from a folder, and print it in a Text widget, and then click it to open on VLC Player.
I just want to add an additional feature, that is: when I click on any filename, it should be highlight and then open on VLC.
Can you please guide me on how can I do it?
import subprocess,os
from Tkinter import *
def viewFile():
tex.delete('1.0', END)
for f in os.listdir(path):
if f.endswith('.h264'):
linkname="link-" + f
tex.insert(END,f + "\n", linkname)
tex.tag_configure(linkname, foreground="blue", underline=True)
tex.tag_bind(linkname, "<1>", lambda event, filename =path+'/'+f: subprocess.call(['vlc',filename])) # Video play on VLC Player
if __name__ == '__main__':
root = Tk()
step= root.attributes('-fullscreen', True)
step = LabelFrame(root,text="FILE MANAGER", font = "Arial 20 bold italic")
step.grid(row=1, columnspan=7, sticky='W',padx=100, pady=5, ipadx=130, ipady=25)
Button(step, text="ViewFile", font = "Arial 8 bold italic", activebackground="turquoise", width=30, height=5, command=viewFile).grid (row= 6, column =3)
Button(step, text="Exit", font = "Arial 8 bold italic", activebackground="turquoise", width=20, height=5, command=root.quit).grid (row= 6, column =5)
tex = Text(master=root) # TextBox For Displaying File Information
scr=Scrollbar(root,orient =VERTICAL,command=tex.yview)
scr.grid(row=8, column=2, rowspan=15, columnspan=1, sticky=NS)
tex.grid(row=8, column=1, sticky=E)
tex.config(yscrollcommand=scr.set,font=('Arial', 8, 'bold', 'italic'))
global process
path = os.path.expanduser("~/python") # Define path To play, delete, or rename video
root.mainloop()
I modified your example to have the lines highlight. How to highlight a line is explained here. Basicly I added a text_click_callback that check which line is clicked and highlight it and calls vlc. I changed the input folder, to be able to execute the code, as I dont have any video files to work with.
import subprocess,os
from Tkinter import *
def text_click_callback(event):
# an event to highlight a line when single click is done
line_no = event.widget.index("#%s,%s linestart" % (event.x, event.y))
#print(line_no)
line_end = event.widget.index("%s lineend" % line_no)
event.widget.tag_remove("highlight", 1.0, "end")
event.widget.tag_add("highlight", line_no, line_end)
event.widget.tag_configure("highlight", background="yellow")
def viewFile():
tex.delete('1.0', END)
for f in os.listdir(path):
#if f.endswith('.h264'):
linkname="link-" + f
tex.insert(END,f + "\n", linkname)
tex.tag_configure(linkname, foreground="blue", underline=True)
tex.tag_bind(linkname, "<Button-1>", text_click_callback ) # highlight a line
tex.tag_bind(linkname, "<Double-Button-1>", lambda event, filename =path+'/'+f: subprocess.call(['vlc',filename]) ) # Video play on VLC Player
if __name__ == '__main__':
root = Tk()
#step= root.attributes('-fullscreen', True)
step = LabelFrame(root,text="FILE MANAGER", font = "Arial 20 bold italic")
step.grid(row=1, columnspan=7, sticky='W',padx=100, pady=5, ipadx=130, ipady=25)
Button(step, text="ViewFile", font = "Arial 8 bold italic", activebackground="turquoise", width=30, height=5, command=viewFile).grid (row= 6, column =3)
Button(step, text="Exit", font = "Arial 8 bold italic", activebackground="turquoise", width=20, height=5, command=root.quit).grid (row= 6, column =5)
tex = Text(master=root) # TextBox For Displaying File Information
scr=Scrollbar(root,orient =VERTICAL,command=tex.yview)
scr.grid(row=8, column=2, rowspan=15, columnspan=1, sticky=NS)
tex.grid(row=8, column=1, sticky=E)
tex.config(yscrollcommand=scr.set,font=('Arial', 8, 'bold', 'italic'))
global process
path = os.path.expanduser("/tmp") # Define path To play, delete, or rename video
root.mainloop()
How it works is shown below:
But I think Bryan Oakley is right. A listbox would be better for this. Nevertheless, if you want to keep using Text, you can do as in the example provided.

print in TextBox Tkinter Python on Ubuntu

I don't know what exactly what should I called this problem so if plz edit if not fully understand.
I am writing a program in Python on Ubuntu, to print file names in TextBox with scrolling option in Y-axis.
But file names are appearing outside the TextBox and scroll option is also not working properly.
I also attached the output of program below
Can you plz me to resolve this issue?
import io,sys,os,subprocess
from Tkinter import *
def viewFile():
s=1
for f in os.listdir(path):
var= StringVar()
var.set(f)
l1 = Label(mainframe, textvariable=var)
l1.grid(row=s)
s += 1
if __name__ == '__main__':
root = Tk()
mainframe= root.title("FILE MANAGER APPLICATION") # Program Objective
mainframe= root.attributes('-fullscreen', True)
step = LabelFrame(root,text="FILE MANAGER", font = "Arial 20 bold italic")
step.grid(row=0, columnspan=7, sticky='W',padx=100, pady=5, ipadx=130, ipady=25)
Button(step, text="File View", font = "Arial 8 bold italic", activebackground="turquoise", width=30, height=5, command=viewFile).grid (row= 1, column =2)
Button(step, text="Exit", font = "Arial 8 bold italic", activebackground="turquoise", width=20, height=5, command=root.quit).grid (row= 1, column =5)
tex = Text(master=root)
scr=Scrollbar(root,orient =VERTICAL,command=tex.yview)
scr.grid(row=2, column=2, rowspan=15, columnspan=1, sticky=NS)
tex.grid(row=2, column=1, sticky=W)
tex.config(yscrollcommand=scr.set,font=('Arial', 8, 'bold', 'italic'))
global process
path = os.path.expanduser("~/python") # Define path To play, delete, or rename video
root.mainloop()
If you want to insert the filenames in tex, then call tex.insert instead of creating new Labels.
def viewFile():
for f in os.listdir(path):
tex.insert(END, f + "\n")

Categories

Resources