added RPCServerThread; attach RPCServerThread to MainWindow, exposing append method to append to DictList and to MDISubPlot; data from DictList needs to be transposed now; apply pyqtgraph theming
This commit is contained in:
35
mainwin.py
35
mainwin.py
@ -1,11 +1,12 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt
|
from PyQt5.QtCore import Qt, pyqtSignal
|
||||||
from PyQt5.QtWidgets import QMainWindow, QSplitter
|
from PyQt5.QtWidgets import QMainWindow, QSplitter
|
||||||
|
|
||||||
import assets
|
import assets
|
||||||
from dictlist import DictList
|
from dictlist import DictList
|
||||||
from mdi import MDIArea, MDISubPlot
|
from mdi import MDIArea, MDISubPlot
|
||||||
|
from rpcserverthread import RPCServerThread
|
||||||
|
|
||||||
|
|
||||||
X = np.arange(100) / 10
|
X = np.arange(100) / 10
|
||||||
@ -13,6 +14,8 @@ X = np.arange(100) / 10
|
|||||||
|
|
||||||
class MainWindow(QMainWindow):
|
class MainWindow(QMainWindow):
|
||||||
|
|
||||||
|
sig_make_new_plot = pyqtSignal(str, list)
|
||||||
|
|
||||||
def __init__(self, *args, title="grum", **kwargs):
|
def __init__(self, *args, title="grum", **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.setWindowTitle(title)
|
self.setWindowTitle(title)
|
||||||
@ -24,6 +27,7 @@ class MainWindow(QMainWindow):
|
|||||||
"exp": [X, np.exp(X)],
|
"exp": [X, np.exp(X)],
|
||||||
"log": [X, np.log(X+1)]
|
"log": [X, np.log(X+1)]
|
||||||
}
|
}
|
||||||
|
data = {k: zip(*v) for k, v in data.items()} # due to the appending of xy pairs, data needs to be transposed
|
||||||
self.lst = lst = DictList(data)
|
self.lst = lst = DictList(data)
|
||||||
lst.setAlternatingRowColors(True)
|
lst.setAlternatingRowColors(True)
|
||||||
lst.doubleClicked.connect(self.on_select_list_item)
|
lst.doubleClicked.connect(self.on_select_list_item)
|
||||||
@ -39,18 +43,41 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
self.setCentralWidget(splitter)
|
self.setCentralWidget(splitter)
|
||||||
|
|
||||||
|
rst = RPCServerThread("localhost", 8000)
|
||||||
|
rst.start()
|
||||||
|
rst.server.register_function(self.append)
|
||||||
|
|
||||||
|
self.sig_make_new_plot.connect(self.make_new_plot)
|
||||||
|
|
||||||
|
|
||||||
|
def append(self, name, xy):
|
||||||
|
lst = self.lst
|
||||||
|
show_it = (name not in lst.data)
|
||||||
|
|
||||||
|
lst.append(name, xy)
|
||||||
|
for sub in self.mdi.subWindowList():
|
||||||
|
if sub.windowTitle() == name:
|
||||||
|
data = lst.data[name]
|
||||||
|
data = list(zip(*data))
|
||||||
|
sub.plot.setData(*data)
|
||||||
|
|
||||||
|
if show_it:
|
||||||
|
data = lst.data[name]
|
||||||
|
self.sig_make_new_plot.emit(name, data)
|
||||||
|
|
||||||
|
|
||||||
def on_select_list_item(self, index):
|
def on_select_list_item(self, index):
|
||||||
key, value = self.lst.get(index)
|
key, value = self.lst.get(index)
|
||||||
|
|
||||||
#TODO: just a test for dynamic adding
|
|
||||||
self.lst.add("x", [X, X])
|
|
||||||
|
|
||||||
for sub in self.mdi.subWindowList():
|
for sub in self.mdi.subWindowList():
|
||||||
if sub.windowTitle() == key:
|
if sub.windowTitle() == key:
|
||||||
self.mdi.setActiveSubWindow(sub)
|
self.mdi.setActiveSubWindow(sub)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
self.make_new_plot(key, value)
|
||||||
|
|
||||||
|
|
||||||
|
def make_new_plot(self, key, value):
|
||||||
sub = MDISubPlot(key, value)
|
sub = MDISubPlot(key, value)
|
||||||
self.mdi.addSubWindow(sub)
|
self.mdi.addSubWindow(sub)
|
||||||
sub.show()
|
sub.show()
|
||||||
|
7
mdi.py
7
mdi.py
@ -4,7 +4,7 @@ from PyQt5.QtGui import QPainter
|
|||||||
from pyqtgraph import PlotWidget
|
from pyqtgraph import PlotWidget
|
||||||
|
|
||||||
import assets
|
import assets
|
||||||
from theme import MDI_BKG
|
from theme import MDI_BKG, pg_plot_style
|
||||||
|
|
||||||
|
|
||||||
class MDIArea(QMdiArea):
|
class MDIArea(QMdiArea):
|
||||||
@ -71,8 +71,11 @@ class MDISubPlot(QMdiSubWindow):
|
|||||||
# without this, the SubWindow is not removed from the subWindowList
|
# without this, the SubWindow is not removed from the subWindowList
|
||||||
self.setAttribute(Qt.WA_DeleteOnClose)
|
self.setAttribute(Qt.WA_DeleteOnClose)
|
||||||
|
|
||||||
|
data = zip(*data)
|
||||||
|
style = pg_plot_style()
|
||||||
|
|
||||||
plt = PlotWidget()
|
plt = PlotWidget()
|
||||||
plt.plot(*data)
|
self.plot = plt.plot(*data, **style)
|
||||||
self.setWidget(plt)
|
self.setWidget(plt)
|
||||||
|
|
||||||
|
|
||||||
|
61
rpcserverthread.py
Normal file
61
rpcserverthread.py
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import atexit
|
||||||
|
import xmlrpc.server as xrs
|
||||||
|
from threading import Thread
|
||||||
|
|
||||||
|
|
||||||
|
class RPCServerThread(Thread):
|
||||||
|
|
||||||
|
def __init__(self, host, port, *args, **kwargs):
|
||||||
|
super().__init__(daemon=True) # atexit seems to only work for deamon threads
|
||||||
|
|
||||||
|
addr = (host, port)
|
||||||
|
kwargs.setdefault("allow_none", True)
|
||||||
|
self.server = xrs.SimpleXMLRPCServer(addr, *args, **kwargs)
|
||||||
|
|
||||||
|
self.thread_shutdown = None
|
||||||
|
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
atexit.register(self.wait_for_stop)
|
||||||
|
self.server.serve_forever()
|
||||||
|
|
||||||
|
|
||||||
|
# BaseServer.shutdown docs say:
|
||||||
|
# This must be called while serve_forever() is running in another thread,
|
||||||
|
# or it will deadlock.
|
||||||
|
|
||||||
|
def wait_for_stop(self):
|
||||||
|
if self.thread_shutdown is None:
|
||||||
|
self.stop()
|
||||||
|
self.thread_shutdown.join()
|
||||||
|
print("RPC server stopped")
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.thread_shutdown = t = Thread(target=self.shutdown)
|
||||||
|
t.start()
|
||||||
|
|
||||||
|
def shutdown(self):
|
||||||
|
self.server.shutdown()
|
||||||
|
self.server.server_close()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
from time import sleep
|
||||||
|
|
||||||
|
def test():
|
||||||
|
print("test")
|
||||||
|
return "test"
|
||||||
|
|
||||||
|
rst = RPCServerThread("localhost", 8000)
|
||||||
|
rst.server.register_function(test)
|
||||||
|
rst.server.register_function(rst.stop)
|
||||||
|
rst.start()
|
||||||
|
|
||||||
|
while rst.is_alive():
|
||||||
|
sleep(1)
|
||||||
|
|
||||||
|
|
||||||
|
|
Reference in New Issue
Block a user