How to record multiple checkboxes in wxPython? - python

I am trying to get my program to record if the user clicked on checkbox(es) so I know what things to delete. The problem is that I don't have all the variables names for all the checkboxes so I can't just do GetValue(). In the code below, I have a set number of things but in the actual program, it pulls user info from file.
import wx
class supper(wx.Frame):
def __init__(self,parent,id):
wx.Frame.__init__(self,parent,id,'Delete Stocks',size=(300,300))
nexus=wx.Panel(self)
again=30
newfp='GOOG AAPL'.split()
#Need to see if user checked box and which one
for i in newfp:
self.checkbox=(wx.CheckBox(nexus,-1,i,(30,again),(160,-1)))
self.Bind(wx.EVT_CHECKBOX, self.lol,self.checkbox)
again+=30
anothercancel=wx.Button(nexus,label='Cancel',pos=(50,250),size=(60,40))
self.Bind(wx.EVT_BUTTON,self.acancel,anothercancel)
anotherok=wx.Button(nexus,label='OK',pos=(200,250),size=(60,40))
self.Bind(wx.EVT_BUTTON,self.okalready,anotherok)
def acancel(self,event):
self.Destroy()
#Couldn't figure out how to see what check was clicked
def okalready(self,event):
for i in newfp:
valuechecker=self.checkbox.GetValue()
if self.checkbox.Get()==True:
print 'You clicked this %s one'%i
self.Destroy()
def lol(self,event):
pass
if __name__=='__main__':
ok=wx.PySimpleApp()
people=supper(parent=None,id=-1)
people.Show()
ok.MainLoop()
This isn't the whole thing so there might be a variable that is not defined here. Thanks in advance! Look forward to the answers!

just keep them in a list ...
self.checkboxes = []
for i in newfp:
self.checkboxes.append(wx.CheckBox(nexus,-1,i,(30,again),(160,-1)))
self.checkboxes[-1].Bind(wx.EVT_CHECKBOX, self.lol)
again+=30
then to check which boxes are checked when you click ok you can use this
def okalready(self,event):
for i,cb in enumerate(self.checkboxes):
print "CB:%d = %s"%(i,cb.GetValue())
print "Checked:",[cb.GetLabel() for cb in self.checkboxes if cb.GetValue()]
self.Destroy()

Related

gradio refresh interface when selecting File

I'm trying to create a gradio User Interface which does the following
on the left panel I have a File control, that allows the selection of a local file (eg. a .csv)
when a file is selected a "Process" button should be made visible
when the "Process" button is pressed, a function is called, reading the contents of the file, and processing it in some ways, resulting in a string
the resulting string is shown in a TextArea in the right column
I'm stuck implementing point 2. I can select the file, but can't make the Process button become visible.
This is my code so far (not yet implementing points 3. a:
import gradio as gr
def file_selected(file_input):
print("yes, file_selected is invoked")
print(process_button)
process_button.visible=True
demo.render()
return process_button
with gr.Blocks() as demo:
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("### Data")
file_input = gr.File(label="Select File")
process_button = gr.Button("Process", visible=False)
with gr.Column(scale=2, min_width=600):
gr.Markdown("### Output")
result_display = gr.TextArea(default="", label="Result", lines=10, visible=False)
file_input.change(fn=file_selected, inputs=file_input, outputs=process_button)
if __name__ == "__main__":
demo.launch()
I see that at file selection the message is printed (and print(process_button) prints "button" so I'm sure this variable is not None), but the button doesn't appear on the page.
edited: fixed some errors not directly related to the problem.
There were many problems with the code (I fixed those not related with the main issue in the original post), but in the end what solved my problem (making the button visible) was that instead to rerender,
def file_selected():
...
process_button.visible=True
demo.render()
I just had to return the process_button.update
def file_selected(file_input):
...
return gr.update(visible=True)
(Actually this was documented in gradio's online docs; sorry, I didn't notice it before)
This is the complete working code:
import gradio as gr
def file_selected(file_input):
print("yes, file_selected is invoked")
print(process_button)
return gr.update(visible=True)
with gr.Blocks() as demo:
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("### Data")
file_input = gr.File(label="Select File")
process_button = gr.Button("Process", visible=False)
with gr.Column(scale=2, min_width=600):
gr.Markdown("### Output")
result_display = gr.TextArea(default="", label="Result", lines=10, visible=False)
file_input.change(fn=file_selected, inputs=file_input, outputs=process_button)
if __name__ == "__main__":
demo.launch()

How to shared data between instances classes (backend) and Kivy graphical elements (frontend)?

I'm a beginner with Kivy and I'm trying to create gui for a python app.
I have a backend programmed in python, working alone (keyboard as input) and now I want frontend with kivy. I have two questions:
- How can I run both components (back and front end) at once?
- How can I share objects of existing classes in my backend to display information in the frontend (kivy)?
classtest.py
class Test(object):
def __init__(self, attr):
self.attr = attr
gui.py
class LoginScreen(GridLayout):
def __init__(self, **kwargs):
super(LoginScreen, self).__init__(**kwargs)
self.cols = 2
self.add_widget(Label(text='User Name'))
self.username = TextInput(multiline=False)
self.add_widget(self.username)
self.add_widget(Label(text='password'))
self.password = TextInput(password=True, multiline=False)
self.add_widget(self.password)
print self.username.text
class Login(App):
def build(self):
Window.borderless = True
return LoginScreen()
main.py
import classtest, gui
users = ['user_name1', 'user_name2', 'user_name3']
gui.Login().run()
for u in users:
test = classtest.Test(u) # this should update the user text field on the windows login automatically, but how?
In example, How can I update an element of the login window when an instance attribute value change?
Thanks many many times!
It won't update because... of a loop :P Kivy for each App().run() or a similar "run" command launches a loop and your:
for u in users:
test = classtest.Test(u)
is written after that loop. So basically it won't even execute while your app is running. Just put print('something') into that for loop and you'll see.
Example:
while True:
<do something>
<change a variable in that loop> # == nope
Which for you means that you need either:
write that into gui.py file or
set those things right in the classtest.py
The second option also depends when you use the class. If outside of the main loop, then you are in the same situation as right now, therefore - use that Test() inside of gui.py.
You won't be able to use any code after run() while the app is running. Maybe with some dirty trick, but that will bring you only troubles. The code you wrote could be used in some "cleaning", which you can also do in App.on_stop method(inside main loop).

PyQt: most efficient delete sql query

I'm using pyqt4, qt designer and postgresql database. I've managed to make part of my GUI which inserts new data to my db, but now I'd like to try something else for my Delete section of GUI. Since I'm into python/pyqt for maybe a week now I'll try to explain what I'm looking for as simple as possible. First off: here is part of my code which I used for adding data:
...
class database_GUI(QtGui.QWidget, Ui_Main_GUI_Widget):
def __init__(self):
QtGui.QWidget.__init__(self)
self.setupUi(self)
self.Add_button.clicked.connect(self.open_sub_ui)
def open_sub_ui(self):
if self.Add_comboBox.currentText() == "kirurg":
global kirurg
kirurg = kirurg_GUI()
kirurg.show()
...
class kirurg_GUI(QtGui.QWidget, Ui_kirurg_Widget):
def __init__(self):
QtGui.QWidget.__init__(self)
self.setupUi(self)
self.kirurg_Add_button.clicked.connect(self.insert_kirurg)
def insert_kirurg(self):
oib_kir = self.kirurg_oib_kir_lineEdit.text()
if not oib_kir:
QtGui.QMessageBox.critical(self, 'Query error', 'oib_kir must not be empty')
else:
query = QSqlQuery()
status = query.exec("INSERT INTO kirurg (oib_kir, prezime, ime, adresa, broj_telefona)"
"VALUES ('%s', '%s', '%s', '%s', '%s')" % (''.join(self.kirurg_oib_kir_lineEdit.text()),
''.join(self.kirurg_prezime_lineEdit.text()),
''.join(self.kirurg_ime_lineEdit.text()),
''.join(self.kirurg_adresa_lineEdit.text()),
''.join(self.kirurg_broj_telefona_lineEdit.text())))
if status is not True:
errorText = query.lastError().text()
QtGui.QMessageBox.critical(self, 'Query error', errorText)
So basically, new GUI would open for every other comboBox option. If user selects comboBox option 1 and clicks Add, it opens GUI for adding data to table number 1, if user selects comboBox option 2 and clicks Add, it opens GUI for adding data to table number 2, and so on.
But, I'd like to be more flexibile with my Delete GUI so I was wondering is it possible to make something like this:
query.exec("DELETE FROM ('%s') WHERE ('%s) = ('%s'))
These ('%s') things should be strings, which my program would read from lineEdit.text(). So basically, program would read data that user enters in lineEdit and according to them it would know which row of data to delete and from which table. I hope you can see my point and question here. If it's not possible, I guess I'll just make another 12 copy pasted GUI's for each table, but I'm hoping there's better solution to that.

Handling delete event in pygtk/glade

I have a GUI designed in glade, using python/gtk in the background.I want to handle the delete event and display a "Are you sure?"-message dialog.I have been trying to handle the delete and destroy events, but failing to do so.any light?
#!/usr/bin/python
import .... stuff
class App:
def __init__(self):
self.gladefile = 'test.glade'
windowname = 'window'# This must match the window name in glade
self.wTree = gtk.glade.XML(self.gladefile, windowname)# object for acessing widgets
dic={
# Also need to set project2's signal tab
'on_window_delete_event':self.on_erro,
'on_window_destroy_event':self.on_erro,
}
self.wTree.signal_autoconnect (dic)
self.op=self.wTree.get_widget('window')
self.op.show()
def on_erro(self,widget,*args):
print 'hello'
app = App()
gtk.main()
This code opens a simple window .On clicking on close button, it prints hello and exits.(I want the window to remain open)
You have to return True in order to stop propagation of the delete event in the callback on_erro as mentioned in the documentation for "delete-event". In your current code, the callback is not returning any boolean value as required by the function, which I am guessing is returning False (Please check the signature for on_window_delete_event callback functions, the return type is boolean)
Hope this helps!

Simple, versatile and re-usable entry dialog (sometimes referred to as input dialog) in PyGTK

I am searching for a simple dialog with a text entry widget asking the user for some input. The dialog should be easy to run (like the gtk.MessageDialog variants) and as flexible.
There are of course some examples but they are either not flexible enough or too complicated to construct for my taste.
I hate re-inventing the wheel... or a dialog.
Based on an example I found (thanks Ardoris!), I came up with a dialog subclass... hope it helps someone out there!
#!/usr/bin/env python
import gtk
class EntryDialog(gtk.MessageDialog):
def __init__(self, *args, **kwargs):
'''
Creates a new EntryDialog. Takes all the arguments of the usual
MessageDialog constructor plus one optional named argument
"default_value" to specify the initial contents of the entry.
'''
if 'default_value' in kwargs:
default_value = kwargs['default_value']
del kwargs['default_value']
else:
default_value = ''
super(EntryDialog, self).__init__(*args, **kwargs)
entry = gtk.Entry()
entry.set_text(str(default_value))
entry.connect("activate",
lambda ent, dlg, resp: dlg.response(resp),
self, gtk.RESPONSE_OK)
self.vbox.pack_end(entry, True, True, 0)
self.vbox.show_all()
self.entry = entry
def set_value(self, text):
self.entry.set_text(text)
def run(self):
result = super(EntryDialog, self).run()
if result == gtk.RESPONSE_OK:
text = self.entry.get_text()
else:
text = None
return text
The run() method returns either the text entered in the entry box if the user presses <Enter> or clicks Ok. If Cancel is clicked or <Esc> pressed, the run() method returns None.
Except for that, the dialog should behave as any other gtk.MessageDialog instance.
Maybe that is not very general as it assumes you will always have Ok as an option, but that is what I need in 99% of my use cases anyway.
There isn't one available in GTK+. You've got two options:
Create a dialog, pack the Entry and any other content you need (probably the best way in my opinion)
Retrieve the content_area of the MessageDialog and append an Entry to it.
Something along the lines of:
#!/usr/bin/env python
import gtk
messagedialog = gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_QUESTION, buttons=gtk.BUTTONS_OK, message_format="Hello")
action_area = messagedialog.get_content_area()
entry = gtk.Entry()
action_area.pack_start(entry)
messagedialog.show_all()
messagedialog.run()
messagedialog.destroy()
Though it does probably need more refinement to get the Entry to display nicely.
Here's the function I wrote, based on the previous answers here. It's a function instead of a class, which means you can use it in one line.
def get_text(parent, message, default=''):
"""
Display a dialog with a text entry.
Returns the text, or None if canceled.
"""
d = gtk.MessageDialog(parent,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
gtk.MESSAGE_QUESTION,
gtk.BUTTONS_OK_CANCEL,
message)
entry = gtk.Entry()
entry.set_text(default)
entry.show()
d.vbox.pack_end(entry)
entry.connect('activate', lambda _: d.response(gtk.RESPONSE_OK))
d.set_default_response(gtk.RESPONSE_OK)
r = d.run()
text = entry.get_text().decode('utf8')
d.destroy()
if r == gtk.RESPONSE_OK:
return text
else:
return None

Categories