我想在python中创建一个倒数计时器应用程序。 我在PyQt中创建了一个计时器,现在我不想通过发送信号和套接字连接来设置计时并从另一个应用程序启动此计时器。
这是我的代码。 Gui是在QtCreator中生成的
Server.py
import socket
import sys
import time
import datetime
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QThread
from serwer_gui import Ui_MainWindow
class MyForm(QtWidgets.QMainWindow):
def __init__(self, parent=None):
QtWidgets.QWidget.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
# Syglany i sloty
self.ui.pushButtonKlientClose.clicked.connect(self.close_client)
self.ui.pushButtonCzasStart.clicked.connect(self.start_count)
def close_client(self):
c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
c.connect(("127.0.0.1", 1234))
c.send("zamknij;".encode())
c.close()
return
def start_count(self):
ilosc_minut = self.ui.spinBoxTime.value()
print(ilosc_minut)
c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
c.connect(("127.0.0.1", 1234))
c.send(("czas_set;10").encode())
c.close()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
myapp = MyForm()
myapp.show()
sys.exit(app.exec_())
和Client.py
import socket
import sys
import time
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QThread
from klient_gui import Ui_MainWindow
class MyForm(QtWidgets.QMainWindow):
def __init__(self, parent=None):
QtWidgets.QWidget.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
# Pelen ekran
# self.showFullScreen()
self.showMaximized()
self.timer = QtCore.QTimer(self)
self.polaczenie = Polaczenie(self)
self.polaczenie.start()
#self.start_linczik(20)
def updateLCD(self):
# Update the lcd
self.start_time -= 1
if self.start_time >= 0:
self.ui.lcdNumber.display("%d:%02d" % (self.start_time / 60, self.start_time % 60))
else:
self.timer.stop()
def start_linczik(self, b):
self.start_time = b
self.ui.lcdNumber.display("%d:%02d" % (self.start_time / 60, self.start_time % 60))
self.timer.start(1000)
self.timer.timeout.connect(self.updateLCD)
class Polaczenie(QtCore.QThread):
sig = QtCore.pyqtSignal(str,str)
def __init__(self, parent):
super(Polaczenie, self).__init__(parent)
self.ui = parent.ui
self.parent = parent
self.sig.connect(self.event_dispatcher)
def run(self):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ip = "127.0.0.1"
port = 1234
adress = (ip, port)
server.bind(adress)
server.listen(1)
while True:
print("Start listenint on ", ip, " on ", port)
(client, addr) = server.accept()
print("Got connection from ", addr[0], ":", addr[1])
data = client.recv(1024)
data = data.decode()
print("Recived ", data, " from the client")
print("Processin data")
indeks_srednik = data.index(";")
instrukcja = data[:indeks_srednik]
try:
string = data[indeks_srednik+1:]
except Exception as e:
print(e)
try:
print(instrukcja)
print(string)
if instrukcja == "zamknij":
# Zamykanie aplikacji przy pomocy serwera
server.close()
sys.exit(0)
elif instrukcja == "czas_set":
self.sig.emit("czas_set", string)
except Exception as e:
print(e)
def event_dispatcher(self, a, b):
# funkcja dispatchujaca eventy
if a == "czas_set":
print("licznik start")
print(a)
print(b)
b=int(b)
MyForm().start_linczik(b)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
myapp = MyForm()
myapp.show()
sys.exit(app.exec_())
我想要实现的是当我从server.py通过套接字(例如czas_set; 60)发送到klient.py消息时,然后klient.py设置倒计时时间,并开始倒计时。 现在,当我运行我的程序时,我可以发送消息,但计时器不会启动。只有应用程序冻结并失败。 当我从MyForm类启动计时器 init 时,计时器工作正常。只有当我想通过套接字从另一个thred运行它时它才会失败 我做错了什么?我该如何解决这个问题呢?
在Windows 7和python 3.6上测试
答案 0 :(得分:0)
问题是由于运行MyForm().Start_linczik(b)
正在创建另一个窗口而引起的,此窗口将创建一个具有相同端口的服务器,该端口会因端口忙而生成错误。
你应该做的是用现有对象调用函数start_linczik
,为此我们可以使用信号,或者在这种情况下我会显示QMetaObject::invokeMethod()
的使用但为此你必须使用插槽中的装饰器pyqtSlot()
,这有利于减少内存消耗并使应用程序更快一些。
class MyForm(QtWidgets.QMainWindow):
def __init__(self, parent=None):
QtWidgets.QWidget.__init__(self, parent)
[...]
@QtCore.pyqtSlot()
def updateLCD(self):
[...]
@QtCore.pyqtSlot(int)
def start_linczik(self, b):
[...]
没有必要将parent
或parent.ui
保存在变量中,因为您可以通过parent()
方法访问父级。
class Polaczenie(QtCore.QThread):
sig = QtCore.pyqtSignal(str,str)
def __init__(self, parent):
super(Polaczenie, self).__init__(parent)
self.sig.connect(self.event_dispatcher)
def run(self):
[...]
def event_dispatcher(self, a, b):
# funkcja dispatchujaca eventy
if a == "czas_set":
print("licznik start")
print(a)
print(b)
b=int(b)
#MyForm().start_linczik(b)
QtCore.QMetaObject.invokeMethod(self.parent(), "start_linczik",
QtCore.Qt.QueuedConnection, QtCore.Q_ARG(int, b))