2016-09-27 6 views
1

私は最初のメモリゲームを作成しようとしています。PyQt5:QActionの後にMainApplicationのレイアウトをウィジェットメソッドで更新する

私は最近、私の質問hereの答えのおかげで働く方法を見つけました。ワーキングコードは同じリンクに掲載されていますが、私はウィジェットとメインアプリケーションクラスを1)分離しておくことをお勧めします。2)OOPの仕組みをより良く学びたいからです。

ここでは、最後の部分を除いて動作するように思われる新しいコードを掲載します。概念:

  1. MainApplicationは、画像のフォルダへのパスを可能にするメニューバーを有し、交互に空QGridLayoutを初期化MemoryGameウィジェットをインスタンス化します。
  2. メニューバーで[ファイル] - > [開く]をクリックすると、のshowDialogというメソッドが呼び出されます。
  3. フォルダを選択すると、populate_grid(MemoryGame objの)メソッドが呼び出されます。
  4. populate_grid QGridLayoutに見つかったイメージのそれぞれを "should"で埋めてください。
  5. グリッドが画面に表示されるはずですが、それは、私は、問題は、私はグリッドレイアウトに要素を追加populate_grid、非常に最後の行にあるかなり確信しています....

ではありませんしかし、私は問題を解決する方法を見つけることができません。あなたは、レイアウト自体を持っていないMemoryGameウィジェット、内部のgridWidgetを置くため

#!/usr/bin/python3 
# -*- coding: utf-8 -*- 

""" 
Memory game 3 

My first memory game in PyQt5. 

author: Umberto Minora 
last edited: September 2016 
""" 

import os 
import sys 
import glob 
import math 

from PyQt5.QtWidgets import (QMainWindow, QWidget, 
    QGridLayout, QPushButton, QApplication, 
    QAction, QFileDialog, QLabel) 

from PyQt5.QtGui import QPixmap 

class MainApplication(QMainWindow): 
    """This is the main application. 
    All widgets should be put inside it.""" 
    def __init__(self, widget): 
     super().__init__() 

     self.widget = widget 
     self.initUI() 

    def showDialog(self): 
     folder = str(QFileDialog.getExistingDirectory(self, "Select Directory", 
      '.', QFileDialog.ShowDirsOnly)) 

     images = glob.glob(os.path.join(folder, '*.jpg')) 

     if images: 
      self.widget.populate_grid(images) 

    def initUI(self): 
     self.statusBar() 

     openFile = QAction('Open', self) 
     openFile.setShortcut('Ctrl+O') 
     openFile.setStatusTip('Search image folder') 
     openFile.triggered.connect(self.showDialog) 

     menubar = self.menuBar() 
     self.fileMenu = menubar.addMenu('&File') 
     self.fileMenu.addAction(openFile) 

     self.setCentralWidget(self.widget) 

     self.setGeometry(300, 300, 350, 300) 
     self.setWindowTitle('Memory Game!') 
     self.show() 

class MemoryGame(QWidget): 
    """This is the Memory Game Widget""" 
    def __init__(self): 
     super().__init__() 

     self.gridWidget = QWidget(self) 
     self.gridLayout = QGridLayout(self.gridWidget) 

    def populate_grid(self, images): 
     n_cols = math.ceil(math.sqrt(len(images))) 
     n_rows = math.ceil(math.sqrt(len(images))) 
     positions = [(i,j) for i in range(n_cols) for j in range(n_rows)] 
     for position, img in zip(positions, images): 
      if img == '': 
       continue 
      pixmap = QPixmap(img) 
      scaled = pixmap.scaled(pixmap.width()/3, pixmap.height()/3) 
      del(pixmap) 
      lbl = QLabel(self) 
      lbl.setPixmap(scaled) 
      self.gridLayout.addWidget(lbl, *position) 

if __name__ == '__main__': 

    app = QApplication(sys.argv) 
    ex = MainApplication(MemoryGame()) 
    sys.exit(app.exec_()) 

答えて

1

画像が表示されない理由はあります。 MemoryGameウィジェットは、実際にので、すべてを行う必要がこれです、gridWidgetを交換する必要があります。

class MemoryGame(QWidget): 
    """This is the Memory Game Widget""" 
    def __init__(self): 
     super().__init__() 
     self.gridLayout = QGridLayout(self) 

私はまた、あなたがMemoryGameウィジェットを作成する方法が不必要に複雑だと思います。カスタムウィジェットクラスは他のクラスと同様に扱われるべきです。そのようなMainApplicationコンストラクタにそれを渡す必要はありません - ちょうどinitUiの内側にそれを直接作成します。

def initUI(self): 
    ...   
    self.widget = MemoryGame() 
    self.setCentralWidget(self.widget) 
+0

おかげで再び!とにかく、MainApplicationを他のゲーム(PokerGameなど)で実装したいと考えています。メインアプリケーションを子ウィジェットと区別する方が良いのではないでしょうか?もちろん、私のMainApplicationは非常にシンプルなので、どうなるかについてもっと考えています。 – umbe1987

+0

複数のゲームが必要な場合は、各ゲームは完全に自己完結型でなければなりません。現在のところ、あなたのメモリゲームは2つのクラスに分割されています。それぞれのクラスは、他のクラスなしでは機能しません。複数のゲームでは、各ゲームはそれ自身の特殊なメニューを提供する必要もあります。メインアプリケーションはゲームのメインウィジェットをロードし、メインメニューバーにゲームのメニューを表示する責任がありますが、ゲームは他のすべてを行います。ゲームには汎用インターフェイスが必要で、メインアプリケーションではそれらを「ブラックボックス」として扱う必要があります。 – ekhumoro

関連する問題