I make simple program server-client with localhost, and I want to integrate with my simple ui (PyQt5). this is my code:
# main program
import sys
import socket
import res
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtNetwork import *
from PyQt5.QtWidgets import *
from PyQt5 import uic
from serv import Server
SERVER = socket.gethostbyname(socket.gethostname())
class MainWindow(QWidget):
def __init__(self):
QWidget.__init__(self)
uic.loadUi("serv.ui", self)
self.setGeometry(100, 50, 400, 500)
self.setWindowFlags(Qt.FramelessWindowHint)
self.setAttribute(Qt.WA_TranslucentBackground)
self.sock = self.makeServer()
self.makeConnections()
self.ipadd.setText(f'{SERVER}')
def makeServer(self):
sock = Server()
sock.start()
sock.clientReadyToRead.connect(self.onClientReadyToRead)
return sock
def makeConnections(self):
self.startButton.clicked.connect(self.onstartButtonClicked)
self.closeButton.clicked.connect(self.close)
def onClientReadyToRead(self, data):
self.messagetext.appendPlainText(data)
def onstartButtonClicked(self):
# port = self.portOpsi.currentText()
# port = int(port)
# if self.server.listen(QHostAddress(SERVER), port):
self.messagetext.appendPlainText(f"[LISTENING] Server is listening on {SERVER}\n")
# else:
# QMessageBox.critical(self, "Error", Server.errorString())
def mousePressEvent(self, QMouseEvent):
self.oldPosition = QMouseEvent.globalPos()
def mouseMoveEvent(self, QMouseEvent):
delta = QPoint(QMouseEvent.globalPos() - self.oldPosition)
self.move(self.x() delta.x(), self.y() delta.y())
self.oldPosition = QMouseEvent.globalPos()
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setStyle("fusion")
w = MainWindow()
w.show()
sys.exit(app.exec_())
serv program:
import socket
import threading
from PyQt5.QtCore import pyqtSignal, QObject
class Server(QObject):
clientReadyToRead = pyqtSignal(str)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.running = 0
def handle_client(self, conn, addr):
print(f"[NEW CONNECTION] {self.addr} connected.")
connected = True
while connected:
self.msg = self.conn.recv(1024).decode('utf-8')
self.clientReadyToRead.emit(self.msg)
print(f"[{self.addr}] {self.msg}")
if self.msg == " ":
connected = False
self.conn.close()
def start(self):
SERVER = socket.gethostbyname(socket.gethostname())
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
PORT = 5050
self.server.bind((SERVER, PORT))
self.server.listen()
print(f"[LISTENING] Server is listening on {SERVER}")
while True:
self.conn, self.addr = self.server.accept()
self.thread = threading.Thread(target=self.handle_client, args=(self.conn, self.addr))
self.thread.start()
print(f"[ACTIVE CONNECTIONS] {threading.activeCount() - 1}")
when I running my program, the ui not showing but server ready to connect and just running on terminal server not showing the ui.
this my ui, and code: ui when running
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>450</width>
<height>550</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<widget class="QWidget" name="widget" native="true">
<property name="geometry">
<rect>
<x>40</x>
<y>30</y>
<width>370</width>
<height>480</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">QPushButton#startButton{
background-color: rgba(0, 0, 0, 150);
color:rgba(225,225,225,210);
border-radius:3px;
}
QPushButton#startButton:hover{
background-color: rgba(20,20,20,170);
}
QPushButton#startButton:pressed{
padding-left:2px;
padding-top:2px;
background-color:rgba(20,20,20,170);
}
QPushButton#closeButton{
background-color: rgba(0, 0, 0, 0);
color:rgba(225,225,225,210);
border-radius:3px;
}
QPushButton#closeButton:hover{
background-color: rgba(0, 0, 0, 0);
}
QPushButton#closeButton:pressed{
padding-left:2px;
padding-top:2px;
background-color: rgba(0, 0, 0, 0);
}
QComboBox#portOpsi{
background-color: rgba(0, 0, 0, 150);
color:rgba(225,225,225,210);
border-radius:3px;
}
</string>
</property>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>40</x>
<y>30</y>
<width>300</width>
<height>420</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">border-image: url(:/res/res/mountains-3840x2160.jpg);
border-radius:15px;</string>
</property>
<property name="text">
<string/>
</property>
</widget>
<widget class="QLabel" name="label_3">
<property name="geometry">
<rect>
<x>40</x>
<y>30</y>
<width>300</width>
<height>420</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, stop:0 rgba(0, 0, 0, 9), stop:0.494318 rgba(0, 0, 0, 50), stop:1 rgba(0, 0, 0, 75));
border-radius:15px;</string>
</property>
<property name="text">
<string/>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>50</x>
<y>60</y>
<width>280</width>
<height>390</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">background-color:rgba(0,0,0,100);
border-radius:15px;</string>
</property>
<property name="text">
<string/>
</property>
</widget>
<widget class="QLabel" name="label_4">
<property name="geometry">
<rect>
<x>150</x>
<y>80</y>
<width>91</width>
<height>41</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>20</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="styleSheet">
<string notr="true">color:rgba(255,255,255,210);</string>
</property>
<property name="text">
<string>Server</string>
</property>
</widget>
<widget class="QTextEdit" name="ipadd">
<property name="geometry">
<rect>
<x>75</x>
<y>140</y>
<width>230</width>
<height>35</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>10</pointsize>
<weight>75</weight>
<italic>false</italic>
<bold>true</bold>
<kerning>true</kerning>
</font>
</property>
<property name="styleSheet">
<string notr="true">background-color:rgba(0,0,0,0);
border:none;
border-bottom:2px solid rgba(105,118,132,255);
color:rgba(255,255,255,230);
padding-botom:7px;</string>
</property>
<property name="autoFormatting">
<set>QTextEdit::AutoNone</set>
</property>
<property name="html">
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
p, li { white-space: pre-wrap; }
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:600; font-style:normal;">
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt; font-weight:400;"><br /></p></body></html></string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextEditable|Qt::TextEditorInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
<property name="placeholderText">
<string>IP Address</string>
</property>
</widget>
<widget class="QComboBox" name="portOpsi">
<property name="geometry">
<rect>
<x>150</x>
<y>180</y>
<width>71</width>
<height>22</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">selection-background-color:rgba(0,0,0,255);
selection-color:(255,255,255,255);</string>
</property>
<property name="editable">
<bool>false</bool>
</property>
<item>
<property name="text">
<string>5050</string>
</property>
</item>
<item>
<property name="text">
<string>8001</string>
</property>
</item>
</widget>
<widget class="QPushButton" name="startButton">
<property name="geometry">
<rect>
<x>230</x>
<y>180</y>
<width>75</width>
<height>22</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>10</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="cursor">
<cursorShape>ArrowCursor</cursorShape>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string>Start</string>
</property>
</widget>
<widget class="QPlainTextEdit" name="messagetext">
<property name="geometry">
<rect>
<x>75</x>
<y>210</y>
<width>230</width>
<height>210</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>10</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="styleSheet">
<string notr="true">background-color:rgba(0,0,0,0);
border:none;
border-bottom:2px solid rgba(105,118,132,255);
color:rgba(255,255,255,230);
padding-botom:7px;</string>
</property>
</widget>
<widget class="QPushButton" name="closeButton">
<property name="geometry">
<rect>
<x>320</x>
<y>35</y>
<width>16</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="res.qrc">
<normaloff>:/res/res/close.png</normaloff>:/res/res/close.png</iconset>
</property>
<property name="iconSize">
<size>
<width>10</width>
<height>10</height>
</size>
</property>
</widget>
</widget>
</widget>
<resources>
<include location="res.qrc"/>
</resources>
<connections/>
</ui>
I just want to integrate ui with server program (show msg to PlainText on ui, etc)
CodePudding user response:
The problem is caused because the start method never ends as it has a while loop. Instead of using threads and socket you can use QTcpServer or asyncio. In this case I will show an example with the second using qasync(python -m pip install qasync
):
import asyncio
from functools import cached_property
from pathlib import Path
import os
import socket
import sys
from PyQt5.QtCore import QObject, Qt, pyqtSignal as Signal
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5 import uic
import qasync
CURRENT_DIRECTORY = Path(__file__).resolve().parent
SERVER = socket.gethostbyname(socket.gethostname())
class Server(QObject):
message_changed = Signal(str)
async def start(self, address="localhost", port=5050):
server = await asyncio.start_server(self.handle_client, address, port)
async with server:
await server.serve_forever()
async def handle_client(self, reader, writer):
connected = True
while connected:
message = (await reader.read(1024)).decode("utf8")
self.message_changed.emit(message)
if message == " ":
connected = False
writer.close()
class MainWindow(QWidget):
def __init__(self):
QWidget.__init__(self)
uic.loadUi(os.fspath(CURRENT_DIRECTORY / "serv.ui"), self)
self.setGeometry(100, 50, 400, 500)
self.setWindowFlags(Qt.FramelessWindowHint)
self.setAttribute(Qt.WA_TranslucentBackground)
self.makeConnections()
@cached_property
def server(self):
return Server()
def makeConnections(self):
self.startButton.clicked.connect(self.onstartButtonClicked)
self.closeButton.clicked.connect(self.close)
self.server.message_changed.connect(self.handle_message_changed)
def handle_message_changed(self, data):
self.messagetext.appendPlainText(data)
def onstartButtonClicked(self):
self.messagetext.appendPlainText(
f"[LISTENING] Server is listening on {SERVER}\n"
)
asyncio.ensure_future(self.server.start(SERVER))
def main():
app = QApplication(sys.argv)
loop = qasync.QEventLoop(app)
asyncio.set_event_loop(loop)
w = MainWindow()
w.show()
with loop:
loop.run_forever()
if __name__ == "__main__":
main()