gtk3 3.2.2
python-gobject 3.0.2
Пытаюсь создать простенький одноранговый чатик. Как я сумел нагуглить, Gtk.main() является фактически бесконечным циклом. И слушанье порта надо запихнуть в бесконечный цикл. Для их совместной работы надо использовать несколько потоков. Причём в Gtk надо использовать свою собственную систему потоков. Ни как не могу найти адекватного примера её использования для PyGObject, попытался по аналогии из PyGtk перетащить, работает некорректно, Серверная часть стопорится на приёме сообщения(144) и не продолжается пока не случится присоединённого сигнала.
Вот исходник:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import socket
from threading import Thread
from gi.repository import Gdk, Gtk, GLib
class Gui(Thread):
'''
Клас для даботы с интерфейсом.
'''
def __init__(self):
Thread.__init__(self)
def run(self):
Gdk.threads_init()
Gdk.threads_enter()
self.Window = Gtk.Window()
self.Window.set_border_width(8)
self.Window.set_title("Выбор лабораторной")
self.Window.set_default_size(755, 275)
self.Window.connect('destroy', lambda x: self.close_win())
#Создаём контейнер в который всё будет запихано
self.Paned = Gtk.Paned.new(Gtk.Orientation.VERTICAL)
self.Window.add(self.Paned)
self.inBox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 5)
self.Paned.pack1(self.inBox, True, False)
self.outBox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 5)
self.Paned.pack2(self.outBox, True, False)
self.inSupBox = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 5)
self.inBox.pack_start(self.inSupBox, False, False, 0)
#Ярлык, в который надо будет записать IP с которого было послано сообщение.
self.inLabelIP = Gtk.Label()
self.inSupBox.pack_start(self.inLabelIP, False, False, 0)
#создаём контейнер с возможностью прокрутки.
self.inScrollWin = Gtk.ScrolledWindow()
self.inScrollWin.set_size_request(600, 200)
self.inBox.pack_start(self.inScrollWin, True, True, 0)
#Многострочное текстовое поле.
self.inTextView = Gtk.TextView()
self.inTextView.set_editable(False)
self.inTextView.set_wrap_mode(Gtk.WrapMode.WORD)
self.inScrollWin.add(self.inTextView)
#Для хранения текста в форме TextView нужен буфер.
self.inTextBuffer = Gtk.TextBuffer()
self.inTextView.set_buffer(self.inTextBuffer)
self.outSupBox = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 5)
self.outBox.pack_start(self.outSupBox, False, False, 0)
#Создаём поле для записи IP4
self.outIP = Gtk.Entry()
self.outIP.set_max_length(15)
self.outIP.set_has_tooltip(True)
self.outIP.set_tooltip_text('IP4 компьютера, на который будет послано сообщение.')
self.outSupBox.pack_start(self.outIP, False, False, 0)
#создаём контейнер с возможностью прокрутки.
self.outScrollWin = Gtk.ScrolledWindow()
self.outScrollWin.set_size_request(600, 55)
self.outBox.pack_start(self.outScrollWin, True, True, 0)
#Многострочное текстовое поле.
self.inTextView = Gtk.TextView()
self.inTextView.set_hexpand(True)
self.inTextView.set_vexpand(True)
self.inTextView.set_wrap_mode(Gtk.WrapMode.WORD)
self.outScrollWin.add(self.inTextView)
#Для хранения текста в форме TextView нужен буфер.
self.inTextBuffer = Gtk.TextBuffer()
self.inTextView.set_buffer(self.inTextBuffer)
self.outBut = Gtk.Button.new_from_stock(Gtk.STOCK_OK)
self.outBut.set_halign(Gtk.Align.END)
self.outBut.set_size_request(150, 35)
self.outBut.connect('clicked', lambda x: self.mess_send())
self.outBox.pack_end(self.outBut, False, False, 0)
self.Window.show_all()
Gtk.main()
def close_win(self):
Gtk.main_quit()
Gdk.threads_leave()
def buffer_add(self, inMess):
self.StartIter = self.inTextBuffer.get_end_iter()
self.inTextBuffer.insert(self.StartIter, "\n\n>>>>> "+inMess)
def ip_set(self, inIp):
self.inLabelIP.set_text(inIp)
class Server(Thread):
'''
Класс отвечающий за приём сообщений
'''
def __init__(self):
Thread.__init__(self)
def run(self):
try:
self.servSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except:
print('Сокет не создаётся.')
try:
self.servSocket.bind(('', 6888))
except:
print('Не запускается слушанье порта')
try:
self.servSocket.listen(1)
except:
print('Я не понимаю эту строчку но она не вышла.')
while True:
try:
inConn, (inIP, tmp) = self.servSocket.accept()
except:
print('Не вышло загнать полученные данные в переменную')
inData = inConn.recv(1024)
inMess = str(inData, 'utf8')
inConn.send(b'data')
class Client:
'''
Клас отвечает за отправку сообщения
'''
def __init__(self):
pass
guiThread = Gui()
guiThread.start()
print('ГУЙ запущен')
serverThread = Server()
serverThread.start()
print('Сервер запущен')