Can't pass path name created from QFileDialog to QLineEdit in PyQt5 - python-3.x

I have created a QDialog window with a QLineEdit field and Browse button to pass the path of a folder into a program I am working on, I have problem with it primarily at point of running program, the path has not been generated.
Nonetheless, please see my codes below:
def RPA_OCR_module(self):
# Define the dialog window
d_width = 500
d_height = 200
module_form = QDialog()
module_form.setGeometry(int((width/2)-(d_width/2)), self.y(), d_width, d_height)
module_form.setWindowTitle('RPA OCR Module')
# Define text for text field
l_col = 20
element_width = 350
element_height = 25
path_field_text = QLabel('Key in the path to working folder', module_form)
path_field_text.setGeometry(l_col,25, element_width,element_height)
path_field_text.setFont(QtGui.QFont('Helvetica', 14))
path_field_text.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
# Define the text field
working_folder_path_field = QLineEdit('Default', module_form)
working_folder_path_field.move(l_col,50)
working_folder_path_field.resize(element_width,element_height)
# Define browse button for directory name
browse_btn = QPushButton('Browse', module_form)
browse_btn.setGeometry(l_col+element_width+1,48, 119,element_height)
browse_btn.clicked.connect(self.openDirNameDialog)
try:
if QFileDialog.Accepted:
working_folder_path_field.setText(fileName)
else:
pass
finally:
pass
x = module_form.exec_()
def openDirNameDialog(self):
# options = QFileDialog.Options()
# options |= QFileDialog.DontUseNativeDialog
global fileName
fileName = str(QFileDialog.getExistingDirectory(self, "Select Directory")) # , options=options
if fileName:
print(fileName)
#self.working_folder_path_field.setText(fileName) # This doesn't work, so I commented it out
else:
pass
If anybody has any idea how to get this done, please let me know. Thanks.

You have to change working_folder_path_field to self.working_folder_path_field so you can access it from another function. Then you just have to call setText(). Here is a generic template to follow.
class Template(QWidget):
def __init__(self):
super().__init__()
btn = QPushButton('Browse')
btn.clicked.connect(self.open)
self.box = QLineEdit()
vbox = QVBoxLayout(self)
vbox.addWidget(btn)
vbox.addWidget(self.box)
def open(self):
name = QFileDialog.getExistingDirectory(self, "Select Directory")
if name:
self.box.setText(name)

Related

Ask dialog saves in the wrong map

When asked to choose a savefile location, I'll choose a map called "timelapse".
but the pictures are saved in the map before the timelapse. as in;
/home/pi instead of /home/pi/timelapse
It appears I accidentally put a default save location in the code? because it won't change the location, but I never coded it should specifically safe in /home/pi
I've tried adding manually a "/" to the text in the hope it would open the timelapse map, but I get an error with permission denied.
Creating a different submap didn't work, it still saves in /home/pi
class Capture:
def __init__(self, waittime=30):
self.capture_stop = False
self.capture_waittime = waittime
self.thread = None
self.capture_running = False
self.folder = ''
def capture_worker(self):
self.capture_running = True
try:
with picamera.PiCamera() as camera:
camera.resolution = (1024, 768)
for filename in camera.capture_continuous(self.folder+'-{timestamp:%H-%M-%S-%f}.jpg'):
i = 0
while i < self.capture_waittime:
time.sleep(0.1)
i += 0.1
if self.capture_stop:
return
finally:
self.capture_running = False
self.capture_stop = False
def start(self):
if not self.capture_running:
self.thread = threading.Thread(target=self.capture_worker)
self.capture_stop = False
self.thread.start()
def stop(self):
if self.capture_running:
self.capture_stop = True
def isRunning(self):
return self.capture_running
def setWaitTime(self, waittime):
self.capture_waittime = waittime
def setFolder(self, folder):
capture.setFolder(folder)
self.folder = folder
capture = Capture()
def startButton():
interval = float(var_2.get())
capture.setWaitTime(interval)
capture.start()
def stopButton():
capture.stop()
def chooseDir():
root.folder = filedialog.askdirectory(
parent=root, initialdir="/home/pi/", title='Please choose a save location')
I expect the pictures to be saved in the map I specifically chose. I also hope to receive some criticism on my ask dialog code so that I can improve it.

How do I make sure all GUI input variables can be accessed by certain classes and function calls?

When I provide an address /and or location to the entry bar and I press the "Get forecast" button the script fails at line 22. I think the error is raised because the str(address.get()) cant find the address variable, probably because it doesn't technically exist during that point of run time (I'm not able to log the error due to the structure of that function).
My question is; How do I make sure that my "get_hourly_forecast" function is able to access the address entry variable?
I have tried instantiating the address variable in various locations, e.g in the MainWeatherHub class, as well as in the MyWeatherApp class and then passing it as an argument to the MainWeatherHub in line 79, neither variation has worked. The current code shows the former variation.
import urllib, json, requests
from tkinter import *
from tkinter import ttk
def get_hourly_forecast(*args):
## params *args:
#A location argument
#Returns:
# A list of temps in Farenheit for the next 156 hours
API_KEY = 'removing my API key for security purposes'
try:
print('here') # The code makes it to here
curr_address = str(address.get()) # Code seems to fail here (not sure how to have the error print)
print('here')
geocode_url = "https://maps.googleapis.com/maps/api/geocode/json?address={}&key={}".format(cur_address, API_KEY)
response = requests.get(geocode_url)
response_dict = response.json()['results']
location = response_dict[0]['geometry']['location']
lat = location['lat']
lng = location['lng']
local_url_request = 'https://api.weather.gov/points/lat={}lng={}'.format(lat, lng)
response_one = requests.get(local_url_request)
json_dict_one = response_one.json()
local_props = json_dict_one['properties']
local_forecast_request = local_props['forecastHourly']
resposne_two = requests.get(local_forecast_request)
json_dict_two = resposne_two.json()
local_forecast_properites = json_dict_two['properties']
hourly_updates = local_forecast_properites['periods']
out = []
for i in hourly_updates:
for key, value in i.items():
if key == "temperature":
out.append(value)
current_weather.set(out[0])
except:
print("Not working.")
#############################################################
class MyWeatherApp:
"""
MyWeatherApp is the primary Frame for this GUI application
"""
def __init__(self, master):
super(MyWeatherApp, self).__init__()
self.master = master
# Create the main window Frame
master_style = ttk.Style()
master_style.configure('Master.TFrame')
self.master.title("My Weather")
self.master.geometry("500x500")
MWA = ttk.Frame(self.master, style='Master.TFrame')
MWA.place(relheight=1.0, relwidth=1.0)
# Run other widgets within this class
MainWeatherHub(MWA)
#############################################################
class MainWeatherHub(MyWeatherApp):
"""
The MainWeatherHub (MWH) is the top panel of the app
"""
def __init__(self, mainwindow):
super(MyWeatherApp, self).__init__()
self.mainwindow = mainwindow
# Create a Frame for the MainWeatherHub
MWH_style = ttk.Style()
MWH_style.configure('MWH.TFrame')
MWH = ttk.Frame(self.mainwindow, style='MWH.TFrame', relief='sunken')
MWH.place(relheight=0.33, relwidth=0.95, relx=0.025, rely=0.025)
# Create an entry widget to take a location
# and store that as a loction variable.
address = StringVar()
loc_entry = ttk.Entry(MWH, textvariable=address)
loc_entry.place(relheight=0.30, relwidth=.95, relx=0.025, rely=0.05)
# Get weather button finds weather for the users location
current_weather = StringVar()
get_weather_button = ttk.Button(loc_entry, text="Get Forecast", command=get_hourly_forecast)
get_weather_button.place(relheight=0.85,relwidth=0.2, relx=0.79, rely=0.075)
#Display weather in the Message widget
weath_display = Message(MWH, textvariable=current_weather)
weath_display.place(relwidth=0.95, relheight=0.55, relx=0.025, rely=0.375)
root = Tk()
my_gui = MyWeatherApp(root)
root.mainloop()
If this script works properly, it should return the current temperature in degrees Fahrenheit of the location that was provided in the entry bar.
You should send it as parameter
def get_hourly_forecast(cur_address):
geocode_url = "...".format(cur_address, API_KEY)
And then assing to button function which runs get_hourly_forecast with string
class MainWeatherHub(MyWeatherApp):
def __init__(self, mainwindow):
self.address = StringVar() # use self.
ttk.Button(loc_entry, text="Get Forecast", command=run_it)
def run_it(self):
get_hourly_forecast(self.address.get())
or using lambda
class MainWeatherHub(MyWeatherApp):
def __init__(self, mainwindow):
ttk.Button(loc_entry, text="Get Forecast", command=lambda:get_hourly_forecast(address.get()))
EDIT:
I see you use current_weather (StringVar from MainWeatherHub) in get_hourly_forecast to set value current_weather.set(out[0]).
You could send current_weather to get_hourly_forecast as parameter
def get_hourly_forecast(cur_address, current_weather):
geocode_url = "...".format(cur_address, API_KEY)
current_weather.set(out[0])
and
class MainWeatherHub(MyWeatherApp):
def __init__(self, mainwindow):
self.address = StringVar() # use self.
self.current_weather = StringVar() # use self.
ttk.Button(loc_entry, text="Get Forecast", command=run_it)
def run_it(self):
get_hourly_forecast(self.address.get(), self.current_weather)
but it could be better to return value from get_hourly_forecast
def get_hourly_forecast(cur_address):
geocode_url = "...".format(cur_address, API_KEY)
return out[0]
and get it in run_it
def run_it(self):
result = get_hourly_forecast(self.address.get())
if result is not None:
self.current_weather.set(result)
This way get_hourly_forecast doesn't work with StringVar and you can use it in other program which doesn't use StringVar.

How to create multiple checkbox in loop using tkinter

I am New to use Tkinter.I want to create multiple checkbox from loop.I refer Tkinter checkboxes created in loop but i don't understand it.
I want to display all files as a checkbox located in a directory.
Help me and tell me what i need to change ?
Code:
from tkinter import filedialog,Checkbutton
import tkinter,os
window = tkinter.Tk()
def browse():
filez = filedialog.askdirectory(parent=window,title='Choose a file')#I choose a directory
ent1.insert(20,filez)#insert the path of directory to text box
dirs = os.listdir(filez)#gives all files of direcory
for file in dirs:
print(file)#Getting all files
var = tkinter.IntVar()
c = tkinter.Checkbutton(window,text=file,variable=var)#Create files to checkox
c.place(x=0,y=100)
window.title("First Gui")
window.geometry("400x400")
window.wm_iconbitmap("path of icon")
lbl = tkinter.Label(window,text="path")
lbl.place(x=0,y=60)
ent1 = tkinter.Entry(window)
ent1.place(x=80,y=60)
btn1 = tkinter.Button(window,text="Set Path",command=browse)
btn1.place(x=210,y=57)
window.mainloop()
After click on button set path i want to to display all files of directory as a checkbox using browse function
I see three problems
you use c.place(x=0,y=100) for all Checkbuttons so you can see only last one - other are hidden behind last one.
every Checkbutton need own IntVar which you can keep on list or in dictionary.
when you select new path then you have to remove previous Checkbuttons so you have to remember them on list or in dictionary.
Example shows how you could use pack() instead of place() to easily put all Checkbuttons. It also show how to uses dictionary to keep IntVars and check which was selected, and how to use list to keep Checkbuttons and remove them later from window.
import tkinter
import tkinter.filedialog
import os
# --- functions ---
def browse():
filez = tkinter.filedialog.askdirectory(parent=window, title='Choose a file')
ent1.insert(20, filez)
dirs = os.listdir(filez)
# remove previous IntVars
intvar_dict.clear()
# remove previous Checkboxes
for cb in checkbutton_list:
cb.destroy()
checkbutton_list.clear()
for filename in dirs:
# create IntVar for filename and keep in dictionary
intvar_dict[filename] = tkinter.IntVar()
# create Checkbutton for filename and keep on list
c = tkinter.Checkbutton(window, text=filename, variable=intvar_dict[filename])
c.pack()
checkbutton_list.append(c)
def test():
for key, value in intvar_dict.items():
if value.get() > 0:
print('selected:', key)
# --- main ---
# to keep all IntVars for all filenames
intvar_dict = {}
# to keep all Checkbuttons for all filenames
checkbutton_list = []
window = tkinter.Tk()
lbl = tkinter.Label(window, text="Path")
lbl.pack()
ent1 = tkinter.Entry(window)
ent1.pack()
btn1 = tkinter.Button(window, text="Select Path", command=browse)
btn1.pack()
btn1 = tkinter.Button(window, text="Test Checkboxes", command=test)
btn1.pack()
window.mainloop()

Bug appears when writing file from tkinter module

import tkinter as tk
class Application(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.pack()
self.create_widgets()
def create_widgets(self):
self.hi_there = tk.Button(self)
self.hi_there["text"] = "Done!\n(click me)"
self.hi_there["command"] = self.say_hi
self.hi_there.pack(side="top")
self.entrythingy = tk.Entry()
self.entrythingy2 = tk.Entry()
self.entrythingy.pack()
self.entrythingy2.pack()
# here is the application variable
self.contents = tk.StringVar()
self.contents2 = tk.StringVar()
# set it to some value
self.contents.set("stdio")
self.contents2.set("script name")
# tell the entry widget to watch this variable
self.entrythingy["textvariable"] = self.contents
self.entrythingy2["textvariable"] = self.contents2
self.text = tk.Text()
self.text.pack()
# and here we get a callback when the user hits return.
# we will have the program print out the value of the
# application variable when the user hits return
self.entrythingy.bind('<Key-Return>',
self.print_contents)
self.quit = tk.Button(self, text="QUIT", fg="red",
command=root.destroy)
self.quit.pack(side="bottom")
def say_hi(self):
#print("hi there, everyone!")
self.fn = self.contents2.get()
self.body = self.text.get(1.0, tk.END).split('\n')
#print('Self.body:\n',self.body)
self.libs = self.contents.get().split(' ')
self.make_c()
def make_c(self):
lib_text = ''
for i in self.libs:
lib_text += "#include <lib.h>\n".replace('lib', i)
body_text = "int main() {\n\t"+"\n\t".join(self.body)+"return 0\n}"
print(lib_text+body_text)
with open(self.fn+'.c', 'w+') as f:
f.write(lib_text+body_text)
print('File written!')
from subprocess import call
call(['gcc',self.fn+'.c', '-o', self.fn])
def print_contents(self, event):
print("hi. contents of entry is now ---->",
self.contents.get())
#self.contents.set("")
#def
root = tk.Tk()
app = Application(master=root)
app.mainloop()
Those are the my code, which tries to make a c file and convert it. The problem is, when I convert it once, it is working fine, but when I change the content of the text box, the file doesn't change, and I don't understand why. I am sure that I put in the new file content, because it prints before it writes. Also, it appears that when I try to write files independent from tkinter, it works just the way I want it to.
I think there is some mechanism that I am not aware of in TK, or there is a bug. Please help me out, thanks.
I solved it. It doesn't compile again due to the error in it when I added return 0, without semicolon. So, when I click the executable file, it shows the old program. I added the semicolon, and now it is fine. Thx everyone!

Creating tkinter gui.How to display information when ID number provided

I am working on creating a gui and could use some help. There are three programs that build off of each other. MY imput will be two CSV files, Examples below:
items4.csv
12345,Italy,100
13579,China,50
ETC.
transactions4.csv
12345,15
13579,10
12345,20
13579,-10
What I want it to do is upon running the gui will open and the window will ask for the "Item ID" Upon entering an id, say 12345, it will open up a new window that displays the following: getID, getName, getAvailableStart, and getAvailableEnd, all of these definitions are were created by the travelclass program (found below) when the program travelToolbox reads the two CSV files.
Note: Both the travelClass and travelToolbox programs are working fine. IT is only travelSystem that needs changing at this point
What I've done:
At this point I have managed to get the travelSystems presents the initial GUI however it doesn't matter what I enter in the entry box because when I hit the open button the next gui opens up but it only shows the information found in the first line of items4.csv. I think my main issue is line 34 or may be line 16. Let me know if any other information is needed.
I could really appreciate some help. Thank you in advance.
travelsystem
from travelToolbox import readItems, readTransactions
from tkinter import *
from tkinter import font
import tkinter as tk
class myApp :
def __init__(self, top, itemRecords) :
self.root = top
# Create a container Frame at the bottom
self.bframe = Frame(self.root)
self.bframe.pack(side=BOTTOM) # Create Label
self.xlabel = Label(self.root, text="Item ID")
self.xlabel.pack(side=LEFT)
self.xentry = Entry(self.root, bd=5) # Create Entry box
self.xentry.pack(side=LEFT)
self.xentry.focus_set() # Set focus in Entry box
self.xopen = Button(self.root, text="Open", command=self.showStockItem) # Create open Button
self.xopen.pack(side=LEFT)
self.xquit = Button(self.bframe, text="Quit", command=self.quitit ) # Create quit Button
#self.root instead of bframe
self.xquit.pack(side=BOTTOM)
def showStockItem(self):
tbl = Toplevel() # Create Toplevel window
hdr = font.Font(underline=1, weight="bold") # Create header font
tid = Label(tbl, text="ID", font=hdr) # Create 4 column headers in grid
tid.grid(row=0, column=0)
tlast = Label(tbl, text="Name", font=hdr)
tlast.grid(row=1, column=0)
tfirst = Label(tbl, text="Start", font=hdr)
tfirst.grid(row=2, column=0)
tlabel = Label(tbl, text="End", font=hdr)
tlabel.grid(row=3, column=0)
for rec in itemRecords.values() :
tid = Label(tbl, text= rec.getID()) # Create 4 column headers in grid
tid.grid(row=0, column=1)
tlast = Label(tbl, text= rec.getName())
tlast.grid(row=1, column=1)
tfirst = Label(tbl, text= rec.getAvailableStart())
tfirst.grid(row=2, column=1)
tlabel = Label(tbl, text= rec.getAvailableEnd())
tlabel.grid(row=3, column=1)
#self.xquit.pack(side=BOTTOM) #May not need this.
return
def quitit(self):
self.root.destroy()
return
itemsFileName = "items4.csv"
transactionsFileName = "transactions4.csv"
# itemRecords is a dictionary of stockItem records indexed by item ID
itemRecords = {}
# Read the items from itemsFileName into itemRecords
readItems(itemsFileName, itemRecords)
# Read the transactions from transactionsFileName into itemRecords
readTransactions(transactionsFileName, itemRecords)
top = tk.Tk()
#top = Travel()
app = myApp(top, itemRecords)
top.mainloop()
Other files:
travelToolbox
import csv
from travelClass import travelItem
def readItems(itemsFileName, itemRecords) :
# readItems reads items from itemsFileName into the itemRecords dictionary
# Open itemsFileName and create a CSV file reader
itemsFile = open(itemsFileName, 'r')
itemsReader = csv.reader(itemsFile)
# Process each row of the items file
for row in itemsReader :
# Get the values for the record
(iid, iname, icount) = row
iid = str(iid)
iname = str(iname)
icount = int(icount)
# Check if this ID is not yet in itemRecords
if (not(iid in itemRecords)) :
# Create a travelItem object and add it to itemRecords
itemRecord = travelItem(iid, iname, icount)
itemRecords[iid] = itemRecord
def readTransactions(transactionsFileName, itemRecords) :
# readTransactions reads transactions from transactionsFileName into the itemRecords dictionary
transactionFile = open(transactionsFileName, 'r')
transactionReader = csv.reader(transactionFile)
for row in transactionReader :
# Get the values for the record
(iid, itransaction) = row
iid = str(iid)
itransaction = int(itransaction)
itemRecords[iid].appendTransaction(itransaction)
#for key, value in itemRecords.items() :
transactionFile.close()
travelClass
class travelItem :
Class travelItem :
def __init__(self, itemID, itemName, itemCount) :
# Constructor to create inventoryItem CORRECT
self.id = itemID
self.name = itemName
self.AvailableStart = itemCount
self.transactions = []
def getID(self) :
# getID returns the tour ID CORRECT
return(self.id)
def getName(self) :
# getName returns the tour name CORRECT
return (self.name)
def setName(self, newName) :
# setName sets the tour name
self.name = newName
def getAvailableStart(self) :
# returns the starting availability
return (self.AvailableStart)
def appendTransaction(self, num) :
# appendTransaction appends a transaction to the transactions list
self.transactions.append(num)
def getTransactions(self) :
# getTransactions returns the list of transactions
return (self.transactions)
def getReservations(self) :
# returns the total of reservation transactions
total = 0
for num in self.transactions :
if ((num) > 0):
total += (num)
self.Reservations = total
return(self.Reservations)
def getCancellations(self) :
# returns the total of cancellation transactions
total = 0
for num in self.transactions :
if (num <= 0):
total += (num)
return(total)
def getAvailableEnd(self) :
# returns the ending availability, which is availableStart minus transactions
self.AvailableEnd = ((self.AvailableStart) - (self.Reservations) - (self.getCancellations()))
return(self.AvailableEnd)

Resources