I have a GUI that has 4 widgets which are user inputs (file in/out and directory in/out). I am trying to make a button that will do two things.
I want to button when clicked to send the four user set parameters to another imported function.
self.btn.clicked.connect(lambda: self.sendData(self.rawName, self.outName, self.directoryIn, self.directoryOut))
I was using something like this. Where send data looks like this:
def sendData(self, rawName, outName, directoryIn, directoryOut):
try:
foo.main(rawName, outName, directoryIn, directoryOut)
except TypeError:
pass
In this case foo.main is the imported function. The user input method looks like this:
def setInputDirectory(self):
options = QtGui.QFileDialog.DontResolveSymlinks | QtGui.QFileDialog.ShowDirsOnly
directoryIn = QtGui.QFileDialog.getExistingDirectory(self,
"Some Directory",
self.directoryLabelIn.text(), options)
if directoryIn:
self.directoryLabelIn.setText(directoryIn)
Finally, I want to have the button (btn) be clickable only when all four values are entered in the gui.
self.rawName = ""
self.outName = ""
self.directoryIn = ""
self.directoryOut = ""
...
self.btn.clicked.connect(self.sendData)
self.btn.setEnabled(False) # disable button here, enable it later
so you can simply send those parameters directly:
def sendData(self):
try:
foo.main(self.rawName, self.outName, self.directoryIn, self.directoryOut)
except TypeError:
pass
also after every input, check if all four values are entered and if so enable button:
def areAllFourValuesEntered(self):
if (self.rawName!="" and self.outName!="" and self.directoryIn!="" and self.directoryOut!=""):
self.btn.setEnabled(True)
Related
def move(sp, t):
if sp == "eightA":
sps = eightA
if t == "sixA":
st = sixA
if st == " ":
# target is empty
sps["text"] = " "
st["text"] = str(sps["text"])
Hello Everyone, Im trying to make this function to "move" text from a tkinter button to another, lets say sp is what i want to move, and t is the target so i want to move text
from the button eightA to sixA, also note that i want to be able to use this function on any 2 buttons, Its hard to explain, but please help if you can, the code above is one i tried out of alot other which didnt work,
Thanks
Procedure
Store the text on first button in a variable
Configure first button to have no text
Configure second button to have text stored in variable
Example
btn1 = tk.Button(text="Hello")
btn2 = tk.Button(text="Not Hello")
# store text on btn1 in a variable
txt = btn1['text']
# configure btn1 to have no text
btn1.config(text="")
# configure btn2 to have text stored in variable
btn2.config(text=txt)
So your function would look like
def move(btn1, btn2):
txt = btn1['text']
btn1.config(text=" ")
btn2.config(text=txt)
I'm trying to create a GUI, in the nav menu you can click a cascade option to open another window where you can click roll to generate a set of numbers. It comes up with error. I think it's because the function is called from another function I just don't know how to get that function to call it/ if there is any other ways to fix this. I've tried global functions and looking it up but haven't found anything other than using classes so far, which I don't know how to do.
line 147, in totalRolls
txtresultsOut.set(totalRollResults)
NameError: name 'txtresultsOut' is not defined
Here is the code that is relevant to it. I've called the function to skip having to input all the other code for the main gui window.
def rollSix():
s = 0
numbers = [0,0,0,0]
for i in range(1,5):
numbers[s] = randrange(1,7)
s += 1
numbers.remove(min(numbers))
Result = sum(numbers)
totalRollResults.append(Result)
def totalRolls():
rollOne()
rollTwo()
rollThree()
rollFour()
rollFive()
rollSix()
txtresultsOut.set(totalRollResults)
def rollw():
rollWindow = tix.Tk()
rollWindow.title("Dice Rolls")
diceLabel = Label(rollWindow, text = "Click Roll for your Stats")
diceLabel.grid(row = 0, column = 0)
rollBtn = Button(rollWindow, text = "Roll Stats", command = totalRolls)
rollBtn.grid(row = 1, column = 0)
txtresultsOut = StringVar()
resultsOut = Entry(rollWindow, state = "readonly", textvariable = txtresultsOut)
resultsOut.grid(row = 2, column = 0)
rollw()
first of all I would NOT recommend using StringVar(). You can use the .get() method of Entry to obtain the value inside the same. Try this way and make a global declaration of the Entry whose values you want to get in other functions.
EDIT------------
#you can use the following code to make your entry active to be edited.
entry.configure(state='normal')
# insert new values after deleting old ones (down below)
entry.delete(0,END)
entry.insert(0, text_should_be_here)
# and finally make its state readonly to not let the user mess with the entry
entry.configure(state='readonly')
So I'm grabbing links of events off a website and putting them into a drop down menu to be selected. My code for the menu:
import Tkinter as tk
from Tkinter import StringVar
selectMenu = tk.Tk()
# #-> this is what I have
# Followed by what you can use
#var = Vars()
#events = var.GetVars('Event')
events = " "
options = []
links = []
#forms = (driver.find_elements_by_class_name("with-cats")) #This is what I have
forms = ["Yolo ","Dad? Closed","Anotha One","Normies! Closed"] #This is so you can try it for yourself
for x in forms:
#info = x.text
info = x #Again, this is so you can try it for yourself
if events in info.lower():
links.append(x)
for link in range(0,len(links)):
#options.append(links[link].text)
options.append(links[link])
list(set(options))
selection = []
for link in range(0,len(options)):
selection.append(options[link])
select = StringVar(selectMenu)
select.set("--None Selected--")
menu = tk.OptionMenu(selectMenu, select, *(selection))
msg = "Which one would you like to attend?"
label = tk.Label(selectMenu, text=msg, font="Helvedica 14")
label.pack(side='top', pady=10)
menu.pack(side="top", pady=10)
selectMenu.attributes('-topmost', True)
selectMenu.mainloop()
So this works fine and dandy, but I would like to improve the look to make it more obvious which events are open. To clarify, an event found that is open and put into the menu may look like "This is a cool event", but one that is closed would be read as "This is a cool event Closed". My aim is to be able to make the foreground red of either just the word Closed or the string containing Closed, whichever is possible if any (And I'm not sure if it's possible because menus and buttons on osx are usually defaulted to system settings, maybe there is a way around this?).
Current: Desired:
According to the documentation for OptionMenu here and here I don't think there is a way to set the color of text.
You might be able to get something close to what you want by using a listBox instead. See post here for the listBox example.
Found a solution! Using a Menu inside of a MenuButton the same way Tkinter creates MenuOptions, I was able to create a custom MenuOption. If you want to add more options, you can use the menbutton.configure() option to edit the button, and menbutton.menu to edit the menu items.
import Tkinter as tk
from Tkinter import Menu, Menubutton
class Vars():
global vari
vari = {}
def GetVars(self, var):
return vari.get(str(var))
def SendVars(self, var, val):
vari[str(var)] = val
class App():
def buttselect(self, link, menbutton, selectMenu):
var = Vars()
var.SendVars("Selection", link) # Store selected event
menbutton.configure(text=link) # Set menu text to the selected event
def prnt(self, link):
var = Vars()
print var.GetVars("Selection") # Print event
def __init__(self, selectMenu):
events = " "
options = []
links = []
forms = ["Yolo ","Dad? Closed","Anotha One","Normies! Closed"] #This is so you can try it for yourself
menbutton = Menubutton (selectMenu, text="--None Selected--", relief="raised")
menbutton.grid()
menbutton.menu = Menu (menbutton, tearoff=0)
menbutton["menu"] = menbutton.menu
#Get a list of event names
for x in forms:
info = x #Again, this is so you can try it for yourself
#If desired event keyword is in an event name, add it to the correct links
if events in info.lower():
links.append(x)
#Remove duplicates
for link in range(0,len(links)):
options.append(links[link])
list(set(options))
#Final list of event names turned into menu commands
for link in options:
if "Closed" in link:
menbutton.menu.add_command( label= link, command= lambda link=link: self.buttselect(link, menbutton, selectMenu), foreground='red')
else:
menbutton.menu.add_command( label= link, command= lambda link=link: self.buttselect(link, menbutton, selectMenu))
b = tk.Button(selectMenu, text="Selection", command= lambda link=link: self.prnt(link)) #Print selected event
b.pack()
msg = "Which one would you like to attend?"
label = tk.Label(selectMenu, text=msg, font="Helvedica 14")
label.pack(side='top', pady=10)
menbutton.pack(side="top", pady=10)
selectMenu = tk.Tk()
selectMenu.attributes('-topmost', True)
app = App(selectMenu)
selectMenu.mainloop()
This results in exactly the result desired:
I found a way!
Let's say x is an optionmenu with options:
options=['Red','Blue','Green']
defopt=tk.StringVar(options[0]) #StringVariable to hold the selected option.
x=tk.OptionMenu(self.optmenuframe,defopt,*options)
Now, get the menu object from the optionmenu and use entryconfig method. That's it!
x.children['menu'].entryconfig(0,foreground='red')
x.children['menu'].entryconfig(1,foreground='blue')
x.children['menu'].entryconfig(2,foreground='green')
#0 is the index of the option you want to apply the configurations to.
I want to activate command link button if at least one element is checked in a treeview.
I tried this method but it is not working well :
def activate_launch_button(self):
model = self.scenarios.model()
checked_indexes = model.match(model.index(0, 0), QtCore.Qt.CheckStateRole,QtCore.Qt.Checked, -1,QtCore.Qt.MatchExactly | QtCore.Qt.MatchRecursive)
print checked_indexes
if checked_indexes != []:
self.launch_btn.setEnabled(True)
The problem with this method is the button is activated only after closing the window. I don't understand why.
For caling this method I put it in two methods :
def show(self):
self.project.load()
if self.project.tranus_project:
self.tranus_folder.setText(self.project.tranus_project.path)
self.activate_launch_button()
self.launch_options_TRANUS()
super(OptionsTRANUSDialog, self).show()
def select_tranus_folder(self):
folder = QtGui.QFileDialog.getExistingDirectory(self, "Select directory")
if folder:
self.tranus_folder.setText(folder)
if not self.project.load_tranus_folder(folder):
self.tranus_folder.setText('')
self.reload_scenarios()
self.activate_launch_button()
I really want that the command link button should be activated when at least one element of treeview is checked and to be inactive if there is no element checked.
Thanks.
Finally, I found solution to all my problems :
def activate_launch_button(self):
model = self.scenarios.model()
model.itemChanged.connect(self.check_configure)
def check_configure(self,item):
model = self.scenarios.model()
index = model.indexFromItem(item)
if index.data(QtCore.Qt.CheckStateRole) != index.data(QtCore.Qt.UserRole + QtCore.Qt.CheckStateRole):
if index.data(QtCore.Qt.CheckStateRole)!= QtCore.Qt.Unchecked :
self.count_check+=1
model.setData(index,index.data(QtCore.Qt.CheckStateRole),QtCore.Qt.UserRole + QtCore.Qt.CheckStateRole)
else :
self.count_check-=1
model.setData(index,index.data(QtCore.Qt.CheckStateRole),QtCore.Qt.UserRole + QtCore.Qt.CheckStateRole)
print self.count_check
self.launch_btn.setEnabled(self.count_check>0)
Finally, I found a partial solution to my problem, I used the signal itemChanged http://pyqt.sourceforge.net/Docs/PyQt4/qstandarditemmodel.html#itemChanged
def activate_launch_button(self):
model = self.scenarios.model()
model.itemChanged.connect(self.check_configure)
def check_configure(self):
self.launch_btn.setEnabled(True)
It activates the button when there is one element is checked however when I uncheck all, the button doesn't become inactive. How can I solve this issue ?
I am very new to PyQt, so I am not even sure where to start searching for this.
So I have two different options for QRadioButtons which ideally will correspond to two QPushButtons, one each.
Basically, I have the following code, where i tried to achieve this by using if statements:
def tab1UI(self):
mytabfont = QFont('Lucida Sans Unicode', 9)
layout = QFormLayout()
#self.setTabText(0,"My Data")
self.tab1.setLayout(layout)
tabdescription = 'To obtain or generate data choose an option below:'
# radio options
label1 = QLabel(tabdescription)
label1.setFont(mytabfont)
layout.addWidget(label1)
radiobtn1 = QRadioButton('Load data from file')
radiobtn1.setChecked(True)
#why does my resize not work?
radiobtn1.resize(100,100)
radiobtn1.setFont(mytabfont)
layout.addWidget(radiobtn1)
loadbtn = QPushButton('Open CSV file...')
layout.addWidget(loadbtn)
radiobtn2 = QRadioButton('Generate data')
radiobtn2.setFont(mytabfont)
genbtn= QPushButton('Generating matrix...')
layout.addWidget(radiobtn2)
layout.addWidget(genbtn)
if radiobtn1.isChecked():
# if this option is clicked then this button needs to be activated else it must be de-activated
loadbtn.setEnabled(True)
genbtn.setEnabled(False)
elif radiobtn2.isChecked():
loadbtn.setEnabled(False)
genbtn.setEnabled(True)
else:
loadbtn.setEnabled(False)
genbtn.setEnabled(False)
So, whenever I click one radio-button option I would like one pushbutton to become automatically active or inactive when the other option is checked instead.
There must be some sort of Action to be connected but not sure how to go about this.
You're only running the if statement once, when the buttons are first created. In order for this to work, you need to evaluate those if statements every time the radio button check state is changed. Qt allows you to do this with Signals and Slots. The QRadioButton will emit a signal when you change the check state. You can connect to this signal and run a function that updates the enabled state of the other buttons.
def tab1UI(self):
mytabfont = QFont('Lucida Sans Unicode', 9)
layout = QFormLayout()
self.tab1.setLayout(layout)
tabdescription = 'To obtain or generate data choose an option below:'
# radio options
self.label1 = QLabel(tabdescription)
self.label1.setFont(mytabfont)
layout.addWidget(self.label1)
self.radiobtn1 = QRadioButton('Load data from file')
self.radiobtn1.setChecked(True)
self.radiobtn1.setFont(mytabfont)
layout.addWidget(self.radiobtn1)
self.loadbtn = QPushButton('Open CSV file...')
layout.addWidget(self.loadbtn)
self.radiobtn2 = QRadioButton('Generate data')
self.radiobtn2.setFont(mytabfont)
self.genbtn= QPushButton('Generating matrix...')
layout.addWidget(self.radiobtn2)
layout.addWidget(self.genbtn)
self.radiobtn1.toggled.connect(self.refresh_button_state)
self.radiobtn2.toggled.connect(self.refresh_button_state)
self.refresh_button_state()
def refresh_button_state(self):
if self.radiobtn1.isChecked():
self.loadbtn.setEnabled(True)
self.genbtn.setEnabled(False)
elif self.radiobtn2.isChecked():
self.loadbtn.setEnabled(False)
self.genbtn.setEnabled(True)
else:
self.loadbtn.setEnabled(False)
self.genbtn.setEnabled(False)