Getting values from multiple GTK spinboxes - python

Image: http://dl.dropbox.com/u/4900888/GUI.png
Source and UI is in comments, due to "New-user-limiations"
I'm sorry if I've totally misunderstood what this site is about, but I have a problem.
When the button in the lower left corner is pressed, I want to get the values from the three spinboxes and save the as variables for use in a function that is triggered by the button.
I'm really blank as to how you would do this.
Any help is appreciated, and additional information can be supplied if it needs to.
EDIT:
I am using Python, and Gtk+ through Glade.
PS:
Does Stack Overflow have any code sharing site prefferences such as pastebin and so on?

The short answer is: with the spin button's get_value_as_int() method.
I suspect, however, that your actual problem is getting a reference to the spin button to call get_value_as_int() on. From your code I see that you are using gtk.Builder to build your UI.
Accessing widgets
Keeping a reference to specific widgets in Handler instance:
handler = Handler()
builder = Gtk.Builder()
...
# Store references to widgets in `handler`
for widget_name in ('sbtn_days', 'sbtn_hours', 'sbtn_minutes'):
setattr(handler, widget_name, builder.get_object(widget_name))
# The above is equivalent to the following:
handler.sbtn_days = builder.get_object('sbtn_days')
...
# In signal handling code:
days = self.sbtn_days.get_value_as_int()
Or you can keep a reference in to builder in your Handler instance:
builder = Gtk.Builder()
handler = Handler()
handler.builder = builder
...
# In signal handler code:
sbtn_days = self.builder.get_object('sbtn_days')
days = sbtn_days.get_value_as_int()
Notes
In the code above,
I assumed that your spin button for days is named sbtn_days. Adjust as necessary.
I only demonstrated accessing sbtn_days and its value. The other buttons can be accessed in a similar way.
P.S. There are a bunch of other problems with your code keeping it from being "good".

Related

Python3.8 with PySide2 Class to Class Usage

My GUI essentially wraps various backend PowerShell scripts that perform some automated functions. Kind of beside the point, but alright, here's where I'm stuck at.
I've got my interface designed in Qt Designer, outputted to a .ui file, converted to a .py file via PySide2-UIC, and a mainwindow class that is a subclass of the main window class I created in Qt Designer. All is well. No issues with any of that.
I'm now on to a part in my programming that I'm capturing form data from QWidgets (which is working) to a list. I've got a completely custom written class that is meant to handle taking that user input, setting other variables like filenames or paths to certain configuration files that are needed, and executing a subprocess PowerShell command with all of that information. Where I'm stuck at is trying to determine what the right place is to instantiate this custom object, inside my MainWindow class, outside my MainWindow class? But if so, where? Here's some simplified code to help explain my dilemma.
Interface Sequence
App start
MainWindow appears
User browses to form with input controls
User enters info like (IP address, username, password)
User clicks button that is connected to a method in the class
Method recurses through the child widgets on the page and captures info into a dictionary via finding qLabels and qLineEdit (buddies)
Questions:
How do I call the next method (only once even though the capturing of data is recursive)? I'm thinking about just connecting the signal to a second method that handles taking the captured data and sending/setting it into the custom class object. However, when I instantiate my custom object inside of the MainWindow class and I try to reference the object by self.customObject.sendUsesrInput(self.userInputVariable), PyCharm doesn't think self is defined inside this particular method. It doesn't properly highlight the word "self" like in the rest of the class definition, and it suggests that I need to import self.
Update
I was able to clear the errors around "import self" in PyCharm. It had something to do with improper spaces vs. tabs, even though I only ever use the tab key to do indentation. Might need to go and check my inpection settings closer. The other questions still stand though. Where is the best place to call methods on my custom class to "form a command", and "run a command", should that be executed by the mainWindow class, or should I set a flag on the customObject class that then triggers those other actions? Or more generally, should an object be in charge of executing it's own functions/methods, something tells me not usually, but I can't be sure. Also, if there are any books on the matter, I'd be happy to do my own research. I'm currently reading "Rapid GUI Programming" but not sure if this topic is covered in the later chapters just yet.
So I guess my question is, where do I handle the customObject class, in the mainWindow class, or in some other place? If so, where?
I apologize if this question is NOT clear. I promise to update as necessary to help work through this.
Here's come simplified code examples:
class customClass(object): # this is actually in a separate file but for argv sake
def __init__(self):
self.userInput = ""
self.file1 = ""
self.file2 = ""
self.otherstuff...
def setUserInput(self, uinput):
self.userInput = uinput
def dostuffwithdata(self):
# method to execute subprocess command
class MainWindow( QMainWindow ):
def __init__(self):
super(MainWindow, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.customObject = customClass.customCmdClass()
self.cmddata = dict()
self.ui.toolButton.clicked.connect(self.getformdata)
def getformdata(self):
# recurses through QWidgets and grabs QLabels and QLineEdit.Text() and updates dict()
for w in widgets:
if w is qlabel:
k = w.text()
v = w.buddy().text()
self.cmddata.update({k: v})
""" all the above works fine. what doesn't work is this part"""
# at this point I want to send the collected data to the customObject for processing
def senddatatocustomObject(self):
self.customObject.setUserInput(self.cmddata) """but this says that 'self' isn't defined.
I know it has to be because of the object in an object, or something I'm doing wrong here.
**Update**: figured this out. PyCharm was freaking out about some sort of
perceived indentation error despite there not appearing to actually be one.
Was able to correct this. """
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec_())
In an effort to close this out, I offer this answer to my previously posted question about where to put the "logic" and flow in my code.
Given that this is a graphical application without any back-end services, it makes the most sense to put most of the user-interaction logic and flow within the MainWindow object because that is essentially the control center of my program. When a user clicks or enters something, it is going to happen on the MainWindow, when a state changes, it happens (mostly) on the MainWindow or is directly tied to the MainWindow in some way. Therefore, it makes sense to include the majority of my method calls, user-input-flow logic, and other code, in the MainWindow class/object of my program.
My other classes and objects are there to capture state and to perform actions on different sets of data, but in most cases, these auxiliary classes/objects will/should be controlled by the MainWindow of my application.
This is certainly not the only way to write this application or others, but I believe this at least answers my previously posted question(s).

Kivy add widget from thread

I am trying to add a widget to the screen via a thread. This is the function I am calling from within the thread:
#mainthread
def add_message(self, text):
message_lab = Label(text=text, markup=True)
message_lab.text_size = message_lab.width, None
self.add_widget(message_lab)
When I run this, I can see that the widget has been added into the children variable of the layout, but it does not show up. When I tried to make a small segment of code, it worked. However, I still don't know what the problem is. Any help I could get would be greatly appreciated!

kivy find all TextInputs

I was trying to register all TextInputs and Spinner in my GUI.
Each of these does have a variable gid.
The problem with the root_widget.walk() method is that I have different tabs and it does not load the widgets that have not been displayed yet.
However this is not my biggest problem.
The thing is that the walk()method does only show Widgets and not TextInputs nor Spinner.
My question now is: How do you traverse EVERY object (TextInputs/Spinner etc.) including those that have not been displayed yet (in a different tab)
I am very happy for any kind of help or advice.
Greetings, Finn
The walk() widget method does visit all child widgets (including TextInput and Spinner. If you are using TabbedPanel as your root widget, then the following will register all your widgets (if it is called by a binding to on_draw):
registered = False
def on_draw(*args):
global registered
if registered:
return # just to avoid running this many times
registered = True
app = App.get_running_app()
for tab in root_widget.tab_list: # assumes root_widget is a TabbedPanel
if tab.content is not None:
for widget in tab.content.walk():
app.register_widget(widget)
A similar construct could be done if you are using a ScreenManager as your root widget.

How to open a popup window with a spinner in python + Gtk

I have a python Gtk application, with the GUI designed in Glade. It has a "scan" feature which will scan the network for a few seconds and then report its results to the user. During the scanning I want a popup window to appear stealing the focus from the parent until scanning is done.
I use a threading.Lock to synchronize the GUI and the scan thread, which makes the popup to last exactly the right time I want (see scanLock.acquire() ). It seems straightforward to me to implement something like a show() and hide() call before and after the scanLock.acquire(). I did use waitPopupShow and waitPopupHide instead of just calling the window.show() and window.hide() because I also may want to set the Label in the popup or start/stop the GtkSpinner. Here is some code from the GUI class:
def scan(self):
sT = scannerThread(self,self.STagList)
self.dataShare.threadsList.append(sT)
sT.start() # start scanning
self.waitPopupShow('Scanning... Please Wait')
self.scanLock.acquire() # blocks here until scan is finished
self.waitPopupHide()
def waitPopupShow(self, msg): # shows a GtkSpinner until the semaphore is cleared
self.waitDialogLabel.set_text(msg)
self.waitDialogBox.show_all()
self.waitDialog.show()
self.waitDialogSpinner.start()
def waitPopupHide(self):
# how to get the handle to the spinner and stop it?
self.waitDialogSpinner.stop()
self.waitDialog.hide()
def getAll(self):
# GUI
self.builder = Gtk.Builder()
self.builder.add_from_file(path to main GUI)
# ... getting stuff from a first glade file
# getting stuff from the waitDialog glade file
self.builder.add_from_file(path to waitDialog GUI)
self.waitDialog = self.builder.get_object("waitDialog") # GtkWindow
self.waitDialogBox = self.builder.get_object("waitDialogBox") # GtkBox
self.waitDialogLabel = self.builder.get_object("waitDialogLabel") # GtkLabel
self.waitDialogSpinner = self.builder.get_object("waitDialogSpinner") # GtkSpinner
self.waitDialog.hide()
I'm trying hardly since a couple of days to show a dialog with a label and a Gtk.Spinner. The best I obtain at the moment is to have the window showing up with no content. Please note that the self.waitDialog.hide() right after getting it with self.builder.get_object is needed because I set the property of the waitDialog Gtkwindow to Visibile. If I stop with the debugger before .hide() the waitDialog shows up perfectly. Afterwards its broken.
This is the waitDialog GUI file: http://pastebin.com/5enDQg3g
So my best guess is that I'm dooing something wrong, and I could find nothing on creating a new Gtk window over the main one, only basic examples and dialogs. A pointer to the documentation saying a bit about this would be a good starting point...

Rebuild interface to change the language (GTK)

I am beginning to work on a program in which i want multilingual support, but since it is pretty modular (and i want it to be even more in the future), a language change means "destroy what you had of interface and build again with the content which language modules have". (You can see the source as of now on GitHub)
This full-modular approach may give many problems, but i still want it, and so the problem is: Whenever i destroy the widgets i had, until i am alone with the raw Gtk.Window itself, i am not able to assign once again widgets to it. They won't get displayed at all, sometimes silently, sometimes with errors depending on my approach.
Lets suppose the class window, which inherits from a Gtk.Window.
This class is the raw window, and i assign to it a Gtk.Box -
self.interface.
self.interface itself, has two Gtk.Box's, one sidebar and one stack of contents.
To rebuild i tried to:
Change the language variable
Use the method destroy on self.interface, which removes the widget and its child's.
Reuse the function to build the widgets stack on top of self.interface
Re-add self.interface to self (window).
This approach returns:
g_object_unref: assertion 'G_IS_OBJECT (object)' failed
Gtk.main()
Pointing to the .show_all() method in this file.
I've already tried to leave interface without using .destroy on it, applying only on its child's, and then creating them again over it, but didn't worked. The window was left blank with no error at all.
The code i am trying right now is:
#Remember, self is a Gtk.Window()
def __init__(self):
[...]
self.interface = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
self.stack = None
self.add(interface)
self.build_interface()
def build_interface(self):
self.interface.pack_start(
self.create_side_navigation(
self.interface_data["menu"][self.language]["name"])
, False, False, 0
)
self.stack = self.create_content_stack(self.interface_data["menu"][self.language])
self.interface.pack_start(self.stack, True, True, 0)
###Code to rebuild(this is a question dialog):
if response == Gtk.ResponseType.OK:
self.language = self.new_language["Index"]
self.new_language = None
self.stack.destroy()
self.interface.destroy()
self.interface = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
self.build_interface()
self.add(self.interface)
This code will cause the previously told "g_object_unref" error.
What is causing this? Why can't i add anything once deleted?
Feel free to clone the repo and try, the code is well commented(yet i am not sure if poorly written, i am a python newbie) and its quite easy to understand where is the problematic part. Its not too big.
PS: It should need GTK+3.12 because of the popovers.
As a GTK Dev showed to me, GTK has by default all the widgets invisible.
The error was caused in the line which declared the whole interface visibility (windowclass.show_all()), but since the interface changed since when it was applied, it threw that warning.
He pointed me to .remove() instead of .destroy(), and to set .show_all() to the new elements after set up.
The next commit(or the following) on that git, has the solution.
The best way to be multilingual is to keep your widgets the same and merely change the text of labels and titles. This can be done without disturbing the overall setup. For example:
s='Stop'
if lang=='fr': s='Arret'
...
somelabel.set_label(s)

Categories

Resources