Webcam, Tkinter, optionmenu, thread - python-3.x

The following script is an attempt to choose webcam from OptionMenu in tkinter and open using thread:
class wcbm():
def __init__(self, nCam):
# a lot of code
from tkinter import *
import threading
def main():
main_window = Tk()
# Webcam list
options = [0,1,2,3,4,5,6,7,8,9]
clicked = StringVar()
clicked.set("Choose a webcam")
drop = OptionMenu(main_window, clicked, *options).pack()
btn = Button(main_window, text="Botão", command=lambda:threading.Thread(target=wbcm(clicked.get())).start()).pack()
main_window.mainloop()
if __name__ == "__main__":
main()
wbcm is a class to open webcam (opencv, dlib, ...). The only one required variable for this class is nCam.
The above script gives an error:
TypeError: 'wbcm' object is not callable
What's going on, please?
I expect with my script I may choose and show (thread) webcam from OptionMenu list options.

Related

How to open two modules in one window, Python Tkinter

I have a question: i am tossing the code from 2ch files, i have already lost ideas. Calling fileA.py opens a window for me with two buttons exit and start. Exit works but when I click start I need to open the second window fileB.pt. (I want both windows to open in one window) Seemingly works only problem I have is it doesn't open "window on window" but "docks underneath" and I have the effect of two windows open :/. Please help, thank you in advance:) Python 3.10
fileA.py
import tkinter as tk
from GUI.module.scale_of_img import get_scale
class FirstPage:
def __init__(self, root):
self.root = root
def get_settings(self):
# Window settings
self.root.title('....')
self.root.resizable(False, False)
self.root.geometry("1038x900")
if __name__ == '__main__':
first = FirstPage(tk.Tk())
first.get_run_first_page()
fileB.py
import tkinter as tk
"importy..."
''' The second side of the application '''
class SecondPage:
def __init__(self, root=None):
self.root = root
self.my_canvas = tk.Canvas(self.root, width=1038, height=678)
self.my_canvas.pack(fill="both", expand=True)
if __name__ == '__main__':
second = SecondPage(tk.Tk())
second.get_run()
in order to put two "windows" in the same "window" you need to put all items inside a Frame, which is basically a container than you can simply pack when you want everything to show and unpack when you want everything in it to disapear.
all items in the first window will be children of a frame and all items in the second window will be children of another frame, and to switch you just need to call pack_forget() on one and pack() on another.
for the first file
class FirstPage:
def __init__(self, root):
self.root = root
self.frame = tk.Frame(root)
self.frame.pack(expand=True)
def get_picture(self):
# all items inside this window must be children of self.frame
self.my_canvas = tk.Canvas(self.frame, width=1038, height=500)
...
def get_second_page(self):
from GUI.module.second_page import SecondPage
self.frame.pack_forget() # to hide first page
# self.frame.destroy() # if you are never brining it back
SecondPage(self.root).get_run()
and for the second file
class SecondPage:
def __init__(self, root=None):
self.root = root
self.frame = tk.Frame(root) # new frame
self.frame.pack(expand=True)
self.my_canvas = tk.Canvas(self.frame, width=1038, height=678)
self.my_canvas.pack(fill="both", expand=True)
def get_button(self):
# Add buttons
# all here should be children of self.frame now
button1 = tk.Button(self.frame, text="...", )
...
you could destroy the first frame when you switch over to save some resources if you don't intend to return to it ever again, but the difference in memory is negligible.
assuming what you want is another Tk window to open, you shouldn't give it the same root, instead use an instance of Toplevel
from tkinter import Toplevel
# class definition here
def get_second_page(self):
from GUI.module.second_page import SecondPage
SecondPage(Toplevel(self.root)).get_run()
passing the Toplevel as a child of self.root is necessary, but note that the two windows have different roots.
Edit: turns out this wasn't what the OP ment by "window on window" -_-, but it am keeping it here for other readers.

Embed Python 3 Tkinter module as Widget in PyQT5

First post and new to python so apologies if the post formatting is weird or the coding errors are dumb.
I created a module using tkinter that I want to embed into a pyQt5 MainWindow widget.
This is the tkinter module, titled Del.py, I'm trying to import.
class Delfiles(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.mw = self.mainwindow()
def mainwindow(self):
# mainwindow formatting
def dellist(self):
# delete function for buttons in mainwindow
class Results(tk.Toplevel):
def __init__(self):
tk.Toplevel.__init__(self)
# toplevel popup that appears after dellist function runs
# root = Delfiles()
# root.mainloop()
This is the part of the pyqt5 module where I've been trying to embed the tkinter module into.
class SpreadSheet(QMainWindow):
def __init__(self, rows, cols, parent=None):
super(SpreadSheet, self).__init__(parent)
self.rows = rows
self.cols = cols
self.cells = {}
self.create_table1()
self.create_table2()
deletefiles = Del.mw()
self.centralwidget = QWidget()
self.vlayout = QVBoxLayout()
self.hlayout = QHBoxLayout()
self.vlayout.addWidget(self.table1)
self.vlayout.addWidget(self.table2)
self.hlayout.addLayout(self.vlayout)
self.hlayout.addWidget(deletefiles)
self.centralwidget.setLayout(self.hlayout)
self.table1.cellDoubleClicked.connect(self.celldoubleclicked)
self.table2.installEventFilter(self)
self.setCentralWidget(self.centralwidget)
self.show()
if __name__ == __main__:
app = QApplication(sys.argv)
sheet = SpreadSheet(5, 5)
sheet.resize(1500, 900)
sheet.show()
sys.exit(app.exec_())
# https://negfeedback.blogspot.com/2017/12/a-simple-gui-spreadsheet-in-less-than.html
#link to source code for the pyqt5 module I'm working with
Every time I try to run the pyqt module with the tkinter module embedded, the tkinter module either opens on top of the pyqt5 module or i get the following error.
Exception in Tkinter callback
AttributeError: module 'Del' has no attribute 'mw'
Any help is greatly appreciated
You can't create windows in tkinter and use them in a PyQT5 application. Each GUI toolkit has a rendering model that knows nothing about the other.

Python 3.5 tkinter confirmation box created progress bar and reads in csv not quite working

I'm realtively new to python and am making a GUI app that does a lot of file i/o and processing. To complete this i would like to get a confirmation box to pop-up when the user commits and actions. From this when clicking 'yes' the app then runs the i/o and displays a progress bar.
From other threads on here I have gotten as far as reading about the requirement to create an addtional thread to take on one of these processes (for example Tkinter: ProgressBar with indeterminate duration and Python Tkinter indeterminate progress bar not running have been very helpful).
However, I'm getting a little lost because I'm not activating the threaded process from the Main() function. So I'm still getting lost in how, and where, I should be creating the progress bar and passing of the i/o process to another thread (reading in a csv file here).
Here is my code and I would be very grateful for any help anyone can give me:
import tkinter as tk
import tkinter.messagebox as messagebox
import csv
import tkinter.ttk as ttk
import threading
class ReadIn(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("Read in file and display progress")
self.pack(fill=tk.BOTH, expand=True)
self.TestBtn = tk.Button(self.parent, text="Do Something", command=lambda: self.confirm_pb())
self.TestBtn.pack()
def confirm_pb(self):
result = messagebox.askyesno("Confirm Action", "Are you sure you want to?")
if result:
self.handle_stuff()
def handle_stuff(self):
nf = threading.Thread(target=self.import_csv)
nf.start()
self.Pbar()
nf.join()
def Pbar(self):
self.popup = tk.Tk()
self.popup.title('Loading file')
self.label = tk.Label(self.popup, text="Please wait until the file is created")
self.progressbar = ttk.Progressbar(self.popup, orient=tk.HORIZONTAL, length=200,
mode='indeterminate')
self.progressbar.pack(padx=10, pady=10)
self.label.pack()
self.progressbar.start(50)
def import_csv(self):
print("Opening File")
with open('csv.csv', newline='') as inp_csv:
reader = csv.reader(inp_csv)
for i, row in enumerate(reader):
# write something to check it reading
print("Reading Row " + str(i))
def main():
root = tk.Tk() # create a Tk root window
App = ReadIn(root)
root.geometry('400x300+760+450')
App.mainloop() # starts the mainloop
if __name__ == '__main__':
main()
The statement nf.join() in function handle_stuff() will block tkinter's main loop to show the progress bar window. Try modify handle_stuff() as below:
def handle_stuff(self):
nf = threading.Thread(target=self.import_csv)
nf.start()
self.Pbar()
#nf.join() # don't call join() as it will block tkinter's mainloop()
while nf.is_alive():
self.update() # update the progress bar window
self.popup.destroy()

Tkinter - Changing label text via another function

I know that it's often best practice to write Tkinter GUI code using object-oriented programming (OOP), but I'm trying to keep things simple because I'm new to Python.
I have written the following code to create a simple GUI:
#!/usr/bin/python3
from tkinter import *
from tkinter import ttk
def ChangeLabelText():
MyLabel.config(text = 'You pressed the button!')
def main():
Root = Tk()
MyLabel = ttk.Label(Root, text = 'The button has not been pressed.')
MyLabel.pack()
MyButton = ttk.Button(Root, text = 'Press Me', command = ChangeLabelText)
MyButton.pack()
Root.mainloop()
if __name__ == "__main__": main()
The GUI looks like this.
I thought the text in the GUI (MyLabel) would change to "You pressed the button!" when the button is clicked, but I get the following error when I click the button:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\elsey\AppData\Local\Programs\Python\Python35-32\lib\tkinter\__init__.py", line 1549, in __call__
return self.func(*args)
File "C:/Users/elsey/Documents/question code.py", line 6, in ChangeLabelText
MyLabel.config(text = 'You pressed the button!')
NameError: name 'MyLabel' is not defined
What am I doing wrong? Any guidance would be appreciated.
MyLabel is local to main() so the way you can not access it that way from ChangeLabelText().
If you do not want to change the design of your program, then you will need to change the definition of ChangeLabelText() like what follows:
def ChangeLabelText(m):
m.config(text = 'You pressed the button!')
And withing main() you will need to pass MyLabel as an argument to ChangeLabelText().
But again, you will have a problem if you code this command = ChangeLabelText(MyLabel) when you declare and define MyButton because the program will execute directly the body of ChangeLabelText() at the start and you will not have the desired result.
To resolve this later problem, you will have to use (and may be read about) lambda
Full program
So your program becomes:
#!/usr/bin/python3
from tkinter import *
from tkinter import ttk
def ChangeLabelText(m):
m.config(text = 'You pressed the button!')
def main():
Root = Tk()
MyLabel = ttk.Label(Root, text = 'The button has not been pressed.')
MyLabel.pack()
MyButton = ttk.Button(Root, text = 'Press Me', command = lambda: ChangeLabelText(MyLabel))
MyButton.pack()
Root.mainloop()
if __name__ == "__main__":
main()
Demo
Before clicking:
After clicking:
Are your sure you don't want to do it as a class (i think it makes the code a bit more clean as your project grows)? Here is a way to accomplish what you'e looking for:
#!/usr/bin/python3
from tkinter import *
from tkinter import ttk
class myWindow:
def __init__(self, master):
self.MyLabel = ttk.Label(root, text = 'The button has not been pressed.')
self.MyLabel.pack()
self.MyButton = ttk.Button(root, text = 'Press Me', command = self.ChangeLabelText)
self.MyButton.pack()
def ChangeLabelText(self, event=None):
self.MyLabel.config(text = 'You pressed the button!')
if __name__ == "__main__":
root = Tk()
mainWindow = myWindow(root)
root.mainloop()
In a Mac, is looks like this before pressing the button:
And when you press it:
But basically, in order to be able to change the text in a Label or a button, you need to ensure it has an active reference. In this case, we are doing it by creating the window as a class and referencing the widgets in the form self. widget_name = widget().
but I'm trying to keep things simple because I'm new to Python Hopefully this helps in understanding that classes are the simple way, otherwise you have to jump through hoops and manually keep track of many variables. Also, the Python Style Guide suggests that CamelCase is used for class names and lower_case_with_underlines for variables and functions. https://www.python.org/dev/peps/pep-0008/
from tkinter import *
from tkinter import ttk
class ChangeLabel():
def __init__(self):
root = Tk()
self.my_label = ttk.Label(root, text = 'The button has not been pressed.')
self.my_label.pack()
## not necessary to keep a reference to this button
## because it is not referenced anywhere else
ttk.Button(root, text = 'Press Me',
command = self.change_label_text).pack()
root.mainloop()
def change_label_text(self):
self.my_label.config(text = 'You pressed the button!')
if __name__ == "__main__":
CL=ChangeLabel()

How to display a custom dialog using PyQt and QtDesigner to design the custom dialog?

I have designed 2 widgets - one is the main application widget and a custom widget which would allow me to set the preferences in my main application. They are named - main and child.
Now, I can't get the child widget to show when I click the button in the main application.
Tried to learn from the Rapid GUI programming using Python and Qt book, but the example given there is for a hand coded form and not designed using QtDesigner. I am getting confused. Kindly help.
My code so far is this-
import serial, sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from main import Ui_Form # main.py and child.py are the ui
from child import Ui_Form as Child_Form # files generated using pyuic4
class Main(QMainWindow):
def __init__(self, parent = None):
super(Main, self).__init__(parent)
self.ui = Ui_Form()
self.ui.setupUi(self)
self.connect(self.ui.btnLaunch, SIGNAL("clicked()"), self.show)
def show(self):
dialog = QDialog()
dialog.ui = Child_Form()
dialog.ui.setupUi(self)
if __name__ == "__main__":
app = QApplication(sys.argv)
myapp = Main()
myapp.show()
sys.exit(app.exec_())
However, nothing happens when I try to launch this program.
Instead of this code:
self.connect(self.ui.btnLaunch, SIGNAL("clicked()"), self.show)
def show(self):
dialog = QDialog()
dialog.ui = Child_Form()
dialog.ui.setupUi(self)
try with this, it should work:
self.connect(self.ui.btnLaunch, SIGNAL("clicked()"), self.showDialog)
def showDialog(self):
dialog = QDialog()
dialog.ui = Child_Form()
dialog.ui.setupUi(self)
dialog.show()

Resources