2015-01-21 5 views
1

В моей эпической борьбе за обработку необработанных данных мыши на моей ubuntu (14.04) ОС с python, с большой помощью отсюда я снова застрял. Мне очень сложно понять «легкость» пикграфа. все, что я хочу сделать, это обернуть код, который у меня теперь есть, в красивый маленький gui с кнопкой start/pause/stop, виджет списка, чтобы показать цифры и сюжет, чтобы я мог видеть, что происходит. Я думаю, главная проблема для меня в том, что я не совсем понимаю эту вещь в pyqt. в любом случае, принимая «легкий» пример, который имеет виджеты я хочу, я не в состоянии реализовать свой код (отредактированного более минималистичный):Python realtime mousedata с pyqtgraph

#!/usr/bin/python 
import threading 
import struct 
import time 
import numpy as np 

from PyQt4 import QtGui # (the example applies equally well to PySide) 
from PyQt4 import QtCore 
import pyqtgraph as pg 
## 
data =[(0,0)] 
sum_data = [(0,0)] 
file = open("/dev/input/mouse2", "rb") 

def getMouseEvent(): 
    buf = file.read(3); 
    #python 2 & 3 compatibility 
    button = buf[0] if isinstance(buf[0], int) else ord(buf[0]) 
    x,y = struct.unpack("bb", buf[1:]); 
    print x,y 
    return x, y 

def mouseCollect(): 
    while True:   
    data.append(getMouseEvent()) 
    sum_data.append(tuple(map(sum,zip(sum_data[-1],data[-1])))) 
    plot.plot(sum_data[0], clear=True) 
    pg.QtGui.QApplication.processEvents() 
    print sum_data[-1]  

## Always start by initializing Qt (only once per application) 
app = QtGui.QApplication([]) 

## Define a top-level widget to hold everything 
w = QtGui.QWidget() 

## Create some widgets to be placed inside 
btn1 = QtGui.QPushButton('Start') 

listw = QtGui.QListWidget() 
plot = pg.PlotWidget() 

def start_btn(): 
    print 'test' 
    threading.Thread(target=mouseCollect).start() 

btn1.clicked.connect(start_btn) 

## Create a grid layout to manage the widgets size and position 
layout = QtGui.QGridLayout() 
w.setLayout(layout)  
## Add widgets to the layout in their proper positions 
layout.addWidget(btn1, 0, 0) # button goes in upper-left 
layout.addWidget(plot, 0, 1, 4, 1)  
## Display the widget as a new window 
w.show()  
## Start the Qt event loop 
app.exec_() 
##------------------------------------------------------------------ 

, когда я нажимаю кнопку запуска, окно просто замирает и ничего не происходит. моя мысль была, если я нажимаю кнопку, она соединяется с состоянием methot там, и это просто делает свое дело. хорошо, у меня бесконечный цикл, но по крайней мере я думал, что должен что-то увидеть. любая помощь приветствуется, а также любые советы для хорошего чтения по этому вопросу очень приветствуются.

рассматривает Edit: вставили нить, как предложено echocage

+0

Можете ли вы обеспечить [ минимальный пример] (http://stackoverflow.com/help/mcve)? Если вы говорите, что кнопка работает, и вызывается 'mouseCollect', то проблема только в' mouseCollect' - ни одна из кнопок не нужна вообще в этом примере. Кроме того, убедитесь, что ваш отступ правильный. – Lack

+0

Отредактировано. Я не знаю, где больше сократить и все еще будет полным :) Протестировано и имеет ту же проблему. Спасибо. – user3759978

+0

Итак, я думаю, что проблема в том, что вы используете mouseCollect в том же потоке. Поскольку вы в ожидании всегда находитесь в цикле, когда обработчик события мыши не возвращает его, он замораживает графический интерфейс. Попробуйте запустить mouseCollect в новом потоке, чтобы избежать этого, хотя я не могу сказать вам, как PyQT обрабатывает многопоточные вызовы. Вы можете сделать это путем импорта темы из модуля многопоточности и вызова 'темы (цель = mouseCollect) .start()' Вы только должны сделать это один раз, вы, вероятно, могли бы это сделать даже в главном корпусе программы – Echocage

ответ

0

Я наконец нашел его. Я как-то никогда не осознавал, что вам нужно использовать массивы numpy. также я не использовал curve.setdata для построения графика.

более или менее окончательный код (не полный код) теперь выглядит следующим образом:

class mouseCollect(QtCore.QThread): 
    def __init__(self): 

     QtCore.QThread.__init__(self) 

    def run (self): 
     global e, curve, curve2, data1, data2 
     while e.wait(): 
     tmp = getMouseEvent() #returns tuples in form of (x,y) 
     data1 = np.append(data1, tmp[0]) 
     data2 = np.append(data2, tmp[1]) 
     sum1= np.cumsum(data1) 
     sum2= np.cumsum(data2)  

     curve.setData(y=sum1) 
     curve2.setData(y=sum2) 
     guiPE # process event thingy 

    def stop(self): 
     e.clear() 

ну, это на самом деле не написано эффективно, но это работает :)

2

Лучший подход для повторяющихся обновлений является использование QTimer. Таким образом вы позволяете программному управлению вернуться к циклу событий Qt после каждого обновления (без бесконечных циклов), а Qt периодически вызывает вашу функцию обновления для вас.

Например, см один из многих на обновление примеры сюжетные включены pyqtgraph: https://github.com/pyqtgraph/pyqtgraph/blob/develop/examples/Plotting.py#L58

Threading очень трудно сделать правильно, и когда это будет сделано неправильно, то вы обычно в конечном итоге с грохотом, что трудно отлаживать. Я рекомендую избегать нарезки резьбы, пока вы не будете очень уверены в системе событий и знакомы с подводными камнями резьбы.

+0

Спасибо за ваше мнение. У меня теперь есть обе версии (потоковые и таймерные).версия таймера работает нормально, но она зависает, когда я пытаюсь использовать другое устройство ввода для нажатия кнопок и т. д. так что я думаю, так как у взломанной версии нет проблем на данный момент, я буду придерживаться этого решения ^^ – user3759978