前提・実現したいこと
ここに質問の内容を詳しく書いてください。
Python 3.8.10 でブラウザとサーバーの並列起動をするシステムを作っています。
ブラウザはQt5で作成し、現在表示されているウィンドウ画像を frame 変数に保持するようにします。サーバーは、その frame 画像を取得することを目的としています。
QtでのGUI実装について明るくないのですが、サーバー側から capture() を呼び、frame を取得することは、以下のようなエラーが発生し、別スレッドからは厳しいようです。
**Cannot make QOpenGLContext current in a different thread**
また、更新処理に該当する update_frame() をバックグラウンドで回し続けるために、 Thread を使ってみましたが、こちらも以下のようなエラーが発生し、不可能でした。
❯ python browser.py QObject::setParent: Cannot set parent, new parent is in a different thread Cannot make QOpenGLContext current in a different thread [1] 7703 abort (core dumped) python browser.py
該当のソースコードは以下になります。
該当のソースコード
python
1# browser.py 2import sys 3from PyQt5.QtCore import Qt 4from PyQt5.QtCore import QUrl 5from PyQt5.QtCore import QTimer 6from PyQt5.QtGui import QPixmap 7from PyQt5.QtGui import QImage 8from PyQt5.QtWebEngineWidgets import QWebEngineView 9from PyQt5.QtWidgets import QApplication 10import numpy as np 11import threading 12 13def qim2cv(qimage): 14 w, h, d = qimage.size().width(), qimage.size().height(), qimage.depth() 15 bytes_ = qimage.bits().asstring(w * h * d // 8) 16 arr = np.frombuffer(bytes_, dtype=np.uint8).reshape((h, w, d // 8)) 17 return arr 18 19class BrowserApp(): 20 def __init__(self, size=(1000,600), url="https://www.google.com/?hl=ja"): 21 self.app = QApplication(sys.argv) 22 self.window_size = size 23 self.browser = QWebEngineView() 24 self.browser.resize(*self.window_size) 25 self.browser.load(QUrl(url)) 26 self.url = url 27 self.frame = None # 常に最新のブラウザキャプチャを保持したい 28 29 def update_frame(self): 30 while True: 31 self.frame = self.capture() 32 33 def capture(self): 34 ## ブラウザの表示画像からフレームを更新 35 browser_size = self.browser.contentsRect() 36 pixmap_img = QPixmap(browser_size.width(), browser_size.height()) 37 self.browser.render(pixmap_img) 38 return qim2cv(pixmap_img.toImage()) # OpenCV 画像に変換 39 40 def show(self): 41 self.browser.show() 42 self.app.exec_() 43 44 45if __name__ == "__main__": 46 app = BrowserApp() 47 48 # バックグラウンドで更新させたい 49 thread = threading.Thread(target=app.update_frame) 50 thread.start() 51 52 app.show()
試したこと
- 更新処理を除けば、ブラウザが正常に起動することは確認しました。
- capture() では、画面のスクリーンショットを撮れることを確認しました。
補足情報(FW/ツールのバージョンなど)
OS: Linux(OpenSUSE Leap 15.3)
Python環境: python 3.8.10(Pyenv)
サーバー側はfastapiを使用しています。
皆様のご助力に感謝いたします。
よろしくお願いいたします。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/06/30 06:38