Kivy add widget from thread - python

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!

Related

Continue a code after calling a class method which opens a tkinter window

I have created a class "Node" which creates a binary tree. (I know i can use binarytree module but its a project given to me in DSA subject.)
class Node:
def __init__(self, data) -> None:
#initialisation
def addNode(self, data):
# Code to add data.
def traverse(self):
#traverses the tree and returns a dict
def view(
self,
length=500,
width=1000,
yDist=50,
xDistScale=0.25,
title='Tree View',
):
# shows the tree in a tkinter window as in the screenshot attached
tree = self.traverse()
root = tk.Tk()
self.root=root
root.geometry(str(width)+'x'+str(length))
root.title(title)
# ........ some code which places the nodes on the window using the place() method
root.mainloop()
Now, I import the code in an another file, create an instance of the class add some nodes and call the view() method it works fine but the code after the view() methd does not run till I close the tkinter window.
How can I make the code after view() run without the window being closed?
Its ok if the window is not able to update.
Code where I import and use the node class :
t1 = Node(15)
t1.addNode(12)
t1.addNode(27)
t1.addNode(7)
t1.addNode(14)
t1.addNode(20)
t1.addNode(88)
t1.addNode(23)
t1.view()
# The code here does not run until I close the window.
Output of the above code :
Link to image
I tried googling and also viewed following stackoverflow posts:
Calling a tkinter application from a different class in python,
A code needs to be continued...(Python with Tkinter)
How would I continue to run code after importing a Tkinter file?
Few other websites and guides...
But nothing was helpful.
Please help/guide me.
I am new to StackOverflow and Python.
Thanks in Advance :)
Method 1: Don't update window
You could replace the root.mainloop() with root.update(). This will stop showing any changes to the window. The window will only and always close if the program stops running.
Method 2: using threading
You could useimport threading to run t1.view() in another thread: threading.Thread(target=t1.view).start(). This may result in a Tcl_AsyncDelete error.

How do I call a function when the screen is rotated?

Problem
I am building in app (with Kivy) which renders some custom widgets to the screen. Unfortunately, their positions (relative to other widgets) changes when the tablet on which I am running the app is rotated. Now I have built a function that repositions them, and I would like to call this function when the tablet is rotated. How can I implement this?
My attempts so far...
I have seen from the Kivy documentation that the Window class has an on_rotate event, and have tried to incorporate this into my program in several different ways.
First, I tried implementing the callback after the if __name__ == '__main__' statement. Something like:
if __name__ == '__main__':
app = MainApp()
Window.on_rotate = lambda: app.reposition_widgets()
app.run()
That did nothing. In vain I also tried:
if __name__ == '__main__':
app = MainApp()
Window.on_rotate(app.reposition_widgets)
app.run()
I then attempted to bind the widgets to on_rotate events, something like:
class CustomWidget(Widget):
def __init__(self, **kwargs)
super().__init__(**kwargs)
self.bind(on_rotate = self.reposition_widgets)
That did nothing. Neither did:
class CustomWidget(Widget):
def __init__(self, **kwargs)
super().__init__(**kwargs)
on_rotate = reposition_widgets
My final attempt was to create a Window class in the accompanying kv file and the Python file, then specify the on_rotate event from there. Something like:
#kv file
Window:
on_rotate: app.reposition_widgets()
That didn't work either.
Possible work around
To be honest, rotating the screen is not all that useful for my app, and so it wouldn't be all that bad if I just disabled screen rotation. However, I was not able to find a good way of doing so in the documentation. Do you know how I would go about doing this?
Binding the widgets to the on_pos event - or something similar. Something like:
class CustomWidget:
def reposition_widgets():
# Code here
on_pos = reposition_widgets
The problem with this is that the widgets move about a lot, which means that the function gets called a lot - causing problems elsewhere.
Let me know if you would like to see more code. I have over 1000 lines spread over several files, and felt that just copy-and-pasting wouldn't be particularly useful.
I was able to solve this issue using the on_size event.
class CustomWidget(Widget):
def reposition_widgets(self):
# Reposition logic here
on_size = reposition_widgets
This worked quite well actually. I added an additional parameter in the reposition_widgets function to differentiate between when I was repositioning because of on_size and when I was repositioning because I was calling it (see example below). However, this is not always necessary.
class CustomWidget(Widget):
def reposition_widgets(self, rotation=False):
if rotation:
# When function is called due to on_size
else:
# When function is called in code
on_size = lambda self, *args: self.reposition_widgets(rotation=True)

Maya UI not docking after rerunning script

I have made a UI window for Autodesk Maya 2015. Every time I run the script within Maya's script editor, it works fine, the UI gets launched and it docks properly on the main Maya window.
However, after closing the UI window and rerunning the script, the window doesn't dock anymore. It gets stuck on the main screen and I have to close the whole software. It seems that the UI can't find the main Maya Window anymore after I close it the first time round. I'm not sure how to fix this. Can anyone give me some advice on how to fix this problem?
Here is my code:
def getMayaWindow():
ptr = apiUI.MQtUtil.mainWindow()
if ptr is not None:
return shiboken.wrapInstance(long(ptr), QtGui.QMainWindow)
class pipeWindow(formClass,baseClass):
def __init__(self, parent=getMayaWindow()):
super(pipeWindow,self).__init__(parent)
self.setupUi(self)
self.setObjectName('pipe_window')
try:
cmds.deleteUI('dockPane')
except:
pass
self.pane = cmds.paneLayout('dockPane', cn='single')
if 'pipeDock' not in cmds.lsUI(ctl=1) :
cmds.dockControl('pipeDock', con=self.pane, area='right',
allowedArea = ['right','left'], label =
"ANMD_Pipeline", w=365)
else:
pass
cmds.control( 'pipe_window', e=True, p=self.pane)
After trying out multiple things, I have managed to resolve this issue. I have used
if cmds.dockControl('pipeDock', q=1, ex=1):
cmds.deleteUI('pipeDock')
Then I have a super(className, self).closeEvent(event) inside a closeEvent function. This did the trick for me. This did the trick for me. Previously I had the cmds.deleteUI within my closeEvent function which did not work, I suspect it was because I did not close the Event itself, so the UI just hides itself whenever I press the cross button instead of deleting it.

Tkinter in Python - Remove widget from active window

I'm trying to remove a Tkinter progress bar widget from an active window (after the GUI window using Tkinter has been initialized). I'm using a Tkinter Frame for my window. I've initialized the progress bar as pb, as below.
pb = ttk.Progressbar(root,orient ="horizontal",length = 540, mode ="determinate")
And then I've tried two different methods to get rid of the progress bar. The line below causes the window to freeze and stop responding when I try to use it after the GUI is initialized.
pb.pack_forget()
The line below causes only a middle section of the progress bar to disappear, but you can still see the two sides of it.
pb.destroy()
Is there any way I could get this widget to disappear after the Frame has been initialized?
The specific answer to your question is that pack_forget, grid_forget or grid_remove are what you want if you want to make a widget temporarily invisible. Which one you choose depends on if you're using grid or pack, and whether or not you want grid to remember where it was so you can later put it back in the same spot.
destroy is what you want to call if you want to literally destroy the widget.
When used properly, none of those methods will cause your program to freeze. Without seeing your code, it's impossible to know what the root cause of the problem is.
Sorry for my bad English.
This code worked for me. I simply follow Oakley's instruction.
def progressBar(*args, **kwargs):
def progress(currentValue):
progressbar["value"] = currentValue
maxValue = 100
progressbar = ttk.Progressbar((kwargs), orient="horizontal", length=150, mode="determinate", takefocus=True)
progressbar.pack(side=tk.BOTTOM)
currentValue = 0
progressbar["value"] = currentValue
progressbar["maximum"] = maxValue
divisions = 10
for i in range(divisions):
currentValue = currentValue + 10
progressbar.after(500, progress(currentValue))
progressbar.update() # Force an update of the GUI
progressbar.destroy()
Hence I simply tried progressbar.destroy() outside of the loader loop. So after
complete the loading, it will disappear from the main App window.
Thank you, Bryan Oakley sir.

Getting values from multiple GTK spinboxes

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".

Categories

Resources