2017-06-01 94 views
-1

我对编程真的很陌生,最近我不得不用PyQt做GUI。基本上它是读取来自Arduino串口上的一些数据,并每Arduino发送100个数值更新图形。还有一个日志功能可将数据记录到格式化文件中。一切似乎工作正常,但现在我的程序停止工作,并显示一条消息说python停止工作弹出。我试了几次,随机弹出相同的消息。你能帮我解决这个问题吗?PyQt5中的访问冲突错误

主要来自我在其他一些论坛上阅读的内容,这个问题出现在我的主窗口类使用的PlotThread类中。我不知道那是什么问题,以及如何解决它。这里是Window和PlotThread类。

感谢,

西蒙·贝勒马尔

class Window(QDialog): 
    def __init__(self, parent=None): 
    super(Window, self).__init__(parent) 

    self.log_x = np.array([]) 
    self.log_y = np.array([]) 
    self.test_id = '' 
    self.plot_thread = PlotThread() 
    self.plot_thread.main = self 
    self.figure = plt.figure() 

    # Canvas Widget 
    self.canvas = FigureCanvas(self.figure) 

    # Navigation Widget 
    self.toolbar = NavigationToolbar(self.canvas, self) 

    # Button to control plot function 
    self.control_plot = QPushButton('Start') 
    self.control_plot.clicked.connect(self.plot) 

    # Button to log data 
    self.log_data = QPushButton('Log') 
    self.log_data.clicked.connect(self.log_file) 

    # Progress bar to indicate data harvesting speed 
    self.progressBar = QProgressBar(self) 
    self.progressBar.setGeometry(QRect(10, 10, 200, 25)) 
    self.progressBar.move(500, 10) 

    # Layout 
    layout = QVBoxLayout() 
    layout.addWidget(self.toolbar) 
    layout.addWidget(self.canvas) 
    layout.addWidget(self.control_plot) 
    layout.addWidget(self.log_data) 
    self.setLayout(layout) 

    # Initialising the plot figure 
    self.fig1 = self.figure.add_subplot(111) 
    rect = self.fig1.patch 
    rect.set_facecolor('white') 
    self.fig1.set_xlabel('time [s]') 
    self.fig1.set_ylabel('RSSI [dBm]') 
    self.fig1.grid(True) 
    self.fig1.spines["top"].set_visible(False) 
    self.fig1.spines["right"].set_visible(False) 
    self.fig1.spines["bottom"].set_visible(False) 
    self.fig1.spines["left"].set_visible(False) 

    def log_file(self): 
    directory = ''.join(filter(str.isalpha, self.test_id)) 

    # Creating the directory if it doesn't exist 
    create_directory(directory) 

    # Creating the file if it doesn't exist 
    if not os.path.isfile(
      'C:\\Users\\Simon\\Documents\\Ete2017\\PythonCode\\main\\{0}\\{1}.txt'.format(directory, 
                         self.test_id)): 
     log = open('C:\\Users\\Simon\\Documents\\Ete2017\\PythonCode\\main\\{0}\\{1}.txt'.format(directory, 
                           self.test_id), 
        'w') 
     # Creating the header 
     log.write(' ' * 9 + 'Time [s]' + ' ' * 9 + '|' + ' ' * 4 + 'RSSI [dBm] \n') 
    else: 
     log = open('C:\\Users\\Simon\\Documents\\Ete2017\\PythonCode\\main\\{0}\\{1}.txt'.format(directory, 
                           self.test_id), 
        'a') 

    # Logging the data 
    for i in range(np.size(self.log_x)): 
     x = str(self.log_x[i]) 
     space_num = 24 - len(x) 
     log.write(' ' * space_num + x + " |" + ' ' * 5 + str(self.log_y[i]) + ' \n') 

    # Reinitialising logging 
    self.log_x = np.array([]) 
    self.log_y = np.array([]) 

    def pause(self): 
    self.plot_thread.terminate() 
    self.control_plot.setText('Start') 
    self.control_plot.clicked.connect(self.plot) 
    self.log_data.setText('Log') 
    self.log_data.clicked.connect(self.log_file) 

    def plot(self): 
    self.control_plot.setText('Pause') 
    self.control_plot.clicked.connect(self.pause) 
    self.log_data.setText('') 
    self.log_data.clicked.connect(self.wait) 

    self.plot_thread.start() 

    def wait(self): 
    pass 

class PlotThread(QThread): 
    def __init__(self): 
     QThread.__init__(self) 
     self.main = '' 
     self.t_start = 0 
     self.ser = ser 

     # Replace by expected values at time 0s 
     self.xf = 0 
     self.yf = -43 

    def run(self): 
     while self.isRunning(): 
      print("Starting to plot") 
      self.ser.flushInput() 
      self.t_start = time.time() 
      # Preallocating memory for the arrays 
      x = np.empty([100]) 
      y = np.empty([100]) 

      # Initializing start values 
      x[0] = self.xf 
      y[0] = self.yf 
      self.main.progressBar.setValue(1) 

      # Reading data from the Arduino 
      for i in range(99): 
       reading = str(ser.readline()) 
       while not reading[3:5].isdigit(): 
        reading = str(ser.readline()) 
       y[i + 1] = -int(reading[3:5]) 
       x[i + 1] = self.xf + (time.time() - self.t_start) 
       print(x[i]) 
       self.main.progressBar.setValue(i + 1) 

      # Preparing start values for next iteration 
      self.xf = x[99] 
      self.yf = y[99] 

      # Preparing the log variables 
      self.main.log_x = np.append(self.main.log_x, x) 
      self.main.log_y = np.append(self.main.log_y, y) 

      # Plotting raw data 
      self.main.fig1.plot(x, y, 'r--') 

      # Filtering raw data 
      poly8 = np.polyfit(x, y, 8) 
      xGraph = np.linspace(x[0], x[99], num=200) 
      yGraph = np.polyval(poly8, xGraph) 

      # Graphing filtered data 
      self.main.fig1.plot(xGraph, yGraph, 'b') 
      # Saving the graph into a file 
      timer = self.xf + time.time() - self.t_start 
      # Scaling the axes 
      if timer > 80: 
       print("Scaling the axes") 
       self.main.fig1.set_xlim([int(timer) - 80, timer]) 

      # refresh canvas 
      self.main.canvas.draw() 
      self.main.canvas.flush_events() 

回答

0

may not与GUI在非主线程交互:

如前所述,每个程序都有一个线程在启动时。这个线程被称为“主线程”(在Qt应用程序中也称为“GUI线程”)。 Qt GUI必须在这个线程中运行。所有小部件和几个相关的类(例如QPixmap)都不能在辅助线程中使用。辅助线程通常被称为“辅助线程”,因为它用于从主线程卸载处理工作。