Bottom Page

Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
 right mouse button click with PyQt5
#1
I'm trying to write a mineweeper program in PyQt5
This is what I already have.
I still have 2 problems:
1* How do I detect a right mouse button click on a button? As you can see I already have a left mouse button click
2* I created a grid of buttons but I'm unable to remove the space between the buttons. How do I do that

I also don't understand the differece between
class Window(QDialog)
and
class Window(QtWidgets.QMainWindow):
import sys
from PyQt5 import QtWidgets, QtGui
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from functools import partial
from random import randint

class Window(QDialog):
	def __init__(self):
		super().__init__()
		self.setGeometry(50,50,600,300)
		self.setWindowTitle("Minesweeper")
		self.setWindowIcon(QtGui.QIcon('favicon.png'))
		
		self.initGame()		
		
		self.mainPage()
	
	def mainPage(self):
		
		self.createGridLayout()

		windowLayout = QVBoxLayout()
		windowLayout.addWidget(self.horizontalGroupBox)
		self.setLayout(windowLayout)
		
		self.show()
	
	def initGame(self):
		self.initialArray=[[0 for i in range(10)]for j in range(10)]
		self.counterTurns=0
		
		for column in range (0,10):
			for row in range (0,10):
				bomb=randint(0,6)
				if bomb==6:
					self.initialArray[row][column]=9
					if row-1>=0 and self.initialArray[row-1][column]!=9:
						self.initialArray[row-1][column]+=1
					if row+1<=9 and self.initialArray[row+1][column]!=9:
						self.initialArray[row+1][column]+=1
					if column-1>=0 and self.initialArray[row][column-1]!=9:
						self.initialArray[row][column-1]+=1
					if column+1<=9 and self.initialArray[row][column+1]!=9:
						self.initialArray[row][column+1]+=1
					if row-1>=0 and column-1>=0 and self.initialArray[row-1][column-1]!=9:
						self.initialArray[row-1][column-1]+=1
					if row+1<=9 and column-1>=0 and self.initialArray[row+1][column-1]!=9:
						self.initialArray[row+1][column-1]+=1
					if row-1>=0 and column+1<=9 and self.initialArray[row-1][column+1]!=9:
						self.initialArray[row-1][column+1]+=1
					if row+1<=9 and column+1<=9 and self.initialArray[row+1][column+1]!=9:
						self.initialArray[row+1][column+1]+=1
	
		

	def createGridLayout(self):
		self.horizontalGroupBox=QGroupBox()
		layout=QGridLayout()
		
		self.button={}
		
		for column in range (0,10):
			for row in range (0,10):
				self.button[row,column]=QPushButton(self)
				self.button[row,column].setFixedHeight(20)
				self.button[row,column].setFixedWidth(20)
				self.button[row,column].setIcon(QtGui.QIcon('tile_plain.gif'))
				self.button[row,column].clicked.connect(partial(self.buttonPressed,row,column))
				layout.addWidget(self.button[row,column],row,column)
				

		for row in self.initialArray:
			print (row)
		self.horizontalGroupBox.setLayout(layout)
		
	def buttonPressed(self,row,column):
		self.displayEmptyButtons(row,column)
		self.counterTurns+=1
		print ('rij'+str(row)+'\nkolom'+str(column))
		if self.initialArray[row][column]==9:
			print ('bomb!!!! ' + str(self.counterTurns))
		game_busy=0
		values=[1,2,3,4,5,6,7,8]
		for x in self.initialArray:
			print (x)
			if any(i in values for i in x):
				game_busy=1
		if game_busy==0:
			print ('you won')
			
		
				
	def displayEmptyButtons(self,row,column):
		if self.initialArray[row][column]!=0:
			if self.initialArray[row][column]!=10:
				self.button[row,column].setText(str(self.initialArray[row][column]))
			self.initialArray[row][column]=10
		else:
			if self.initialArray[row][column]!=10:
				self.button[row,column].setText(str(self.initialArray[row][column]))
			self.initialArray[row][column]=10
			if row-1>=0:
				self.displayEmptyButtons(row-1,column)
			if row+1<=9:
				self.displayEmptyButtons(row+1,column)
			if column-1>=0:
				self.displayEmptyButtons(row,column-1)
			if column+1<=9:
				self.displayEmptyButtons(row,column+1)
			if row-1>=0 and column-1>=0:
				self.displayEmptyButtons(row-1,column-1)
			if row+1<=9 and column-1>=0:
				self.displayEmptyButtons(row+1,column-1)
			if row-1>=0 and column+1<=9:
				self.displayEmptyButtons(row-1,column+1)
			if row+1<=9 and column+1<=9:
				self.displayEmptyButtons(row+1,column+1)

			
if __name__ == '__main__':
    
    app = QApplication(sys.argv)
    ex = Window()
    sys.exit(app.exec_())




Quote
#2
To remove the space between buttons, you must apply these settings on the layout (or edit the Layout section in QtDesigner):
        self.gridLayout.setSpacing(0)
        self.gridLayout.setContentsMargins(0,0,0,0)
Then to detect the type of mouse click, or even the mouse wheel, you must install an event filter on each button:

import sys
from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_Form(QtWidgets.QMainWindow):
    def setupUi(self, Form):
        self.gridLayout = QtWidgets.QGridLayout(Form)
        self.gridLayout.setSpacing(0)
        self.gridLayout.setContentsMargins(0,0,0,0)
        self.gridLayout.setObjectName("gridLayout")

        self.pushButton_1 = QtWidgets.QPushButton(Form)
        self.pushButton_1.setFixedSize(QtCore.QSize(20, 20))
        self.pushButton_1.setObjectName("pushButton_1")
        self.gridLayout.addWidget(self.pushButton_1, 0, 0, 1, 1)

        self.pushButton_2 = QtWidgets.QPushButton(Form)
        self.pushButton_2.setFixedSize(QtCore.QSize(20, 20))
        self.pushButton_2.setObjectName("pushButton_2")
        self.gridLayout.addWidget(self.pushButton_2, 1, 0, 1, 1)

        self.pushButton_3 = QtWidgets.QPushButton(Form)
        self.pushButton_3.setFixedSize(QtCore.QSize(20, 20))
        self.pushButton_3.setObjectName("pushButton_3")
        self.gridLayout.addWidget(self.pushButton_3, 0, 1, 1, 1)

        self.pushButton_4 = QtWidgets.QPushButton(Form)
        self.pushButton_4.setFixedSize(QtCore.QSize(20, 20))
        self.pushButton_4.setObjectName("pushButton_4")
        self.gridLayout.addWidget(self.pushButton_4, 1, 1, 1, 1)

        self.pushButton_1.installEventFilter(self)
        self.pushButton_2.installEventFilter(self)
        self.pushButton_3.installEventFilter(self)
        self.pushButton_4.installEventFilter(self)

    def eventFilter(self, obj, event):
        if event.type() == QtCore.QEvent.MouseButtonPress:
            if event.button() == QtCore.Qt.LeftButton:
                print(obj.objectName(), "Left click")
            elif event.button() == QtCore.Qt.RightButton:
                print(obj.objectName(), "Right click")
            elif event.button() == QtCore.Qt.MiddleButton:
                print(obj.objectName(), "Middle click")
        return QtCore.QObject.event(obj, event)


if __name__ == "__main__":
    app = QtWidgets.QApplication([])
    Form = QtWidgets.QWidget()
    ui = Ui_Form()
    ui.setupUi(Form)
    Form.show()
    sys.exit(app.exec_())
Finally, the choice between a Dialog and a MainWindow depend of what you intend to do with it. The dialog usually have some action button (apply, ok, cancel...), and therefore they have accepted and rejected signals. The MainWindow have more complex features, such as a top menu and status bar. It is very well detailled in Qt docs:

https://doc.qt.io/qt-5/qmainwindow.html
https://doc.qt.io/archives/qt-4.8/qdialog.html
Quote
#3
There is still something going wrong with the mouse click. Any idea what I'm doing wrong?
This is the error message I'm getting:

Traceback (most recent call last):
File "minesweeper_A01.py", line 53, in eventFilter
if event.button() == Qt.LeftButton:
AttributeError: 'QEvent' object has no attribute 'button'


------------------
(program exited with code: 3)

Druk op een toets om door te gaan. . .


import sys
from PyQt5 import QtWidgets, QtGui
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from functools import partial
from random import randint

#class Window(QWidget):
class Window(QMainWindow):
	def __init__(self):
		super(Window,self).__init__()
		self.setWindowTitle("Minesweeper")
		self.setWindowIcon(QtGui.QIcon('ekopak-favicon.png'))
		
		fileAction = QAction("New", self)
		fileAction.triggered.connect(self.init_game)

		mainMenu = self.menuBar()
		fileMenu = mainMenu.addMenu('&File')
		fileMenu.addAction(fileAction)
		
		self.setMouseTracking(True)
		
		self.init_game()		
		
		self.main_page()
	
	def main_page(self):		
		self.button={}
		
		self.centralwidget = QWidget()
		self.setCentralWidget(self.centralwidget)
        
		horizontalLayout=QHBoxLayout(self.centralwidget)
		for column in range (0,10):
			verticalLayout=QVBoxLayout()
			verticalLayout.setSpacing(0)
			for row in range (0,10):
				self.button[row,column]=QPushButton(self)
				self.button[row,column].setFixedHeight(20)
				self.button[row,column].setFixedWidth(20)
				self.button[row,column].setContentsMargins(0,0,0,0)
				self.button[row,column].setIcon(QtGui.QIcon('tile_plain.gif'))
				self.button[row,column].installEventFilter(self)
				self.button[row,column].clicked.connect(partial(self.button_pressed,row,column))
				verticalLayout.addWidget(self.button[row,column])
			horizontalLayout.addLayout(verticalLayout)
			horizontalLayout.setSpacing(0)
		self.show()
	
	def eventFilter(self,obj,event):
		print('button pressed')
		if event.button() == Qt.LeftButton:
			print(obj.objectName(), "Left click")
		elif event.button() == Qt.RightButton:
			print(obj.objectName(), "Right click")
		elif event.button() == Qt.MiddleButton:
			print(obj.objectName(), "Middle click")
		return QObject.event(obj, event)


		

	
	def init_game(self):
		self.initialArray=[[0 for i in range(10)]for j in range(10)]
		self.counterTurns=0
		
		for column in range (0,10):
			for row in range (0,10):
				bomb=randint(0,6)
				if bomb==6:
					self.initialArray[row][column]=9
					if row-1>=0 and self.initialArray[row-1][column]!=9:
						self.initialArray[row-1][column]+=1
					if row+1<=9 and self.initialArray[row+1][column]!=9:
						self.initialArray[row+1][column]+=1
					if column-1>=0 and self.initialArray[row][column-1]!=9:
						self.initialArray[row][column-1]+=1
					if column+1<=9 and self.initialArray[row][column+1]!=9:
						self.initialArray[row][column+1]+=1
					if row-1>=0 and column-1>=0 and self.initialArray[row-1][column-1]!=9:
						self.initialArray[row-1][column-1]+=1
					if row+1<=9 and column-1>=0 and self.initialArray[row+1][column-1]!=9:
						self.initialArray[row+1][column-1]+=1
					if row-1>=0 and column+1<=9 and self.initialArray[row-1][column+1]!=9:
						self.initialArray[row-1][column+1]+=1
					if row+1<=9 and column+1<=9 and self.initialArray[row+1][column+1]!=9:
						self.initialArray[row+1][column+1]+=1	
		for row in self.initialArray:
			print (row)

		
	def button_pressed(self,row,column):
		self.display_empty_buttons(row,column)
		self.counterTurns+=1
		print ('rij'+str(row)+'\nkolom'+str(column))
		if self.initialArray[row][column]==9:
			print ('bomb!!!! ' + str(self.counterTurns))
		game_busy=0
		values=[1,2,3,4,5,6,7,8]
		for x in self.initialArray:
			print (x)
			if any(i in values for i in x):
				game_busy=1
		if game_busy==0:
			print ('you won')
			
		
				
	def display_empty_buttons(self,row,column):
		#the value of initialArray can be 0-8, 9 is for a bomb, 10 is if it has been opened
		if self.initialArray[row][column]!=0:
			if self.initialArray[row][column]!=10:
				if self.initialArray[row][column]==0:
					self.button[row,column].setIcon(QtGui.QIcon('tile_clicked.gif'))
				elif self.initialArray[row][column]==1:
					self.button[row,column].setIcon(QtGui.QIcon('tile_1.gif'))	
				elif self.initialArray[row][column]==2:
					self.button[row,column].setIcon(QtGui.QIcon('tile_2.gif'))
				elif self.initialArray[row][column]==3:
					self.button[row,column].setIcon(QtGui.QIcon('tile_3.gif'))	
				elif self.initialArray[row][column]==4:
					self.button[row,column].setIcon(QtGui.QIcon('tile_4.gif'))	
				elif self.initialArray[row][column]==5:
					self.button[row,column].setIcon(QtGui.QIcon('tile_5.gif'))
				elif self.initialArray[row][column]==6:
					self.button[row,column].setIcon(QtGui.QIcon('tile_6.gif'))	
				elif self.initialArray[row][column]==7:
					self.button[row,column].setIcon(QtGui.QIcon('tile_7.gif')) 
				elif self.initialArray[row][column]==8:
					self.button[row,column].setIcon(QtGui.QIcon('tile_8.gif'))
				elif self.initialArray[row][column]==9:
					self.button[row,column].setIcon(QtGui.QIcon('tile_mine.gif'))
				else:
					self.button[row,column].setText(str(self.initialArray[row][column]))
			self.initialArray[row][column]=10
		else:
			if self.initialArray[row][column]!=10:
				if self.initialArray[row][column]==0:
					self.button[row,column].setIcon(QtGui.QIcon('tile_clicked.gif'))
				else:
					self.button[row,column].setText(str(self.initialArray[row][column]))
			self.initialArray[row][column]=10
			if row-1>=0:
				self.displayEmptyButtons(row-1,column)
			if row+1<=9:
				self.displayEmptyButtons(row+1,column)
			if column-1>=0:
				self.displayEmptyButtons(row,column-1)
			if column+1<=9:
				self.displayEmptyButtons(row,column+1)
			if row-1>=0 and column-1>=0:
				self.displayEmptyButtons(row-1,column-1)
			if row+1<=9 and column-1>=0:
				self.displayEmptyButtons(row+1,column-1)
			if row-1>=0 and column+1<=9:
				self.displayEmptyButtons(row-1,column+1)
			if row+1<=9 and column+1<=9:
				self.displayEmptyButtons(row+1,column+1)

#messagebox bomb pressed
#messagebox won
#rightclick add flag
					
			
if __name__ == '__main__':
    
    app = QApplication(sys.argv)
    ex = Window()
    sys.exit(app.exec_())





Quote
#4
It is because not all event have the same properties. Therefore you must verify what type of event it is before looking for the button attribute.

if event.type() == QtCore.QEvent.MouseButtonPress:
Quote
#5
Thanks for the help, it's working now
Quote

Top Page

Possibly Related Threads...
Thread Author Replies Views Last Post
  [Tkinter] Checking button click in Tkinter GalaxyCoyote 3 239 Oct-20-2019, 03:28 AM
Last Post: GalaxyCoyote
  [PyQt] Problem how to click a button inside a group box? mart79 2 251 Aug-05-2019, 01:21 PM
Last Post: mart79
  [PySimpleGui] How to alter mouse click button of a standard submit button? skyerosebud 3 414 Jul-21-2019, 06:02 PM
Last Post: FullOfHelp
  [Tkinter] Tkinter window pop up again when i click button Orimura_Sandy 1 642 May-12-2019, 08:17 PM
Last Post: joe_momma
  [Tkinter] Not getting entry values on button click & treeview not updating ? swanysto 4 1,235 May-10-2019, 04:16 PM
Last Post: swanysto
  [PyQt] `QPushButton` without mouse click animation Atalanttore 2 786 Apr-22-2019, 01:00 PM
Last Post: Atalanttore
  Huge code problems (buttons(PyQt5),PyQt5 Threads, Windows etc) ZenWoR 0 398 Apr-06-2019, 11:15 PM
Last Post: ZenWoR
  Simple Button click on image file to create action? jpezz 4 520 Mar-27-2019, 10:08 PM
Last Post: jpezz
  QTabBar Indexing is wrong for right mouse click xenas 2 534 Jan-04-2019, 10:08 PM
Last Post: xenas
  [Tkinter] loop function when called from tkinter button click WantedStarling 5 2,406 Jul-13-2018, 06:12 PM
Last Post: nilamo

Forum Jump:


Users browsing this thread: 1 Guest(s)