質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.26%

[pyqt5-pyton] mainwindowにcanvasが表示されない

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 61

Kenza

score 15

pyqt5-pythonで簡単なお絵描きツールを作っています。
今、mainwindow内に、canvas,predictcanvas,button類(tools)を並列させて、表示させようとしているのですが、なぜかpredictcanvasだけ表示されません。。。

表示できる解決策、よろしくお願いいたします。

以下は実行したコードです

環境:windows10

import sys
from PyQt5.QtWidgets import (
  QWidget, QApplication, QMainWindow, QAction,
  QFileDialog, QColorDialog, QInputDialog, QPushButton,QHBoxLayout, QVBoxLayout, QApplication)
from PyQt5.QtGui import QPainter, QImage, QPen, qRgb
from PyQt5.QtCore import Qt, QPoint, QRect, QSize, QDir
from collections import deque
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtGui import QIcon

class MainWindow(QMainWindow):
  def __init__(self):
    super(MainWindow, self).__init__()
    self.setupUI()
    self.setCentralWidget(self.initUI())
    #クラスを呼び出す。

  def initUI(self):
        frame = QWidget(self)
        self.canvas = Canvas(frame)
        tools = ToolFrame(frame)
        predict=PredictCanvas(frame)
        hbox = QHBoxLayout(frame)
        #vbox=QVBoxLayout()
        #vbox.addStretch(0)
        #vbox.addWidget(tools)
        #vbox.addWidget(predict)
        hbox.addWidget(self.canvas)
        hbox.addWidget(predict)
        hbox.addWidget(tools)
        return frame

  def setupUI(self):
    menubar = self.menuBar()

    openAct = QAction('&Open', self)
    openAct.setShortcut('Ctrl+O')
    openAct.triggered.connect(self.openFile)

    exitAct = QAction('&Exit', self)
    exitAct.setShortcut('Ctrl+Q')
    exitAct.triggered.connect(self.close)

    saveAct = QAction('&Save', self)
    saveAct.setShortcut('Ctrl+S')
    saveAct.triggered.connect(self.saveFile)

    fileMenu = menubar.addMenu('&File')
    #fileMenu.addAction(resetAct)
    fileMenu.addAction(openAct)
    fileMenu.addAction(saveAct)
    fileMenu.addAction(exitAct)

    # 画像付き Pencolor selectするアクションオブジェクト作成
    selectColorAction = QAction( QIcon('sample/white-bear.png'),'Pen Color', self)
    selectColorAction.setShortcut('Ctrl+A')
    selectColorAction.triggered.connect(self.selectColor)
    self.toolbar = self.addToolBar('Pen Color')
    self.toolbar.addAction(selectColorAction)

    # ツールバー作成
    selectwidthAction = QAction( QIcon('sample/white-bear.png'),'Selecwidth', self)
    selectwidthAction.triggered.connect(self.selectWidth)
    self.toolbar = self.addToolBar('Width')
    self.toolbar.addAction(selectwidthAction)

    # ツールバー作成
    backAction = QAction( QIcon('sample/white-bear.png'),'Back', self)
    backAction.setShortcut('Ctrl+Z')
    backAction.triggered.connect(self.on_back)
    self.toolbar = self.addToolBar('Undo')
    self.toolbar.addAction(backAction)

    # ツールバー作成
    clearAction = QAction( QIcon('sample/white-bear.png'),'Clear', self)
    clearAction.setShortcut('Ctrl+B')
    clearAction.triggered.connect(self.on_reset)
    self.toolbar = self.addToolBar('Undo')
    self.toolbar.addAction(clearAction)

  @pyqtSlot()
  def on_back(self):
    print('PyQt5 button click')
    self.canvas.backImage()

  @pyqtSlot()
  def on_reset(self):
    self.canvas.resetImage()

  @pyqtSlot()
  def on_run(self):
    fileName, _ = QFileDialog.getOpenFileName(self, "Open File", QDir.currentPath())

    if fileName:
      self.predict_canvas.PredictImage(fileName)
      #self.canvas.openImage(fileName)

  def selectColor(self):
    newColor = QColorDialog.getColor(self.canvas.penColor())
    self.canvas.setPenColor(newColor)

  def selectWidth(self):
    newWidth, ok = QInputDialog.getInt(
      self, "select",
      "select pen width: ", self.canvas.penWidth(), 1, 100, 1)
    if ok:
      self.canvas.setPenWidth(newWidth)

  def openFile(self):
    fileName, _ = QFileDialog.getOpenFileName(self, "Open File", QDir.currentPath())
    if fileName:
      self.canvas.openImage(fileName)

  def saveFile(self):
    path = QDir.currentPath()
    print(path)
    fileName, _ = QFileDialog.getSaveFileName(self, "Save as",path)
    fileName=fileName+'.png'
    if fileName:
      print(fileName)
      return self.canvas.saveImage(fileName)
    else:
      print("you couldnt save the file")
    return False

class ToolFrame(QWidget):
    def __init__(self, parent=None, *args, **kw):
        super().__init__(parent, *args, **kw)
        self.predict=PredictCanvas()
        self.initUI()

    def initUI(self):
        button_predict = QPushButton('predict', self)
        button_predict.clicked.connect(self.on_run)


        button_reset = QPushButton('Reset', self)

        vbox = QVBoxLayout(self)
        vbox.addStretch(1)
        vbox.addWidget(button_predict)
        vbox.addWidget(button_reset)

    @pyqtSlot()
    def on_run(self):
      fileName, _ = QFileDialog.getOpenFileName(self, "Open File", QDir.currentPath())

      if fileName:
        self.predict.PredictImage(fileName)
        #self.canvas.openImage(fileName)

class Canvas(QWidget):
  def __init__(self, parent = None):
    super(Canvas, self).__init__(parent)

    self.myPenWidth = 2
    self.myPenColor = Qt.black
    self.image = QImage()
    self.check = False
    self.back = deque(maxlen = 10)
    self.image = QImage(300, 300, QImage.Format_RGB32)
    self.image.fill(qRgb(255, 255, 255))
    #self.next = deque(maxlen = 10)
    # initUIはもう必要ないから消しておこうね


  def mousePressEvent(self, event):
    if event.button() == Qt.LeftButton:
      self.back.append(self.resizeImage(self.image, self.image.size()))
      self.lastPos = event.pos()
      self.check = True

  def mouseMoveEvent(self, event):
    if event.buttons() and Qt.LeftButton and self.check:
      self.drawLine(event.pos())

  def mouseReleaseEvent(self, event):
    if event.button() == Qt.LeftButton and self.check:
      self.drawLine(event.pos())
      self.check = False

  def drawLine(self, endPos):
    painter = QPainter(self.image)
    painter.setPen(
      QPen(self.myPenColor, self.myPenWidth, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)
    )
    painter.drawLine(self.lastPos, endPos)
    self.update()
    self.lastPos = QPoint(endPos)

  def paintEvent(self, event):
    painter = QPainter(self)
    rect = event.rect()
    painter.drawImage(rect, self.image, rect)

  def resizeEvent(self, event):
    if self.image.width() < self.width() or self.image.height() < self.height():
      changeWidth = max(self.width(), self.image.width())
      changeHeight = max(self.height(), self.image.height())
      self.image = self.resizeImage(self.image, QSize(changeWidth, changeHeight))
      self.update()

  def resizeImage(self, image, newSize):
    changeImage = QImage(newSize, QImage.Format_RGB32)
    changeImage.fill(qRgb(255, 255, 255))
    painter = QPainter(changeImage)
    painter.drawImage(QPoint(0, 0), image)
    return changeImage

  def saveImage(self, filename):
    if self.image.save(filename):
      return True
    else:
      return False

  def openImage(self, filename):
    image = QImage()
    if not image.load(filename):
      return False

    self.image = image
    self.update()
    return True

  def penColor(self):
    return self.myPenColor

  def penWidth(self):
    return self.myPenWidth

  def setPenColor(self, newColor):
    self.myPenColor = newColor

  def setPenWidth(self, newWidth):
    self.myPenWidth = newWidth

  def resetImage(self):
    self.image.fill(qRgb(255, 255, 255))
    self.update()

  def backImage(self):
    if self.back:
      back_ = self.back.pop()
      #self.next.append(back_)
      self.image = QImage(back_)
      self.update()


class PredictCanvas(QWidget):
  def __init__(self, parent = None):
    super(PredictCanvas, self).__init__(parent)

    self.image_predict = QImage()
    self.image_predict.fill(qRgb(255, 0, 255))

  def PredictImage(self, filename):
    image = QImage()
    if not image.load(filename):
      return False

    self.image_predict = image
    self.update()
    return True

def main():
  app = QApplication(sys.argv)
  ex = MainWindow()
  ex.setWindowTitle('Paint Tools')
  ex.setGeometry(50, 50, 1400, 800)
  ex.show()
  sys.exit(app.exec_())

if __name__ == '__main__':
  main()
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+2

なぜかpredictcanvasだけ表示されません

複数の問題があります

  • predictcanvas が表示されない (画面中央の領域)
    paintEvent がない
  • 読み込んだ画像が反映されない (ファイル選択時のイベント)
    ToolFrame 内で別の PredictCanvas() を生成?

まず、表示されていますが、表示するものが何もない状態です。

  • QImageを準備しているが、サイズが 0 
  • QImageは準備されただけで、何処にも描画されてない
    Canvas クラスと同様に paintEvent メソッドを実装しましょう。

次に、ファイルを選択したときの挙動ですが

画面中央に表示されているのは、MainWindowのpredict
ToolFrameのon_run()で呼び出しているのは、
ToolFrame内で生成されたPredictCanvas()と、それぞれ異なるものです。

メインウィンドウ側のpredict canvas のメソッドを呼び出すことで
問題自体は解決できますが、親ウィジェットを辿ってアクセスするのは、
クラスの利便性を損なうので、あまりお勧めしません。

Qtのシグナル/スロットを使った解消法を提案

  • (1) ToolFrame でファイル選択時のシグナルを定義します
    fileSelected = pyqtSignal(str)
  • (2) PredictCanvas 側で、ファイルを読み込むスロットを定義します
    @pyqtSlot ... def loadImage(self, filename)
  • (3) MainWindow で双方を接続する
    tools.fileSelected.connect(predict.loadImage)
  • (4) シグナル発火
    ToolFrame.on_run メソッド内 で self.fileSelected.emit(filename) 

PyQt5 でのシグナル/スロットの使い方は
PyQt5 signals_slots 等を参考に、コードの書き方は調べて下さい。

追記:

因みに、pyqtではスロットの宣言は省略可能で、引数さえ一致すればよく
例えば、Canva.openImage にも connect することができます。

tools.fileSelected.connect(self.canvas.openImage)

ToolFrame.on_runから親にアクセス
self.parent().predict.loadImage(fileName) みたいなコードは、
MainWindowに依存したコードになり、クラス・オブジェクトの構造が変わると使えなくなりますが、
シグナル・スロットを用いることで、利用側が振る舞いを決められるようになり、
ウィジェットの部品としての再利用性が高まります。


--- main.orig.py    2020-05-23 14:52:14.587404600 +0900
+++ main.py    2020-05-23 14:55:03.595347700 +0900
@@ -5,7 +5,7 @@
 from PyQt5.QtGui import QPainter, QImage, QPen, qRgb
 from PyQt5.QtCore import Qt, QPoint, QRect, QSize, QDir
 from collections import deque
-from PyQt5.QtCore import pyqtSlot
+from PyQt5.QtCore import pyqtSlot, pyqtSignal
 from PyQt5.QtGui import QIcon

 class MainWindow(QMainWindow):
@@ -28,6 +28,9 @@
         hbox.addWidget(self.canvas)
         hbox.addWidget(predict)
         hbox.addWidget(tools)
+
+        tools.fileSelected.connect(predict.loadImage)
+
         return frame

   def setupUI(self):
@@ -124,9 +127,11 @@
     return False

 class ToolFrame(QWidget):
+
+    fileSelected = pyqtSignal(str)
+
     def __init__(self, parent=None, *args, **kw):
         super().__init__(parent, *args, **kw)
-        self.predict=PredictCanvas()
         self.initUI()

     def initUI(self):
@@ -146,7 +151,7 @@
       fileName, _ = QFileDialog.getOpenFileName(self, "Open File", QDir.currentPath())

       if fileName:
-        self.predict.PredictImage(fileName)
+        self.fileSelected.emit(fileName)
         #self.canvas.openImage(fileName)

 class Canvas(QWidget):
@@ -253,7 +258,12 @@
     self.image_predict = QImage()
     self.image_predict.fill(qRgb(255, 0, 255))

-  def PredictImage(self, filename):
+  def paintEvent(self, event):
+    painter = QPainter(self)
+    painter.drawImage(0, 0, self.image_predict)
+
+  @pyqtSlot(str)
+  def loadImage(self, filename):
     image = QImage()
     if not image.load(filename):
       return False

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

※投稿後追記:
動くコードにはなっていますが、当方の知識不足の点が多々あると思います。上のteamiklさんの回答の方が正確なため、teamiklさんの回答&コードを参考にしてください。

① 削除
② PredictCanvasで下記のようにpaintEventを実装してあげないと、描画更新されません。

  def paintEvent(self, event):
    painter = QPainter(self)
    rect = event.rect()
    painter.drawImage(rect, self.image_predict, rect)

③ 元コードでは、ToolFrame(QWidget)で新たにPredictCanvasが生成されてしまっており、メインウィジェットのpredict(predict_canvas)が共有されていません。

下記のように、メインウィジェットのpredict_canvasをToolFrame(QWidget)が受け取れるように修正する必要があります。

呼び出し元

  def initUI(self):
        frame = QWidget(self)
        self.canvas = Canvas(frame)

        self.predict_canvas = PredictCanvas(frame)
        tools = ToolFrame(frame, canvas=self.predict_canvas) #修正部分 メインウィジェットのpredict_canvsを引数として呼び出す。

呼び出し先

class ToolFrame(QWidget):
    def __init__(self, parent=None, canvas = None): 修正
        super().__init__(parent)
        self.predict = canvas  # 修正 メインウィジェットのpredict_canvasを受け取る
        self.initUI()

以上をまとめた全体コードが、下記のコードです。

import sys
from PyQt5.QtWidgets import (
  QWidget, QApplication, QMainWindow, QAction,
  QFileDialog, QColorDialog, QInputDialog, QPushButton,QHBoxLayout, QVBoxLayout, QApplication)
from PyQt5.QtGui import QPainter, QImage, QPen, qRgb
from PyQt5.QtCore import Qt, QPoint, QRect, QSize, QDir
from collections import deque
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtGui import QIcon

class MainWindow(QMainWindow):
  def __init__(self):
    super(MainWindow, self).__init__()
    self.setupUI()
    self.setCentralWidget(self.initUI())
    #クラスを呼び出す。

  def initUI(self):
        frame = QWidget(self)
        self.canvas = Canvas(frame)

        self.predict_canvas = PredictCanvas(frame)
        tools = ToolFrame(frame, canvas=self.predict_canvas)
        hbox = QHBoxLayout(frame)
        #vbox=QVBoxLayout()
        #vbox.addStretch(0)
        #vbox.addWidget(tools)
        #vbox.addWidget(predict)
        hbox.addWidget(self.canvas)
        hbox.addWidget(self.predict_canvas)
        hbox.addWidget(tools)

        # frame.setLayout(hbox)  # 9行目前でQHBoxLayout(frame)というように親を指定しているため不要

        return frame

  def setupUI(self):
    menubar = self.menuBar()

    openAct = QAction('&Open', self)
    openAct.setShortcut('Ctrl+O')
    openAct.triggered.connect(self.openFile)

    exitAct = QAction('&Exit', self)
    exitAct.setShortcut('Ctrl+Q')
    exitAct.triggered.connect(self.close)

    saveAct = QAction('&Save', self)
    saveAct.setShortcut('Ctrl+S')
    saveAct.triggered.connect(self.saveFile)

    fileMenu = menubar.addMenu('&File')
    #fileMenu.addAction(resetAct)
    fileMenu.addAction(openAct)
    fileMenu.addAction(saveAct)
    fileMenu.addAction(exitAct)

    # 画像付き Pencolor selectするアクションオブジェクト作成
    selectColorAction = QAction( QIcon('sample/white-bear.png'),'Pen Color', self)
    selectColorAction.setShortcut('Ctrl+A')
    selectColorAction.triggered.connect(self.selectColor)
    self.toolbar = self.addToolBar('Pen Color')
    self.toolbar.addAction(selectColorAction)

    # ツールバー作成
    selectwidthAction = QAction( QIcon('sample/white-bear.png'),'Selecwidth', self)
    selectwidthAction.triggered.connect(self.selectWidth)
    self.toolbar = self.addToolBar('Width')
    self.toolbar.addAction(selectwidthAction)

    # ツールバー作成
    backAction = QAction( QIcon('sample/white-bear.png'),'Back', self)
    backAction.setShortcut('Ctrl+Z')
    backAction.triggered.connect(self.on_back)
    self.toolbar = self.addToolBar('Undo')
    self.toolbar.addAction(backAction)

    # ツールバー作成
    clearAction = QAction( QIcon('sample/white-bear.png'),'Clear', self)
    clearAction.setShortcut('Ctrl+B')
    clearAction.triggered.connect(self.on_reset)
    self.toolbar = self.addToolBar('Undo')
    self.toolbar.addAction(clearAction)

  @pyqtSlot()
  def on_back(self):
    print('PyQt5 button click')
    self.canvas.backImage()

  @pyqtSlot()
  def on_reset(self):
    self.canvas.resetImage()

  @pyqtSlot()
  def on_run(self):
    fileName, _ = QFileDialog.getOpenFileName(self, "Open File", QDir.currentPath())

    if fileName:
      self.predict_canvas.PredictImage(fileName)
      #self.canvas.openImage(fileName)

  def selectColor(self):
    newColor = QColorDialog.getColor(self.canvas.penColor())
    self.canvas.setPenColor(newColor)

  def selectWidth(self):
    newWidth, ok = QInputDialog.getInt(
      self, "select",
      "select pen width: ", self.canvas.penWidth(), 1, 100, 1)
    if ok:
      self.canvas.setPenWidth(newWidth)

  def openFile(self):
    fileName, _ = QFileDialog.getOpenFileName(self, "Open File", QDir.currentPath())
    if fileName:
      self.predict_canvas.PredictImage(fileName)

  def saveFile(self):
    path = QDir.currentPath()
    print(path)
    fileName, _ = QFileDialog.getSaveFileName(self, "Save as",path)
    fileName=fileName+'.png'
    if fileName:
      print(fileName)
      return self.canvas.saveImage(fileName)
    else:
      print("you couldnt save the file")
    return False

class ToolFrame(QWidget):
    def __init__(self, parent=None, canvas = None):
        super().__init__(parent)
        self.predict = canvas  # PredictCanvas()
        self.initUI()

    def initUI(self):
        button_predict = QPushButton('predict', self)
        button_predict.clicked.connect(self.on_run)


        button_reset = QPushButton('Reset', self)

        vbox = QVBoxLayout(self)
        vbox.addStretch(1)
        vbox.addWidget(button_predict)
        vbox.addWidget(button_reset)

    @pyqtSlot()
    def on_run(self):
      fileName, _ = QFileDialog.getOpenFileName(self, "Open File", QDir.currentPath())

      if fileName:
        self.predict.PredictImage(fileName)
        #self.canvas.openImage(fileName)

class Canvas(QWidget):
  def __init__(self, parent = None):
    super(Canvas, self).__init__(parent)

    self.myPenWidth = 2
    self.myPenColor = Qt.black
    self.image = QImage()
    self.check = False
    self.back = deque(maxlen = 10)
    self.image = QImage(300, 300, QImage.Format_RGB32)
    self.image.fill(qRgb(255, 255, 255))
    #self.next = deque(maxlen = 10)
    # initUIはもう必要ないから消しておこうね


  def mousePressEvent(self, event):
    if event.button() == Qt.LeftButton:
      self.back.append(self.resizeImage(self.image, self.image.size()))
      self.lastPos = event.pos()
      self.check = True

  def mouseMoveEvent(self, event):
    if event.buttons() and Qt.LeftButton and self.check:
      self.drawLine(event.pos())

  def mouseReleaseEvent(self, event):
    if event.button() == Qt.LeftButton and self.check:
      self.drawLine(event.pos())
      self.check = False

  def drawLine(self, endPos):
    painter = QPainter(self.image)
    painter.setPen(
      QPen(self.myPenColor, self.myPenWidth, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)
    )
    painter.drawLine(self.lastPos, endPos)
    self.update()
    self.lastPos = QPoint(endPos)

  def paintEvent(self, event):
    painter = QPainter(self)
    rect = event.rect()
    painter.drawImage(rect, self.image, rect)

  def resizeEvent(self, event):
    if self.image.width() < self.width() or self.image.height() < self.height():
      changeWidth = max(self.width(), self.image.width())
      changeHeight = max(self.height(), self.image.height())
      self.image = self.resizeImage(self.image, QSize(changeWidth, changeHeight))
      self.update()

  def resizeImage(self, image, newSize):
    changeImage = QImage(newSize, QImage.Format_RGB32)
    changeImage.fill(qRgb(255, 255, 255))
    painter = QPainter(changeImage)
    painter.drawImage(QPoint(0, 0), image)
    return changeImage

  def saveImage(self, filename):
    if self.image.save(filename):
      return True
    else:
      return False

  def openImage(self, filename):
    image = QImage()
    if not image.load(filename):
      return False

    self.image = image
    self.update()
    return True

  def penColor(self):
    return self.myPenColor

  def penWidth(self):
    return self.myPenWidth

  def setPenColor(self, newColor):
    self.myPenColor = newColor

  def setPenWidth(self, newWidth):
    self.myPenWidth = newWidth

  def resetImage(self):
    self.image.fill(qRgb(255, 255, 255))
    self.update()

  def backImage(self):
    if self.back:
      back_ = self.back.pop()
      #self.next.append(back_)
      self.image = QImage(back_)
      self.update()

# teratail 264079 modified by taizan-hokuto
class PredictCanvas(QWidget):
  def __init__(self, parent = None):
    super(PredictCanvas, self).__init__(parent)

    self.image_predict = QImage()
    self.image_predict.fill(qRgb(255, 0, 255))

  def PredictImage(self, filename):
    image = QImage()
    if not image.load(filename):
      return False

    self.image_predict = image
    self.update()
    return True

  def paintEvent(self, event):
    painter = QPainter(self)
    rect = event.rect()
    painter.drawImage(rect, self.image_predict, rect)


def main():
  app = QApplication(sys.argv)
  ex = MainWindow()
  ex.setWindowTitle('Paint Tools')
  ex.setGeometry(50, 50, 1400, 800)
  ex.show()
  sys.exit(app.exec_())

if __name__ == '__main__':
  main()

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/05/23 15:36

    (1) については
    qt layoutの基底クラスで親が与えられたときに
    setLayout が呼ばれるようになってます。

    Pythonだから明示した方がいいみたいな観点はありますが、
    前の回答で私が、親を与えると setLayout を省略できますと書いた為で、
    今回の表示問題への影響はないと思います。

    hbox = QHBoxLayout(frame)
    print(frame.layout() == hbox) # => Trueになります
    frame.setLayout(hbox)

    ----
    参考:

    ドキュメント (QWidget::setLayout)
    https://doc.qt.io/qt-5/qwidget.html#setLayout
    > An alternative to calling this function is to pass this widget to the layout's constructor.

    実装箇所 (QLayoutコンストラクタ)
    https://code.woboq.org/qt5/qtbase/src/widgets/kernel/qlayout.cpp.html#123

    キャンセル

  • 2020/05/23 15:42 編集

    補足ありがとうございます。こちらの知識不足でした。
    私が書いたのは誤った情報であったため、修正しておきます。

    キャンセル

  • 2020/05/23 16:16

    何処かで読んだ記憶があるんだけど、何処だっただろうと
    QLayout側の説明には書かれてなくて、焦って調べ直しました。
    (C++での仕様と PyQt5 で違ってた可能性もあったので)

    ---
    2つ目の問題についてはアプローチは異なりますが
    私のシグナル~スロット云々については、若干、改善案的な面もあり、
    シグナルの導入がハードルになるかもと、後々思い返すこともあったり…

    問題自体の焦点は「predictが共有されてない事」と同じなので、
    全体をまとめられた、そのまま動くコードは参考になると思います。

    キャンセル

  • 2020/05/23 20:53 編集

    お二方ともありがとうございました。
    taizan205様の回答は具体的且つ明示的で非常にわかりやすかったですが、
    今回はより勉強になったという点でteamikl様を選ばせていただきました

    今後ともよろしくお願いいたします。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.26%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる