Saturday, July 15, 2017

I wrote a new job offer for a marketing assistant and reviewed our general Jobs page.

I read Erik Marsja’s PyCharm vs Spyder: a quick comparsion of two Python IDEs, and because Spyder uses PyQt, I started to dream once more about a Lino client in PyQt. I read PyQt - Introduction.

Seems that PyQt5 is best for me. Let’s try:

$ sudo apt-get install pyqt5-dev-tools
$ p3 # activate my Python 3 environment
$ pip install qtpy
$ pip install pyqt5

Here is my first Qt snippet (copied from here):

import sys
# from PyQt5 import QtGui
# from qtpy import QtGui
from qtpy import QtWidgets as QtGui


def window():
   app = QtGui.QApplication(sys.argv)
   w = QtGui.QWidget()
   b = QtGui.QLabel(w)
   b.setText("Hello World!")
   w.setGeometry(100,100,200,50)
   b.move(50,20)
   w.setWindowTitle("PyQt")
   w.show()
   sys.exit(app.exec_())
	
if __name__ == '__main__':
   window()

I had an AttributeError: module 'qtpy.QtGui' has no attribute 'QApplication', that’s because the modularization has been changed as explained in Transition from Qt 4.x to Qt5.

Tutorialspoint unfortunately now continues using QtDesigner, that’s not what I want. But this one is a better one tutorial for me. Here is my sandbox code after reaching their layouts section

import sys
from PyQt5.QtWidgets import (QApplication, QWidget, QPushButton,
                             QMessageBox, QDesktopWidget, QMainWindow,
                             QAction, qApp, QTextEdit, QHBoxLayout,
                             QVBoxLayout)
# from PyQt5.QtCore import QCoreApplication
from PyQt5.QtGui import QIcon


class DetailForm(QWidget):
    
    def __init__(self, title="Detail Form"):
        super().__init__()
        self.setWindowTitle(title)    
        self.initUI()
        
    def initUI(self):
        
        okButton = QPushButton("OK")
        cancelButton = QPushButton("Cancel")

        hbox = QHBoxLayout()
        hbox.addStretch(1)
        hbox.addWidget(okButton)
        hbox.addWidget(cancelButton)

        vbox = QVBoxLayout()
        vbox.addStretch(1)
        vbox.addLayout(hbox)
        
        self.setLayout(vbox)    
        
        self.setGeometry(300, 300, 300, 150)
        # self.show()


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

        textEdit = QTextEdit()
        self.setCentralWidget(textEdit)        

        self.setGeometry(300, 300, 300, 220)
        self.center()
        self.setWindowTitle('2.py')
        self.setWindowIcon(QIcon('../../.static/logo.png'))
        self.setToolTip('This is a <b>QWidget</b> widget')

        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&File')
        
        exitAction = QAction(QIcon('exit.png'), '&Exit', self)
        exitAction.setShortcut('Ctrl+Q')
        exitAction.setStatusTip('Exit application')
        exitAction.triggered.connect(qApp.quit)
        fileMenu.addAction(exitAction)

        a = QAction(QIcon('detail.png'), '&Detail', self)
        a.triggered.connect(self.show_detail)
        fileMenu.addAction(a)

        self.toolbar = self.addToolBar('Exit')
        self.toolbar.addAction(exitAction)

        # btn = QPushButton('Quit', self)
        # btn.clicked.connect(QCoreApplication.instance().quit)
        # btn.setToolTip('This is a <b>QPushButton</b> widget')
        # btn.resize(btn.sizeHint())
        # btn.move(50, 50)               
    
        self.show()
        
        self.statusBar().showMessage('Ready')
        
    def show_detail(self, event):
        self.detail_form = DetailForm()
        self.detail_form.show()
        
    def closeEvent(self, event):
        
        reply = QMessageBox.question(self, 'MessageBox',
            "This will close the window! Are you sure?",
                                     QMessageBox.Yes | 
                                     QMessageBox.No, QMessageBox.Yes)

        if reply == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()

    def center(self):
        
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())
            
	
if __name__ == '__main__':

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

My summary after my first session: nice! promising!

An important thing to try out is how to display and edit tabular data (probably using QTableWidget). Another important question is whether it can run on mobile devices (probably using pyqtdeploy).