My research has included:
PyQt reference to callable problem?
Python PyQt callback never runs - how to debug?
Passing extra arguments to PyQt slot
I am building a linux 'launcher' program which currently has two callbacks. One simply launches the clicked app, the other creates a new launcher. The first one works fine - the second one has been extremely tricky. I've done a lot to solve this.
- Running PyCharm debug on script and watch values for self, etc. to learn more
- Moving the NewLauncher function to within the InitUI method.
- Endlessly changing "self", "centralWidget" and other object references.
- Using functools partial.
The error I'm getting is "AttributeError: 'QWidget' object has no attribute 'newLauncher'"
Here's the code: (my apologies if it's too long - I was recently advised not to edit too much out).
import sys, os
import subprocess
from functools import partial
from PyQt5.QtWidgets import QFileDialog, QToolButton, QHBoxLayout, QGridLayout, QSizePolicy, QSpacerItem, QWidget, QPushButton, QFormLayout, QLineEdit, QAction, QApplication, QDesktopWidget, QMainWindow, QTabWidget, QVBoxLayout
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import QSize
from ruamel.yaml import YAML
yaml = YAML()
file_object = open("/home/tsc/PycharmProjects/launcher/Matrix.yaml", "r")
code = file_object.read()
matrix = yaml.load(code)
file_object.close()
class App(QMainWindow):
def __init__(self):
super(App, self).__init__()
self.initUI()
def launch(self, filepath):
subprocess.run(filepath)
def newLauncher(self):
num_butts = len(matrix)
btn_str = 'btn' + str(num_butts)
file_object = open("/home/tsc/PycharmProjects/launcher/Matrix.yaml", "a")
btn_str = 'btn' + str(num_butts + 1)
file_object.write("\n" + btn_str + ":\n")
self.setStyleSheet('padding: 3px; background: white');
fname, _ = QFileDialog.getOpenFileName(self, "select an executable or document to launch:", "",
"all files (*.*)")
path = fname
fname = os.path.basename(fname)
file_object.write(" " + "name: " + str(fname) + "\n" + " " + "path: " + str(path) + "\n")
self.setStyleSheet('padding: 3px; background: white');
icon, _ = QFileDialog.getOpenFileName(self, "select an image file for the icon:", "",
"all files (*.*)")
file_object.write(" " + "icon: " + str(icon) + "\n")
file_object.close()
def initUI(self):
super(App, self).__init__()
centralWidget = QWidget()
tabWidget = QTabWidget()
lay = QVBoxLayout(centralWidget)
for i in range(3):
page = QWidget()
pagelay = QGridLayout(page)
bmatrix = {}
for btn in matrix:
name = matrix[btn]['name']
filepath = matrix[btn]['path']
icon = matrix[btn]['icon']
bmatrix[btn] = QToolButton(page)
bmatrix[btn].setIcon(QIcon(icon))
bmatrix[btn].setIconSize(QSize(64, 64))
bmatrix[btn].resize(100, 100)
bmatrix[btn].clicked.connect(lambda checked, arg=filepath: self.launch(arg))
pagelay.addWidget(bmatrix[btn])
tabWidget.addTab(page, 'tab{}'.format(i))
mainMenu = self.menuBar()
fileMenu = mainMenu.addMenu('File')
mainMenu.addMenu(fileMenu)
newAction = QAction('&New', centralWidget)
#1 newAction.triggered.connect(lambda checked, arg=matrix: centralWidget.newLauncher(arg)) - shows window.
#2 newAction.triggered.connect(partial(self.NewLauncher, self)) - shows nothing, App has no NewLauncher
fileMenu.addAction(newAction)
editMenu = mainMenu.addMenu('Edit')
lay.addWidget(mainMenu)
lay.addWidget(tabWidget)
centralWidget.setGeometry(100, 100, 1080, 630)
centralWidget.setWindowTitle('LaunchMaster')
qtRectangle = centralWidget.frameGeometry()
centerPoint = QDesktopWidget().availableGeometry().center()
qtRectangle.moveCenter(centerPoint)
centralWidget.move(qtRectangle.topLeft())
centralWidget.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
And here's the yaml config file. You'll need to customize the paths, etc. if you want to test it. The interface has a menuBar and a tabWidget containing pages that themself contain the launcher buttons.
Matrix.yaml: substitute spaces for the underscores (indent is 2 chars.). I'm unsure of this markup syntax just yet, sorry for the hassle.
btn1:
name: firefox
path: firefox-esr
icon: /home/tsc/PycharmProjects/launcher/icons/firefox.jpeg
btn2:
name: thunderbird
path: /home/tsc/thunderbird/thunderbird
icon: /home/tsc/PycharmProjects/launcher/icons/thunderbird.jpeg