I am trying to create a chat server where multiple clients can connect to a server. I want to create a GUI in one module (say clientgui.py) which calls another module (say client.py) to connect to the server.
The problem is I have to call client.py when a certain button is clicked. But while doing so, the main loop never gets executed. For example,
app = Tk()
...
sendbutton = Button(text,height...., command = Client().senddata())
#This will call function of a different module.
....
app.mainloop()
Is it possible to call another module inside a "GUI loop"?
You are not assigning the function to command, but the result of senddata. Try this instead:
sendbutton = Button(text, height, ..., command = Client().senddata)
That should solve your problem. Notice how the senddata method has no parenthesis on it? That is because you don't want to call it right there, you want to talk about it. Since functions and methods are objects, it is ok to assign it to a parameter (e.g. command).
What your code was doing, was assign the result of calling Client().senddata() to the buttons command. I assume this doesn't return a function/method/callable object (but it could) and that instead you assign None, in effect making the button not do anything at all when clicked.
Related
I've created a GUI that ask the user an User/Password. The class that creates the GUI calls another class that creates a web browser and try to login in a website using a method of the same class. If the login is successful, a variable of the GUI's object becomes 'True'
My main file is the next one :
from AskUserPassword import AskGUI
from MainInterfaceGUI import MainGUI
Ask = AskGUI()
Ask = Ask.show()
MainInterface = MainGUI()
if Ask.LoginSuccesful == True:
Ask.close()
MainInterface.show()
If the login is successful, I would like to hide the User/Password GUI and show the main GUI. The code above clearly doesn't work.
How can I make Python to wait until some condition of this type is met ?
Instead of constantly checking for the condition to be met, why not supply what you want upon login to do as a callback to your AskGUI object, and then have the AskGUI object call the callback when login is attempted? Something like:
def on_login(ask_gui):
if ask_gui.LoginSuccesful:
ask_gui.close()
MainInterface.show()
Ask = AskGUI()
Ask.login_callback = on_login
Then, in AskGUI, when the login button is clicked and you check the credentials, you do:
def on_login_click(self):
...
# Check login credentials.
self.LoginSuccessful = True
# Try to get self.login_callback, return None if it doesn't exist.
callback_function = getattr(self, 'login_callback', None)
if callback_function is not None:
callback_function(self)
Re.
I prefer to have all the structure in the main file. This is a reduced example but If I start to trigger from a method inside a class that is also inside another class... it's going to be hard to understand
I recommend this way because all the code to handle something that happens upon login is included in the class that needs to do the logging in. The code to handle which UI elements to display (on_login()) is included in the class that handles that.
You don't need anything in the background that keeps checking to see if Ask.LoginSuccessful has changed.
When you use a decent IDE, it's pretty easy to keep track of where each function is defined.
I have a python program using eel library to build a nice GUI.
In the GUI I have a variable within a JS function that I need to pass to Python to store in a variable.
Any ideas why this is?
You can read the below Github article. Maybe this will help.
https://github.com/samuelhwilliams/Eel
Return values
While we want to think of our code as comprising a single application, the Python interpreter and the browser window run in separate processes. This can make communicating back and forth between them a bit of a mess, especially if we always had to explicitly send values from one side to the other.
Eel supports two ways of retrieving return values from the other side of the app, which helps keep the code concise.
To prevent hanging forever on the Python side, a timeout has been put in place for trying to retrieve values from the JavaScript side, which defaults to 10000 milliseconds (10 seconds). This can be changed with the _js_result_timeout parameter to eel.init. There is no corresponding timeout on the JavaScript side.
Callbacks
When you call an exposed function, you can immediately pass a callback function afterward. This callback will automatically be called asynchronously with the return value when the function has finished executing on the other side.
For example, if we have the following function defined and exposed in Javascript:
eel.expose(js_random);
function js_random() {
return Math.random();
}
Then in Python, we can retrieve random values from the Javascript side like so:
def print_num(n):
print('Got this from Javascript:', n)
# Call Javascript function, and pass explicit callback function
eel.js_random()(print_num)
# Do the same with an inline lambda as callback
eel.js_random()(lambda n: print('Got this from Javascript:', n))
(It works exactly the same the other way around).
Synchronous returns
In most situations, the calls to the other side are to quickly retrieve some piece of data, such as the state of a widget or contents of an input field. In these cases it is more convenient to just synchronously wait a few milliseconds then continue with your code, rather than breaking the whole thing up into callbacks.
To synchronously retrieve the return value, simply pass nothing to the second set of brackets. So in Python we would write:
n = eel.js_random()() # This immediately returns the value
print('Got this from Javascript:', n)
You can only perform synchronous returns after the browser window has started (after calling eel.start()), otherwise obviously the call with hang.
In Javascript, the language doesn't allow us to block while we wait for a callback, except by using await from inside an async function. So the equivalent code from the Javascript side would be:
async function run() {
// Inside a function marked 'async' we can use the 'await' keyword.
let n = await eel.py_random()(); // Must prefix call with 'await', otherwise it's the same syntax
console.log("Got this from Python: " + n);
}
run();
I am not skilled in Gtk programming and I am trying to modify some existing code so that the gobject.timeout_add() callback function can use data from another thread.
The existing code creates a GUI for displaying a DOT graph by periodically reading a file but I want the DOT data to be read from a string that can be obtained from a subscriber defined as follows:
import rospy
from std_msgs.msg import String
rospy.Subscriber('/dot_string', String, self.update_dot_graph)
def update_dot_graph(self, msg)
self.dot_string = msg.data
The rospy.Subscriber runs in its own thread and so it is unclear to me how to get access to self.dot_string when the Gtk.main() function appears to block any other code from running.
The existing GUI code defines the following callback for gobject.timeout_add():
def update(self):
if self.openfilename is not None:
current_mtime = os.stat(self.openfilename).st_mtime
if current_mtime != self.last_mtime:
self.last_mtime = current_mtime
self.reload()
return True
Here you can see that the DOT code is read from a file if it has changed since the last read and then the GUI window is reloaded. I would like instead to use the data in self.dot_string from the other thread to be used in this update function. Alternatively, I would like to trigger the data update and reload() directly in the update_dot_graph() callback that is attached to the other thread.
Please let me know if more details are needed for this to make sense.
I'm making a gui in python wich uses the serial port for sending commands. In my old script, without a gui, i used time.sleep(x) between the write commands (it is necessary for to commands to succeed). Now when i use a gui envrimont, i can't use sleep so i use after.
It works well, but:
I'm using Tkinter for my gui. When i press the button start , OnButtonClickSTART starts the other function after x time. With self.after i wait x secondes between every process. It works, but when i give a value with the function, it doesn't wait the given time.
def OnButtonClickSTART(self):
print "START"
self.button1.configure(state='disabled')
self.after(1000, self.waitmore)
def waitmore(self):
value = 5
print value
self.after(10000,self.waitmuchmore(value))
def waitmuchmore(self,value):
print value
self.after(10000,self.OnButtonClickSTOP)
def OnButtonClickSTOP(self):
print "STOP"
self.button1.configure(state='normal')
And isn't here a better way to execute a series of command , with a certain time between them. Like sleep, but works with 1 function and doesn't disable the gui.
Thx
Using self.waitmuchmore(value) will immediately call the waitmuchmore method. You need to use either a lambda expression or functools.partial to return a new function that will call waitmuchmore with value, and pass that to self.after instead:
lambda: self.waitmuchmore(value)
or
import functools
functools.partial(self.waitmuchmore, value)
So I have a small python program that is spread out across a few classes. In my main class, I tell my title screen class to display and then wait for input. If the input it gets is 'q' it calls back to my main class telling it to set it's stop flag to true. Otherwise, it just loops.
This is the callback I give to my title screen:
def quit():
stopped = True
stopped is set to False outside of the callback. The callback is registered fine, and goes off no problem, but it seems to set stopped to true locally in titlescreen, and not in main. I can fix this by creating a class stopFlag and doing the exact same thing, except in the object.
My question is why do I need to make a new class to do this? Is there a way I can set a global flag in main which is just a boolean without making an object out of it? How can I have the callback reference that boolean?
Edit:
I declare stopped like this:
stopped = False
Here is the quit callback register call:
titleScreen.registerCallbackQuit(quit)
Which looks like:
def registerCallbackQuit(self, callback):
self.callbackQuit = callback
And it calls quit if it gets a in the user input.
global stopped would work (probably). People use classes to avoid globals (among other things). If 'stopped' is spread out over many files, you would need to import it.