2017-06-01 91 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)都不能在輔助線程中使用。輔助線程通常被稱爲「輔助線程」,因爲它用於從主線程卸載處理工作。