Why is the text label unchanged?

0

I have the class of a screen, which contains a text label, the code loads an xml containing the objects.

tela.py:

#!/usr/bin/python3
import gi
import modulo_arquivos
import os

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk

# diretorios dos arquivos
diretorio_exe = os.path.dirname(os.path.realpath(__file__))
diretorio_proj = diretorio_exe + '/'
diretorio_tela = diretorio_proj + 'screens/tela_principal/tela_principal.glade'

class tela_principal():


    def carrega_arquivo_xml(self):


        self.tela_builder = Gtk.Builder()
        self.tela_builder.add_from_file(diretorio_tela)

        self.janela = self.tela_builder.get_object("Janela")
        self.label_txt = self.tela_builder.get_object('txt_ps_atual01')


    def abre_tela(self):
        self.janela.show()

    def fecha_tela(self):
        self.janela.hide()


    def escreve_txt(self, texto):
        self.label_txt.set_text(texto))

And I have a main file that instantiates the screen and has it open. In the main code I have two processes according to the code below:

#!/usr/bin/python3

#IMPORTS
import gi
gi.require_version("Gtk", "3.0")
from multiprocessing import Process, Queue, Pipe
from gi.repository import Gtk, GObject

import tela

tela_principal = tela.tela_principal()
tela_principal.carrega_arquivo_xml()
tela_principal.abre_tela()

def escreve_texto(texto):
    tela_principal.escreve_txt(texto)

def interface_grafica(tx, rx):

    while True:

        Gtk.main_iteration_do(False)

        #escreve_texto('HELLO')

def comunicacao_serial(tx,rx):
    escreve_texto('HELLO2')




if __name__ == "__main__":
    queue1 = Queue()
    queue2 = Queue()

    p1 = Process(target=interface_grafica, args=(queue1, queue2,))
    p2 = Process(target=comunicacao_serial, args=(queue2, queue1,))
    p1.start()
    p2.start()
    p1.join()
    p2.join()

The problem is that the label is only modified within the graphical interface function, but within the communication function is not changed. Why does this happen and how do I resolve it?

    
asked by anonymous 26.02.2018 / 21:00

1 answer

1

In fact, it is surprising that the label is changed the way the code is, if you call the escreve_texto function from within interface_grafica .

A "process" is something independent at the operating system level - no variable, window, file, or other thing of a process should be visible from another process - unless explicit data sharing mechanisms are used between processes . There are some resource inheritance rules - depending on the parameters used to create the child process, it may have access to some features of the parent process.

This code actually has 3 processes: the main program - and you create a subprocess just to manage the graphical interface, and another only for serial communication. Your window stays open and does not close with an error when calling .main_iteration_do is a surprise to me - means that this second process actually had access to the GTK data structures that were in the first process (and this happened in a way implied).

Well - there are a few ways to work out the approach there; if you are going to keep the multi-process architecture, the recommended way would be to create queues (you can not see how you create the ones that are there, but I suppose they are correct) - and pass all the data that you want them to appear in the graphical interface through these queues. It is no use trying to call a method that accesses GTK directly from another process - variables, objects, everything on the screen, do not even exist in the second process.

Now - the same recommendation there would not use this subprocess architecture in that program. As you can see, the complexity starts to increase (and you're trying to change a simple label) - the complexity will increase, much more if you have to respond to more events in the interface than just changing one label - will have to end up creating a function that reads the event queue from the other process and dispatches it to local functions - and to encode the events in the queue, it will end up developing a "mini-language".

A code with serial communication and itnerface GTK can perfectly work in a single process. If you do not want to write the serial code a bit more complex to be non-blocking, you can use two threads. (But remember to always try not to call any GTK functionality from within the second thread - just put data in structures that are consumed in functions inside the first thread - you can use queues, or even Python lists for that) / p>

In any case, you have already solved the problem of GTK not giving you control of the program by calling .main_iteration_do instead of .mainloop . All you have to do is, at the same point you repeatedly call this GTK method, also call the function to interact with the serial port - and, of course, change the function of the serial to have a timeout of zero - program will not be stopped waiting to have bytes available.

...

def main():
    dados_lidos = b""
    dados_a_escrever = b""
    while True:
         # processa eventos da interface gráfica:
         if Gtk.main_iteration_do(False):
              # a interface gráfica recebeu um evento de sair:
              break
         # realiza a comunicação serial:
         comunicacao_serial(dados_a_escrever)
         # processa os dados lidos da serial, 
         # como está tudo no mesmo processo e mesma thread, essa
         # funçao vai poder alterar a interface gráfica
         # sem problemas
         dados_a_escrever = processa(dados_lidos)
         # repete.


def comunicacao_serial(dados_a_escrever):
     if dados_a_escrever:
         serial.write(dados_a_escrever)
     return serial.read(10000)

def setup():
    serial = Pyseral.Serial(..., timeout=0)

if __name__ == "__main__":
    setup()
    main()
    
27.02.2018 / 14:01