How to have a PyQt window call a method when its “X” close button is selected

一曲冷凌霜 提交于 2020-01-25 03:00:19

问题


I'm trying to have a method called when the "X" close button of a PyQt window is selected. Briskly, I have a class of the object QtGui.QWidget and I want it to call one of its methods when the window is closed using the "X" close button in order to wrap up some subprocesses. How could this be done?

The code is shown below. The method of the class interface that I want to have called is stylusProximityControlOff(). This method terminates a subprocess which is potentially a little messy, but that is a separate problem.

Anyway, I would appreciate suggestions on having that method called when the "X" is selected.

#!/usr/bin/env python

"""
spin, a small utility to assist in setting usage modes of laptop-tablet devices

Usage:
    spin.py
    spin.py -h | --help
    spin.py --nogui
Options:
    -h,--help      : show this help message
    --nogui        : non-GUI mode
"""

from docopt import docopt
import os
import sys
import subprocess
from multiprocessing import Process
import time
from PyQt4 import QtGui
import logging

# logging
logger = logging.getLogger(__name__)
logging.basicConfig()
logger.level = logging.INFO

class interface(QtGui.QWidget):
    def __init__(
        self,
        docopt_args=None
    ):
        self.docopt_args=docopt_args
        super(interface, self).__init__()
        logger.info("running spin")
        # engage stylus proximity control
        self.stylusProximityControlOn()
        if not docopt_args["--nogui"]:
            # create buttons
            buttonsList = []
            # button: tablet mode
            buttonModeTablet = QtGui.QPushButton('tablet mode', self)
            buttonModeTablet.clicked.connect(self.engageModeTablet)
            buttonsList.append(buttonModeTablet)
            # button: laptop mode
            buttonModeLaptop = QtGui.QPushButton('laptop mode', self)
            buttonModeLaptop.clicked.connect(self.engageModeLaptop)
            buttonsList.append(buttonModeLaptop)
            # button: left
            buttonLeft = QtGui.QPushButton('left', self)
            buttonLeft.clicked.connect(self.engageLeft)
            buttonsList.append(buttonLeft)
            # button: right
            buttonRight = QtGui.QPushButton('right', self)
            buttonRight.clicked.connect(self.engageRight)
            buttonsList.append(buttonRight)
            # button: inverted
            buttonInverted = QtGui.QPushButton('inverted', self)
            buttonInverted.clicked.connect(self.engageInverted)
            buttonsList.append(buttonInverted)
            # button: normal
            buttonNormal = QtGui.QPushButton('normal', self)
            buttonNormal.clicked.connect(self.engageNormal)
            buttonsList.append(buttonNormal)
            # button: touchscreen on
            buttonTouchscreenOn = QtGui.QPushButton('touchscreen on', self)
            buttonTouchscreenOn.clicked.connect(self.engageTouchscreenOn)
            buttonsList.append(buttonTouchscreenOn)
            # button: touchscreen off
            buttonTouchscreenOff = QtGui.QPushButton('touchscreen off', self)
            buttonTouchscreenOff.clicked.connect(self.engageTouchscreenOff)
            buttonsList.append(buttonTouchscreenOff)
            # button: touchpad on
            buttonTouchpadOn = QtGui.QPushButton('touchpad on', self)
            buttonTouchpadOn.clicked.connect(self.engageTouchpadOn)
            buttonsList.append(buttonTouchpadOn)
            # button: touchpad off
            buttonTouchpadOff = QtGui.QPushButton('touchpad off', self)
            buttonTouchpadOff.clicked.connect(self.engageTouchpadOff)
            buttonsList.append(buttonTouchpadOff)
            # button: nipple on
            buttonNippleOn = QtGui.QPushButton('nipple on', self)
            buttonNippleOn.clicked.connect(self.engageNippleOn)
            buttonsList.append(buttonNippleOn)
            # button: nipple off
            buttonNippleOff = QtGui.QPushButton('nipple off', self)
            buttonNippleOff.clicked.connect(self.engageNippleOff)
            buttonsList.append(buttonNippleOff)
            # button: stylus proximity on
            buttonStylusProximityControlOn = QtGui.QPushButton('stylus proximity on', self)
            buttonStylusProximityControlOn.clicked.connect(self.engageStylusProximityControlOn)
            buttonsList.append(buttonStylusProximityControlOn)
            # button: stylus proximity off
            buttonStylusProximityControlOff = QtGui.QPushButton('stylus proximity off', self)
            buttonStylusProximityControlOff.clicked.connect(self.engageStylusProximityControlOff)
            buttonsList.append(buttonStylusProximityControlOff)
            # set button dimensions
            buttonsWidth=150
            buttonsHeight=60
            for button in buttonsList:
                button.setFixedSize(buttonsWidth, buttonsHeight)
            # set layout
            vbox = QtGui.QVBoxLayout()
            vbox.addStretch(1)
            for button in buttonsList:
                vbox.addWidget(button)
                vbox.addStretch(1)  
            self.setLayout(vbox)
            # window
            self.setGeometry(200, 200, 150, 100)
            self.setWindowTitle('spin')
            self.show()
    elif docopt_args["--nogui"]:
            logger.info("non-GUI mode")
    def displayLeft(self):
        logger.info("changing display to left")
        os.system('xrandr -o left')
    def displayRight(self):
        logger.info("changing display to right")
        os.system('xrandr -o right')
    def displayInverted(self):
        logger.info("changing display to inverted")
        os.system('xrandr -o inverted')
    def displayNormal(self):
        logger.info("changing display to normal")
        os.system('xrandr -o normal')
    def touchscreenLeft(self):
        logger.info("changing touchscreen to left")
        os.system('xinput set-prop "ELAN Touchscreen" "Coordinate Transformation Matrix" 0 -1 1 1 0 0 0 0 1')
    def touchscreenRight(self):
        logger.info("changing touchscreen to right")
        os.system('xinput set-prop "ELAN Touchscreen" "Coordinate Transformation Matrix" 0 1 0 -1 0 1 0 0 1')
    def touchscreenInverted(self):
        logger.info("changing touchscreen to inverted")
        os.system('xinput set-prop "ELAN Touchscreen" "Coordinate Transformation Matrix" -1 0 1 0 -1 1 0 0 1')
    def touchscreenNormal(self):
        logger.info("changing touchscreen to normal")
        os.system('xinput set-prop "ELAN Touchscreen" "Coordinate Transformation Matrix" 1 0 0 0 1 0 0 0 1')
    def touchscreenOn(self):
        logger.info("changing touchscreen to on")
        os.system('xinput enable "ELAN Touchscreen"')
    def touchscreenOff(self):
        logger.info("changing touchscreen to off")
        os.system('xinput disable "ELAN Touchscreen"')
    def touchpadOn(self):
        logger.info("changing touchpad to on")
        os.system('xinput enable "SynPS/2 Synaptics TouchPad"')
    def touchpadOff(self):
        logger.info("changing touchpad to off")
        os.system('xinput disable "SynPS/2 Synaptics TouchPad"')
    def nippleOn(self):
        logger.info("changing nipple to on")
        os.system('xinput enable "TPPS/2 IBM TrackPoint"')
    def nippleOff(self):
        logger.info("changing nipple to off")
        os.system('xinput disable "TPPS/2 IBM TrackPoint"')
    def stylusProximityControl(self):
        previousProximityStatus = None
        while True:
            proximityCommand = 'xinput query-state "Wacom ISDv4 EC Pen stylus" | grep Proximity | cut -d " " -f3 | cut -d "=" -f2'
            proximityStatus = subprocess.check_output(proximityCommand, shell=True).lower().rstrip()
            if (proximityStatus == "out") and (previousProximityStatus != "out"):
                logger.info("stylus inactive")
        self.touchscreenOn()
            elif (proximityStatus == "in") and (previousProximityStatus != "in"):
                logger.info("stylus active")
        self.touchscreenOff()
        previousProximityStatus = proximityStatus
            time.sleep(0.25)
    def stylusProximityControlOn(self):
        logger.info("changing stylus proximity control to on")
    self.process1 = Process(target=self.stylusProximityControl)
    self.process1.start()
    def stylusProximityControlOff(self):
        logger.info("changing stylus proximity control to off")
    self.process1.terminate()
    def engageModeTablet(self):
        logger.info("engaging mode tablet")
        self.displayLeft()
    self.touchscreenLeft()
        self.touchscreenOff()
        self.touchpadOff()
        self.nippleOff()
    def engageModeLaptop(self):
        logger.info("engaging mode laptop")
        self.displayNormal()
        self.touchscreenNormal()
        self.touchscreenOn()
        self.touchpadOn()
        self.nippleOn()
    def engageLeft(self):
        logger.info("engaging mode left")
        self.displayLeft()
        self.touchscreenLeft()
    def engageRight(self):
        logger.info("engaging mode right")
        self.displayRight()
        self.touchscreenRight()
    def engageInverted(self):
        logger.info("engaging mode inverted")
        self.displayInverted()
        self.touchscreenInverted()
    def engageNormal(self):
        logger.info("engaging mode normal")
        self.displayNormal()
        self.touchscreenNormal()
    def engageTouchscreenOn(self):
        self.touchscreenOn()
    def engageTouchscreenOff(self):
        self.touchscreenOff()
    def engageTouchpadOn(self):
        self.touchpadOn()
    def engageTouchpadOff(self):
        self.touchpadOff()
    def engageNippleOn(self):
        self.nippleOn()
    def engageNippleOff(self):
        self.nippleOff()
    def engageStylusProximityControlOn(self):
        self.stylusProximityControlOn()
    def engageStylusProximityControlOff(self):
        self.stylusProximityControlOff()
def main(docopt_args):
    application = QtGui.QApplication(sys.argv)
    interface1 = interface(docopt_args)
    sys.exit(application.exec_())
if __name__ == '__main__':
    args = docopt(__doc__)
    main(args)

回答1:


One approach is to reimplement the closeEvent method of the QWidget, having it call the method that joins (or terminates) subprocesses and then having it call either deleteLater() or destroy().

    def closeEvent(self, event):
        logger.info("stopping spin")
        self.stylusProximityControlOff()
        self.deleteLater() 


来源:https://stackoverflow.com/questions/20895645/how-to-have-a-pyqt-window-call-a-method-when-its-x-close-button-is-selected

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!