2016-09-27 40 views
1

我正在嘗試創建我的第一個記憶遊戲。PyQt5:通過小部件方法更新QAction後的MainApplication佈局

我最近發現如何讓它工作得益於我的問題here的答案。工作代碼發佈在同一個鏈接中,但現在我試圖將小部件和主要應用程序類分開1),因爲我認爲它更好,2)因爲我想爲了更好地學習OOP如何工作。

所以,我在這裏發佈我的新代碼,這似乎工作,除了最後一部分。的概念:

  1. MainApplication具有一個菜單,其允許對路徑圖像的文件夾,並實例化MemoryGame小部件,它在轉彎初始化空QGridLayout。
  2. 單擊文件 - >打開菜單欄中的方法showDialog被調用。
  3. 當選擇一個文件夾時,populate_grid方法(MemoryGame obj)被調用。
  4. populate_grid「應該」用找到的每個圖像填充QGridLayout。
  5. 網格應顯示在屏幕上,但它不是....

我敢肯定問題是populate_grid,在這裏我添加元素的網格佈局的非常最後一行,但我無法找到如何解決問題。

#!/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

爲什麼圖像不顯示的原因是因爲你把gridWidgetMemoryGame小部件,它不具有佈局本身內。該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)。將主應用程序與它的(比方說)子部件分開是不是更好?當然,現在我的主應用程序非常簡單,我更多地考慮它的潛在可能性。 – umbe1987

+0

如果你想要多個遊戲,每個遊戲都應該是完全自給自足的(即如我之前建議的那樣,每個遊戲中的所有內容都應該在一個類中)。目前,你的記憶遊戲分爲兩類,每一類都不能沒有其他功能。對於多個遊戲,每個遊戲還需要提供它自己的專用菜單。因此,主應用程序將負責加載遊戲的主要部件,並在主菜單欄中顯示遊戲的菜單,但遊戲會執行其他任何操作。遊戲應該有一個通用的接口,主應用程序應該把它們當作「黑盒子」。 – ekhumoro