0

I have two programs both with a QTableWidget. I want to synchronize the tables over network automatically. I have no idea how to do this. I have used pyqt with socket it dosen't work. I have read a lot about simple chat application like this. I think that is not the way I need.

My program without any network code:

import sys
from PyQt4 import QtGui, QtCore

class Window(QtGui.QMainWindow):
    def __init__(self, parent=None):

        QtGui.QMainWindow.__init__(self, parent)

        # Table
        header = ["Name", "Date", "Club"]

        self.Table = QtGui.QTableWidget(0, len(header))
        self.Table.setHorizontalHeaderLabels(header)
        self.Table.resizeColumnsToContents()

        # Layout
        layout = QtGui.QGridLayout()
        layout.addWidget(self.Table)

        self.tab_widget = QtGui.QTabWidget()
        self.tab_widget.updatesEnabled()

        tabs = [u"Overview"]
        for i,d in enumerate(tabs):
            widget = QtGui.QWidget()
            self.tab_widget.addTab(widget, d)
            print i, d
            if i == 0:
                widget.setLayout(layout)

        self.setCentralWidget(self.tab_widget)
        self.show()

        data = ["Name1", "Monday", "Club1"]

        self.Table.insertRow(0)

        # insert Data
        for i in range(len(data)):

            t = QtGui.QTableWidgetItem(data[i].decode("utf8"))
            self.Table.setItem(0, i, t)

        self.Table.resizeColumnsToContents()                    

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    prog = Window()
    prog.show()
    sys.exit(app.exec_())
2
  • I thing, the code is at line 4, where is "..:def init" broken, please correct it. Even if it works, it is usual not to put any code after ":" in Python, it makes the code much more readable. Commented Apr 27, 2014 at 21:32
  • You are planning to synchronize status of something over network. You shall first make clear general logic - do you plan to use master - slave roles? Or you plan to allow updates on both tables? This could be rather complex. Your current question is now too wide. Commented Apr 27, 2014 at 21:34

1 Answer 1

0

I'd recommend changing the QTable to work with a model instead of items. Refer to here for an example that is based on a list-of-lists which should be easy to change to list-of-dictionaries (should you choose).

The code below uses JSON and ZeroMQ to JSON-serialise dictionaries and push them to listeners to update the dictionary on that end.

import json
import time
import threading
import zmq

class push_to(object):
    def __init__(self, address, *args, **kwargs):
        context = zmq.Context()

        # Socket to send messages to
        self.sender = context.socket(zmq.PAIR)
        self.sender.connect(address)

    def __call__(self, send_str, *args, **kwargs):
        self.sender.send_string(send_str)

class own_listener(threading.Thread):
    def __init__(self, parent, address, *args, **kwargs):
        self.parent = parent

        context = zmq.Context()

        # Socket to receive messages from
        self.receiver = context.socket(zmq.PAIR)
        self.receiver.bind(address)
        super(own_listener, self).__init__(*args, **kwargs)
        self.daemon = True

    def run(self):
        while True:
            message = self.receiver.recv()
            self.parent.change_receive(message)

class pub_sub_dict(dict):
    def __init__(self, address, *args, **kwargs):
        self.address   = address
        self.listeners = []
        self.is_listen = False
        super(pub_sub_dict, self).__init__(*args, **kwargs)
        self.own_listener = own_listener(self, address)
        self.own_listener.start()

    def __setitem__(self, key, value, *args, **kwargs):
        if not self.is_listen:
            self.change_send({key : value})
        super(pub_sub_dict, self).__setitem__(key, value, *args, **kwargs)

    def update(self, value, *args, **kwargs):
        if not self.is_listen:
            self.change_send(value)
        super(pub_sub_dict, self).update(value, *args, **kwargs)

    def change_send(self, idict):
        json_str = json.JSONEncoder().encode(idict)
        for listener in self.listeners:
            listener(json_str)

    def change_receive(self, json_str):
        self.is_listen = True
        state = json.JSONDecoder().decode(json_str)
        self.update(state)
        self.is_listen = False

a = pub_sub_dict("tcp://127.0.0.1:5556")
b = pub_sub_dict("tcp://127.0.0.1:5557")
c = pub_sub_dict("tcp://127.0.0.1:5558")

a.listeners.append(push_to(b.address))
a.listeners.append(push_to(c.address))
b.listeners.append(push_to(a.address))

print "a:", a
print "b:", b
print "c:", c
time.sleep(1)
a["test"] = "test string 1"
print "a:", a
print "b:", b
print "c:", c
time.sleep(1)
b["test"] = "test string 2"
print "a:", a
print "b:", b
print "c:", c
time.sleep(1)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.