How do I run a tcp server in pyqt? - pyqt

I configured as below and ran pyqt
However, the ui screen appears and the program ends as it falls into an infinite loop.
How can I run a tcp server when running the program
host = "127.0.0.1"
port = 8000
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.initUI()
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((host, port))
server_socket.listen()
while True:
connection, addr = server_socket.accept()
try:
data = connection.recv(100)
except socket.error:
connection.close()
def initUI(self):
self.ui = uic.loadUi("./main.ui")
self.ui.showFullScreen()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = MyApp()
sys.exit(app.exec_())

Related

Can't get a connection between two socket scripts

I am trying to build a tkinter messaging app using the socket module in python, I was testing it, but two copies of the script cannot connect to each other (one hosting and the other connecting). The create_messaging_screen() method never runs.
import socket
from threading import Thread
import tkinter as tk
default_port = 43777
self_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def client_link():
self_socket.connect(('', default_port))
create_messenging_screen()
self_socket.sendall(("hi to you too").encode("utf-8"))
while True:
try:
print(self_socket.recv(1024))
except:pass
def host_link():
self_socket.bind(('', default_port))
self_socket.listen(1)
global client_conn
client_conn, client_addr = self_socket.accept()
create_messenging_screen()
client_conn.sendall(("hi").encode("utf-8"))
print(client_addr)
while True:
try:
print(client_conn.recv(1024))
except:pass
def continue_setup(route):
if route == None:
Thread(target=host_link).start()
else:
Thread(target=client_link).start()
def create_messenging_screen():
#clear the window and create the messaging GUI
window = tk.Tk()
#IM app connection screen
#host a chatroom
button(window, command=lambda: continue_setup(None))
#join a chatroom
button(window, command=lambda: continue_setup(1))
window.mainloop()
acw1668 was correct, I should've used 'localhost' or something of the like for the IP parameter in self_socket.connect('', default_port).

WinError 10022: An invalid argument was supplied, and I cannot figure out why

I made a chat application just for fun using just the socket library and threading, but now I am trying to make a GUI version of it. I am trying to have a first window where you choose your name and a second window where you send messages etc. My name window works with receiving messages but my text window does not work with receiving messages and I get:
[WinError 10022] An invalid argument was supplied.
MY CODE: https://github.com/BenTensMexicans/pyqt5thing
EDIT: Here is my minimal example,
#SIMPLE SERVER
import socket
import threading
connections = []
def handler(conn, addr):
while True:
try:
msg = conn.recv(1024).decode("utf-8")
except:
break
for x in connections:
x.send(f"{addr[0]}: {msg}".encode("utf-8"))
def start():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostbyname(), 8888))
s.listen(5)
while True:
conn, addr = s.accept()
t = threading.Thread(target=handler, args=(conn, addr))
t.start()
start()
#PYQT5 BASIC CLIENT
import socket
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QThreadPool, QThread
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
#removed setup so it does not look overwelming
self.c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.c.connect((socket.gethostname(), 8888))
self.lineEdit.returnPressed.connect(self.sendmsg)
self.thread = QThread()
self.thread.start(self.recieve())
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
def sendmsg(self):
self.c.send(self.lineEdit.text().encode("utf-8"))
self.lineEdit.clear()
def recieve(self):
while True:
msg = self.c.recv(1024).decode("utf-8")
if msg:
txt = txt + msg + "\n"
self.plainTextEdit.setPlainText(txt)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
It does not even start but when windows prompts to terminate this and I terminate it it gives me the error previously described.
Your code has several errors with the handling of threads:
self.thread.start(self.recieve()) doesn't make sense, it looks like you're confusing QThread with python threading.
Even if the above worked it would still be an error since you should not update the GUI from another thread.
Instead of messing with threads you can use QTcpSocket from QtNetwork:
import socket
from PyQt5 import QtCore, QtGui, QtWidgets, QtNetwork
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self._socket = QtNetwork.QTcpSocket(self)
self.lineEdit = QtWidgets.QLineEdit()
self.plainTextEdit = QtWidgets.QPlainTextEdit(readOnly=True)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
lay = QtWidgets.QVBoxLayout(central_widget)
lay.addWidget(self.lineEdit)
lay.addWidget(self.plainTextEdit)
self.socket.readyRead.connect(self.receive_message)
self.lineEdit.returnPressed.connect(self.send_message)
self.socket.connected.connect(self.on_connected)
self.socket.disconnected.connect(self.on_disconnected)
try:
server_name = socket.gethostbyname()
except:
server_name = socket.gethostbyname(socket.gethostname())
self.socket.connectToHost(QtNetwork.QHostAddress(server_name), 8888)
self.lineEdit.setEnabled(False)
#property
def socket(self):
return self._socket
def send_message(self):
msg = self.lineEdit.text()
self.socket.write(msg.encode("utf-8"))
def receive_message(self):
data = self.socket.readAll()
msg = data.data().decode("utf-8")
self.plainTextEdit.appendPlainText(msg)
def on_connected(self):
self.lineEdit.setEnabled(True)
def on_disconnected(self):
self.lineEdit.setEnabled(False)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
Note: for x in connections: it will not do anything since connections is empty, if you want there to be echo then you must add connections.append(conn) after conn, addr = s.accept()

a serial port thread in pyQT5

The following is my code. I am trying to create a serial port thread in my pyQt5 GUI. I checked many examples. This is very helpful one Background thread with QThread in PyQt
I think I made a successful connection but I am confused about the signature.
SelectedItem is the selected port. The GUI is still freezing because of while loop.
I need some help. Thanks!
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
# vim:fileencoding=utf-8
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from TTP_Monitor_GUI import Ui_MainWindow
import serial
import serial.tools.list_ports
import binascii
import glob
class SerialPort(QObject):
def __init__(self, parent = None):
super(SerialPort, self).__init__(parent)
# Explicit signal
newParams = pyqtSignal(str)
#pyqtSlot(str)
def ReadSerialPort(self, port):
#initialization and open the port
with serial.Serial(port, 115200, timeout=1) as ser:
print ("Starting up")
while True:
readOut = 0 #chars waiting from laser range finder
#readOut = ser.readline().decode('ascii')
readOut = ser.read(268) # Reads # Bytes
r = binascii.hexlify(readOut).decode('ascii')
print(r)
self.newParams.emit(r)
#ser.flush() #flush the buffer
if ser.isOpen() == False:
print("Serial Port is Close")
class Main(QMainWindow):
# Explicit Signal
#ser = pyqtSignal(str)
def __init__(self, parent=None):
super(QMainWindow, self).__init__(parent)
#QMainWindow.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.btnRefresh.clicked.connect(self.Refresh)
self.ui.btnConnect.clicked.connect(self.Connect)
self.ListFunction(self.SerialPorts())
# Implicit Slot
def Connect(self):
Items = self.ui.listMain.selectedItems()
if len(Items) != 1:
msg = QMessageBox()
msg.setIcon(QMessageBox.Critical)
msg.setWindowTitle("BE CAREFULL!")
msg.setText("SELECT ONLY 1 ITEM!...")
msg.exec_()
else:
SelectedItem = Items[0].text()
SelectedItem = SelectedItem.split(" ")[0]
if sys.platform.startswith('win') and SelectedItem[:3] != 'COM':
msg = QMessageBox()
msg.setIcon(QMessageBox.Critical)
msg.setWindowTitle("BE CAREFULL!")
msg.setText("THERE IS A MISTAKE!...")
msg.exec_()
return
# Read Selected Serial Port
self.serialThread = QThread()
self.ser = SerialPort()
self.ser.moveToThread(self.serialThread)
self.ser.newParams.connect(self.serialThread.quit)
#self.serialThread.started.connect(self.ser.ReadSerialPort(SelectedItem))
self.serialThread.started.connect(lambda port=SelectedItem: self.ser.ReadSerialPort(port))
self.serialThread.start()
def Refresh(self):
""" Refresh List Widget """
self.ui.listMain.clear()
if self.ui.radioSerialPorts.isChecked() == True:
self.ListFunction(self.SerialPorts())
elif self.ui.radioTCP.isChecked() == True:
pass
def ListFunction(self, items):
""" Lists items into List Widget """
if type(items) == list and type(items[0]) == str:
#qApp.processEvents() # See Changes on GUI
self.ui.listMain.addItems(items)
else:
msg = QMessageBox()
msg.setIcon(QMessageBox.Critical)
msg.setWindowTitle("BE CAREFULL!")
msg.setText("ITEMS ARE WRONG!...")
msg.exec_()
def SerialPorts(self):
""" Lists serial port names """
device = []
description = []
result = []
for port in serial.tools.list_ports.comports():
device.append(port.device)
description.append(port.description)
result.append(port.device + ' - ' + port.description)
return result
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
myapp = Main()
myapp.show()
sys.exit(app.exec_())
provide delay function time.sleep(1) at thread function ReadSerialPort(self, port) inside the while loop äfter the function self.newParams.emit(r).
pyqt UI does not gets sufficient time to execute. so provide delay. it will work.

Problems with Tkinter window crashing in Python 3

I've been developing a chatbot sort of program with tkinter and sockets, and I've had problems integrating Tkinter with the chatbot system, after clicking the "Ask" button, the tkinter window stops responding.
Code for the Client:
`
import socket, threading, time
import tkinter as tk
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = '25.65.227.4'
port = 10001
window = tk.Tk()
window.geometry('800x400+20+20')
window.title('Client')
labelBot = tk.Label(window, text='')
labelBot.config(font='Decker')
labelBot.place(x = 10, y = 10)
e1 = tk.Entry(window)
e1.config(font='Decker')
e1.place(x=50, y=350)
photo = tk.PhotoImage(file="Aldenv1.gif")
labelPic = tk.Label(image=photo)
labelPic.place(x=450, y=10)
s.connect((host, int(port)))
print('connected to server')
labelBot['text'] = 'Connected to Server'
def Main():
while True:
data = s.recv(2048).decode('utf-8')
labelBot['text'] = ''
labelBot['text'] = data
if not data:
break
def bt_click():
answer = e1.get().encode('utf-8')
s.send(answer)
Main()
bt = tk.Button(window, text='Ask', command=bt_click)
bt.config(font='Decker')
bt.place(x=400, y=350)
window.mainloop()
if __name__ == '__main__':
Main()`
I tried doing all sorts of things but I haven't managed to solve this crash

Howto change progress by worker thread

I'm new to PyQt4 so maybe it is a bagatelle. I try to show a progress in my GUI, which will be updated by an worker thread.The QProgressBar is with other memory's in a QTableWidget.
The worker thread starts in the init function of my GUI.
self.st = ServerThread()
self.st.start()
Here is the thread class
_exportedMethods = {
'changes': signal_when_changes,
}
class ServerThread(QtCore.QThread):
def __init__(self):
super(ServerThread,self).__init__()
st = self
#threading.Thread.__init__(self)
def run(self):
HOST = '' # local host
PORT = 50000
SERVER_ADDRESS = HOST, PORT
# set up server socket
s = socket.socket()
s.bind(SERVER_ADDRESS)
s.listen(1)
while True:
conn, addr = s.accept()
connFile = conn.makefile()
name = cPickle.load(connFile)
args = cPickle.load(connFile)
kwargs = cPickle.load(connFile)
res = _exportedMethods[name](*args,**kwargs)
cPickle.dump(res,connFile) ; connFile.flush()
conn.close()
If my Server changes values in the database he will call the following method which will captured with a remote prozedure call in the thread.
def signal_when_changes():
s = Subject()
s.advise()
The pattern is a simple observer, which updated my GUI. To update the table in my gui is the following method called.
def refresh(self,table):
clients = self.db.get_clients()
if(self.ui.mainTable.rowCount() != len(clients)):
self.search_add_client
allRows = table.rowCount()
for row in xrange(0,allRows):
for c in clients:
if table.item(row,0).text() == c.get_macaddr().text():
self.refresh_line(table,row,c)
This method checks wheter there were changes in a row if the needs a update the following method will do this.
def refresh_line(self,table,rowNumber,client):
table.item(rowNumber, 0).setText(client.get_macaddr().text())
table.item(rowNumber, 1).setText(client.get_product().text())
table.item(rowNumber, 2).setText(client.get_site().text())
table.item(rowNumber, 3).setText(client.get_hostname().text())
table.item(rowNumber, 4).setText(client.get_priv_data().text())
table.cellWidget(rowNumber, 5).setValue(client.get_progress_value())
table.item(rowNumber, 6).setText(client.get_stage().text())
The other memory's can be updated but not the progress, here the line in which i want to update the progress
self.ui.mainTable.setCellWidget(appendRowIndex,5,c.get_progress())
After this line the GUI crashes and i get the following message
QPixmap: It is not safe to use pixmaps outside the GUI thread
My conjecture is that i can't change QPixmaps outside the "Main/Gui" thread. I don't know how i can solve this problem, so I welcome all suggestions for resolution.
Thanks in advance.
Don't try to update the progress bar from within the thread: use a signal instead.
from PyQt4 import QtCore, QtGui
class Thread(QtCore.QThread):
def __init__(self,parent):
QtCore.QThread.__init__(self, parent)
def run (self):
for step in range(5):
self.sleep(1)
self.emit(QtCore.SIGNAL('taskUpdated'))
class Window(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
self.button = QtGui.QPushButton('Start', self)
self.progress = QtGui.QProgressBar(self)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.button)
layout.addWidget(self.progress)
self.connect(self.button, QtCore.SIGNAL('clicked()'),
self.handleButton)
self.thread = Thread(self)
self.connect(self.thread, QtCore.SIGNAL('taskUpdated'),
self.handleTaskUpdated)
def handleButton(self):
self.progress.setRange(0, 4)
self.progress.setValue(0)
self.thread.quit()
self.thread.start()
def handleTaskUpdated(self):
self.progress.setValue(self.progress.value() + 1)
def closeEvent(self, event):
self.thread.wait()
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())

Resources