I wrote a networked chatroom server and client and it works in a simple Terminal environment just fin, and just today started to translate it to over to a GUI form using Tkinter. The sending of messages is fine as I can handle them with button press event handlers and key handles, but the problem is receiving messages. I need to be able to check to see if data has been received while still in the Tkinter window. Is there a nice way of doing something like this? I've tried checking every second using the root.action(time,event) call, but that didn't seem to work, and have just tried running loops in different spots (against my better judgement).
What can I do to have Tkinter listen to something outside of itself, but still be listening to the events going on within my Tkinter window?
See
How do you run your own code alongside Tkinter's event loop?
In particular, the comment about setting the timeout to 0 in the Tk().after() call, so you have non-blocking, outside the Tk event loop code handling possibilities.
Hope that helps.
Related
I am now trying to make a GUI on my PC communicate with a Server per sockets.
here is part of the code of GUI:
def listenToServer(self):
""" keep listening to the server until receiving 'All Contracts Finished' """
self.feedbackWindow.appendPlainText('--Executing the Contracts, Listening to Server--')
contentsListend = ''
while contentsListend != 'All Contracts Finished':
#keep listen from the socket
contentsListend = self.skt.recv(1024)
#make the GUI show the text
self.feedbackWindow.appendPlainText(contentsListend)
On the Other side, the server will send data one by one but with some interval. Here is the test code simulating the server:
for i in range(7):
print 'send back msg, round: ', i # this will be printed on the screen of the server, to let me know that the server works
time.sleep(1) # make some interval
# c is the connected socket, which can send messages
# just send the current loop number
c.send('send back msg' + str(i))
c.send('All Contracts Finished')
c.close()# Close the connection
Now, everything works except the problem that, the GUI will only show the received messages after the whole for loop in the server.
Once I run the server and the GUI. The server side print the messages onto the screen with correct speed one by one, but the GUI has no response, it does not update. Till the end of the program, all the 7 lines occurs all at once at GUI side. I want them to appear one by one, so that later I can inspect the state of the server with this GUI on my PC.
Can anybody help, thanks a lot!
This has nothing to do with "fast" or "slow".
The GUI runs on the same thread as your listenToServer method - so as long as it's running nothing can happen on the GUI thread. You'll notice that you can't move, resize or click anything in the GUI while you're waiting socket input.
You'll have to run your listenToServer method on a thread separate from the GUI. The proper way to do that would be to implement a Worker object that receives data from the socket and notifies you textEdit via a Signal->Slot connection that there's data ready to receive.
I answered a similar question a while back, that might help
https://stackoverflow.com/a/24821300/2319400
A really quick and dirty alternative would be to process all queued events when you've appended new data, via:
QApplication.processEvents()
This gives Qt time to e.g. repaint the GUI on the screen with new text.
Your GUI will however not respond to any events while python is waiting for data to come from the socket!
I'm trying to get my tkinter app (python 3.4.2) to be aware of the system shutdown event so it can release the sqlite3 connection and close a log. I found a post from 2009 about using the win32 api module. I can't get the posted sample to work as I expect (I may not understand it), where a message should cause the wndproc function to fire.
2009 reference:
Python - Windows Shutdown Events
Any other good references or pointers to how to accomplish this?
Typically you want to close the connection anytime the app closes, even if it wasn't a normal closure (ie: by picking "Exit" from a menu). The normal way to do that is to set up a handler for the WM_DELETE_WINDOW protocol (something of a dinosaur left over from when tk only worked on X11 systems). I don't know for certain your app will be notified this way when the system shuts down, but it probably does.
For more information see this question on stackoverflow: Intercept Tkinter "Exit" command?
The log output of my python program (using the builtin logging module, but occurs even when using simple prints) is partially messed up, as you can see in the following image. Note the first line, first word still being correct and then it gets mixed up:
I tried to visualize the situation where this happens:
Basically in my main thread/program I start a simple socketserver.TCPServer to listen for incoming messages. That server runs on its own thread (QtCore.QThread) so my program is not blocked. If some other application sends a message the request handler of the TCPServer will simply forward the message to the main thread using a QtCore.SIGNAL like:
self.emit(QtCore.SIGNAL('received(const QString)'), receivedMessage)
The program then does some parsing and computation with that message and logs those, thereby producing the gibberish seen above. At some point the logging returns back to working normally.
I am not sure if this is related to sockets or threading or both, but I guess it may be a common issue and therefore I am thankful for any hints why this occurs.
I think I have located the problem:
When the external application wants to send a message it will always create a new client socket, connect to the server, send the message and then close the client socket.
The sock.close() does not seem to close immediately, the docs say I should call sock.shutdown(how) first, but unfortunately this did not help as well. I can use a small time.sleep(0.5) after the close to fix the logging issue, but instead I did something like this:
def ensure_closed(self):
while True:
try:
self.sock.recv(1024)
except:
break
def close_connection(self):
self.sock.close()
self.ensure_closed()
# Continue with other stuff.
# Now the logging behaves normally.
There might be better ways to do it.
I'm making a cmd IRC client in Python. I want to receive data at the same time I can write message, in the previous code I did I could only write 2 messages and then it bugs and I can't write until it receives some kind of data.
The question is, can I have one cmd window running the received data and other one with a constant input waiting for me to write something to send?, maybe with threads?
I've looked through the subprocess library but I don't really know how to code it.
CMD1:
while Connected:
print socket.recv(1024)
CMD2:
while Connected:
text = raw_input("Text to send>> ")
socket.send(text)
(This is a pseudocode not a real one)
This approach you are proposing could be done by making a server like application, and 2 client applications that connect via localhost to send and receive events. So that way you could have 2 terminals open , connected to the same session of the server.
On the other side you should consider a different design approach that include ncurses which allow you to make a terminal ui with input and output at the same terminal (two sections up and down). You can reference: http://gnosis.cx/publish/programming/charming_python_6.html
I want to write an (GUI) application that listens both to keyboard events (client side generated events) and to a network port (server side generated events). I could use some high level advice on how to do this. Some additional info:
- I am using the wxPython module for the GUI
- I could set the socket in non-blocking mode, but this way I have to keep polling the socket by keeping executing the recv() command. I did this earlier and I can recall that this used considerable resources
- I could use the thread module, but since I am not familiar with it, I try to avoid this, but maybe I can't
Advice would be appreciated.
wxPython does have key events. Here are the wxPython docs page on the subject: http://www.wxpython.org/docs/api/wx.KeyEvent-class.html
wxPython doesn't wrap every single thing in wxWidgets. The developers didn't think that they needed to wrap stuff that already had great support in Python itself. Thus, see Python for its socket support
http://docs.python.org/library/socket.html
http://docs.python.org/howto/sockets.html
http://docs.python.org/library/socketserver.html
And if you want to get really heavy, look into the Twisted framework. There are several articles on using it with wxPython:
http://twistedmatrix.com/documents/current/core/howto/choosing-reactor.html
http://wiki.wxpython.org/wxPythonAndTwisted
http://code.activestate.com/recipes/181780-using-wxpython-with-twisted-python/
I am not a wx expert. Could you use wx's native event driven mechanisms? The keypress would certainly have an event. Wx has a socket class wxSocketClient() that could translate the low level socket events (data ready, closed, etc) into a wx event.
There is wxKeyEvent in Docs. Use that to catch the keys and Socket to send it via a network or do whatever you want to do! For socket see this sticky. It is C++ but it will give you a better Idea!