Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I am trying to develop my first app with PyQt5 (a memory game).

I have created two classes: MainApplication, which inherits from QMainWindow, and GridWidget, which inherits from QWidget. My aim is to let the user specify a folder with some images (jpg) using the fileMenu of the menuBar.

So, in the MainApplication I created the method showDialog which connects to the fileMenu and outputs a list of filenames (names of the images within the selected folder), stored in a list variable. I would like to be able to pass this to the GridWidget, so that it can creates and fill the grid.

I am kind of new to OOP programming, so maybe the organization of my script is not the best, and I am open to suggestions to improve it. My idea was to add GridWidget into MainApplication, but I don't know how to pass the output of showDialog to this. Any suggestion would be appreciated.

Here is my code so far:

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

"""
Memory game 

My first memory game in PyQt5.

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

import os, sys, glob
from PyQt5.QtWidgets import (QMainWindow, QWidget,
    QGridLayout, QPushButton, QApplication,
    QAction, QFileDialog)
from PyQt5.QtGui import QPixmap

class MainApplication(QMainWindow):

    def __init__(self):
        super().__init__()

        self.initUI()

    def initUI(self):
        self.statusBar()

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

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

        self.form_widget = GridWidget(self)

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

    def showDialog(self):

        folder = str(QFileDialog.getExistingDirectory(self, "Select Directory", 
            '/home', QFileDialog.ShowDirsOnly))

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

        if images:
            return images * 2

class GridWidget(QWidget):

    def __init__(self):
        super().__init__()

        grid = QGridLayout()
        self.setLayout(grid)

        names = self.showDialog() # DA SISTEMARE!!!!!!

        positions = [(i,j) for i in range(int(len(names)/2)) for j in range(int(len(names)/2))]

        for position, name in zip(positions, names):

            if name == '':
                continue
            button = QPushButton(name)
            grid.addWidget(button, *position)

if __name__ == '__main__':

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

EDIT

Thanks to @ekhumoro's answer, now the code is working. Here is the code I am actually running (it's not the complete game, just an initial import of images from a folder).

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

"""
Memory game 2

My first memory game in PyQt5.

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

import os, sys, glob, math
from PyQt5.QtWidgets import (QMainWindow, QWidget,
    QGridLayout, QPushButton, QApplication,
    QAction, QFileDialog, QLabel)
from PyQt5.QtGui import QPixmap

class MainApplication(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()

    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.gridWidget = QWidget(self)
        self.gridLayout = QGridLayout(self.gridWidget)
        self.setCentralWidget(self.gridWidget)

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

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

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

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

        if images:
            self.populateGrid(images)


if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = MainApplication()
    sys.exit(app.exec_())
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
137 views
Welcome To Ask or Share your Answers For Others

1 Answer

I think it will be simpler if you keep everything in one class. You should make each child widget an attribute of the class, so you can access them later using self within the methods of the class. All the program logic will go in the methods - so it's just a matter of calling methods in response to signals and events.

Here is what the class should look like:

class MainApplication(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.statusBar()

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

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

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

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

    def populateGrid(self, images):
        names = images * 2
        positions = [(i,j) for i in range(int(len(names)/2)) for j in range(int(len(names)/2))]
        for position, name in zip(positions, names):
            if name == '':
                continue
            button = QPushButton(name)
            self.gridLayout.addWidget(button, *position)

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

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

        if images:
            self.populateGrid(images)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...