Python Forum

Full Version: Calling functions from within a class: PYQT6
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi all,
My code is written in python and aims to output a GUI using PYQT6. The code below has been streamlined to troubleshoot the error:

1. From within the 'Widow' class, an instance of 'ButtonClass' class is called, which is named 'play_button'.

2. The 'ButtonClass' object, when clicked, sends a 'clicked.connect' signal to call the function 'button_visibility', which is contained within 'ButtonClass' class.

3. When the play_button is clicked, it produces the error below (described in 'The Returned Error:')


Does anybody know why I cannot access 'setVisible()' from within the 'button_visibility' function?


My code:

from PyQt6.QtWidgets import QApplication, QPushButton, QWidget from PyQt6.QtGui import QIcon from PyQt6.QtCore import * import sys class ButtonClass(QPushButton): mouseHover = pyqtSignal(bool) def __init__(self, parent, set_image, set_button_geometry, set_button_resize, set_button_visible, path_to_clicked_function, button_name): super().__init__(parent) # Instance variables assigned with arguments self.set_image = set_image self.set_button_geometry = set_button_geometry self.set_button_resize = set_button_resize self.set_button_visible = set_button_visible self.path_to_clicked_function = path_to_clicked_function self.button_name = button_name self.setMouseTracking(True) # Assign icon to QPushButton object and insert custom image self.setIcon(QIcon(self.set_image)) # Specify button geometry self.setGeometry(self.set_button_geometry[0], self.set_button_geometry[1], self.set_button_geometry[2], self.set_button_geometry[3]) # Specify Icon size self.setIconSize(QSize(self.set_button_resize[0], self.set_button_resize[1])) # Stylesheet attributes self.setStyleSheet("border: 0px") # Set button visibility self.setVisible(self.set_button_visible) self.clicked.connect(ButtonClass.button_visibility) def button_visibility(self): self.setVisible(False) def enterEvent(self, event): self.mouseHover.emit(True) print("Button entered") def leaveEvent(self, event): self.mouseHover.emit(False) print("Button left") class Window(QWidget): def __init__(self): super().__init__() # Define window title self.setWindowTitle("Soular") # Define window height self.setFixedHeight(700) # Define window width self.setFixedWidth(400) # window stylesheet defines window background colour self.setStyleSheet("background-color:'#323232'") # Moves main window to screen location self.move(10, 10) # initialises play_button from class 'Button_class' play_button = ButtonClass(self, 'Images/Play_standard.png', [165, 580, 70, 70], [70, 70], True, ButtonClass.button_visibility, 'play_button') app = QApplication(sys.argv) window = Window() window.show() sys.exit(app.exec())
The Returned Error:

Quote:Traceback (most recent call last):
File "/Users/Library/Mobile Documents/com~apple~CloudDocs/Python Projects/pythonProject5/UI.py", line 50, in button_visibility
self.setVisible(False)
AttributeError: 'bool' object has no attribute 'setVisible'

Process finished with exit code 134 (interrupted by signal 6: SIGABRT)
In line 50 try changing self to play_button. Somehow self is a boolean at that point (according to the error) rather than the button.
This code treats "button_visibility()" like a class method when it is really an instance method.
self.clicked.connect(ButtonClass.button_visibility)
The code should be written like this:
self.clicked.connect(self.button_visibility)
The reason you got an error message about 'bool' object has no attribute 'setVisible' was because you were not passing an instance (self) when calling the method.
Thank you both for your help. The 'self.clicked.connect(self.button_visibility)' approach worked.
I think it is a bad idea using setGeometry() to size and position your button in the window. I also think it is a bad idea passing the size and position as a parameter when you create the button. The ​common practice to use a geometry manager to place widgets in a window.

I don't think the button should have a button_visibility() method and I don't think the button should bind the clicked signal to call this method. What good is a button that hides itself? Buttons should not do things like set their size or bind their clicked events. Buttons should be generic reusable things. The application should use the button API to bind the events.

This is how I would write your code. I use PySide instead of PyQt, so there are some minor differences related to that. I also removed the style sheets and anything that is not absolutely required to demonstrate the issue related to the post topic. And just for fun I changed the hover event to not only emit a signal but change the button icon.
import sys import PySide6.QtWidgets as QtWidgets import PySide6.QtCore as QtCore import PySide6.QtGui as QtGui class HoverButton(QtWidgets.QPushButton): """A Pushbutton that changes it's icon when you hover""" hover = QtCore.Signal(bool) def __init__(self, parent, icon, hover_icon): super().__init__(parent) self.icon = icon self.hover_icon = hover_icon self.setMouseTracking(True) self.setIcon(self.icon) def enterEvent(self, event): self.setIcon(self.hover_icon) self.hover.emit(True) def leaveEvent(self, event): self.setIcon(self.icon) self.hover.emit(False) class Window(QtWidgets.QWidget): """A window that demonstrates how to use my hover button""" def __init__(self): super().__init__() play_button = HoverButton( self, QtGui.QIcon("ttt_x.png"), QtGui.QIcon("ttt_o.png") ) # Bind events outside the button play_button.hover.connect(lambda flag: print("Hover", flag)) play_button.clicked.connect(lambda flag: play_button.setVisible(False)) layout = QtWidgets.QVBoxLayout(self) layout.addWidget(play_button) app = QtWidgets.QApplication(sys.argv) window = Window() window.show() sys.exit(app.exec())