Un pequeño programa desarrollado con Python 2.7, PyQt 4 y AutoPy para grabar la entrada del usuario (mouse y teclado), y luego simularla. Utiliza Qt para la interfaz gráfica, como también para capturar los eventos de presión de teclas, y AutoPy para reproducirlas. Gracias a la portabilidad de estos módulos, el código corre en las distintas plataformas. Puedes descargar el código de fuente como archivo ZIP desde este enlace.
Vista previa
Puedes ver el video del programa en funcionamiento en nuestra página de Google+.
Utilización
Sencillamente se presiona el botón «Record» para comenzar con la grabación. El programa torna a pantalla completa para capturar la totalidad de los eventos. Una vez finalizado, se presiona la tecla asignada para detener la grabación (Esc
por defecto). El botón «Play» estará ahora habilitado para reproducir los eventos.
Limitaciones
Las teclas Alt
, Control
, Shift
y Meta
son soportadas como pulsaciones convencionales, no así como modificadores. Algunos programas pueden obtener la entrada del usuario por otros métodos, especialmente los juegos, por lo que las pulsaciones enviadas serán ignoradas.
Código de fuente
#!/usr/bin/env python # -*- coding: utf-8 -*- import sys from threading import Thread from time import sleep, time import autopy from PyQt4.QtCore import Qt, QEvent from PyQt4.QtGui import (QApplication, QMainWindow, QLabel, QLineEdit, QPainter, QPushButton, QKeyEvent, QKeySequence, QSlider, QVBoxLayout, QWidget) additional_key_names = { Qt.Key_Control: "Ctrl", Qt.Key_Alt: "Alt", Qt.Key_AltGr: "Alt Gr", Qt.Key_Shift: "Shift", Qt.Key_Meta: "Meta" } # Nombres de teclas de Qt a AutoPy autopy_keys = { "F1": autopy.key.K_F1, "F2": autopy.key.K_F2, "F3": autopy.key.K_F3, "F4": autopy.key.K_F4, "F5": autopy.key.K_F5, "F6": autopy.key.K_F6, "F7": autopy.key.K_F7, "F8": autopy.key.K_F8, "F9": autopy.key.K_F9, "F10": autopy.key.K_F10, "F11": autopy.key.K_F11, "F12": autopy.key.K_F12, "Meta": autopy.key.K_META, "Shift": autopy.key.K_SHIFT, "CapsLock": autopy.key.K_CAPSLOCK, "Return": autopy.key.K_RETURN, "Esc": autopy.key.K_ESCAPE, "Space": " ", "PgUp": autopy.key.K_PAGEUP, "PgDown": autopy.key.K_PAGEDOWN, "Del": autopy.key.K_DELETE, "End": autopy.key.K_END, "Alt": autopy.key.K_ALT, "Ctrl": autopy.key.K_CONTROL, "Backspace": autopy.key.K_BACKSPACE, } EVENT_KEYBOARD = 0 EVENT_MOUSE = 1 class Ellipse(QWidget): """ Simple círculo. """ def paintEvent(self, event): painter = QPainter(self) painter.drawEllipse(0, 0, 50, 50) class KeySelector(QLineEdit): """ Caja de texto para seleccionar una tecla. """ def __init__(self, parent, prompt, default_key): self.prompt = prompt self.key = default_key QLineEdit.__init__(self, parent) self.keyReleaseEvent( QKeyEvent(QEvent.KeyRelease, default_key, Qt.KeyboardModifiers()) ) def keyPressEvent(self, event): pass def keyReleaseEvent(self, event): key_name = (additional_key_names[event.key()] if event.key() in additional_key_names else QKeySequence(event.key()).toString()) self.key = event.key() self.setText(self.prompt.format(key_name)) class Window(QMainWindow): def __init__(self): QMainWindow.__init__(self) self.setWindowTitle("Input Recorder") self.recording = False self.recorded_events = [] self.record_button = QPushButton("Record", self) self.record_button.clicked.connect(self.start_record) self.play_button = QPushButton("Play", self) self.play_button.clicked.connect(self.play) self.play_button.setEnabled(False) self.key_label = QLabel(self) self.key_label.setGeometry(10, 10, 250, 50) self.key_label.setStyleSheet("font-size: 30px;") self.transparency_slider = QSlider(Qt.Horizontal, self) self.transparency_slider.setMaximum(80) self.transparency_slider.setSliderPosition(40) self.transparency_slider.valueChanged.connect( self.set_transparency_value) self.transparency_label = QLabel("Transparency: 40%.", self) self.key_selector = KeySelector(self, "Stop recording with: {0}", Qt.Key_Escape) self.ellipse = Ellipse(self) self.ellipse.resize(60, 60) self.ellipse.hide() self.layout = QVBoxLayout() self.layout.addWidget(self.record_button) self.layout.addWidget(self.play_button) self.layout.addWidget(self.transparency_slider) self.layout.addWidget(self.transparency_label) self.layout.addWidget(self.key_selector) self.central_widget = QWidget(self) self.central_widget.setLayout(self.layout) self.setCentralWidget(self.central_widget) self.resize(500, 400) def add_event(self, event, *params): sleep_time = time() - self.last_time self.last_time = time() self.recorded_events.append((sleep_time, event, params)) def events_player_thread(self): self.showMinimized() for event in self.recorded_events: sleep_time, event_type, params = event sleep(sleep_time) if event_type == EVENT_KEYBOARD: qt_key = str(params[0]) # Enviar pulsación de tecla. autopy.key.tap( autopy_keys[qt_key] if qt_key in autopy_keys else qt_key.lower() ) elif event_type == EVENT_MOUSE: x, y = params # Enviar pulsación del ratón. autopy.mouse.move(x + 10, y) autopy.mouse.click() # Restaurar ventana. self.showNormal() def mousePressEvent(self, event): if self.recording: # Dibujar un círculo donde se haya presionado. self.ellipse.move(event.x() - 25, event.y() - 25) self.ellipse.show() self.add_event(EVENT_MOUSE, event.x(), event.y()) return QMainWindow.mousePressEvent(self, event) def mouseReleaseEvent(self, event): if self.recording: self.ellipse.hide() return QMainWindow.mouseReleaseEvent(self, event) def keyPressEvent(self, event): if self.recording: if event.key() == self.key_selector.key: self.stop_record() else: # Buscar un nombre predefinido disponible. # De no encontrarlo, utilizar el nombre de la tecla de Qt. key_name = (additional_key_names[event.key()] if event.key() in additional_key_names else QKeySequence(event.key()).toString()) self.key_label.setText(key_name) self.add_event(EVENT_KEYBOARD, key_name) return QMainWindow.keyPressEvent(self, event) def play(self): # Evitar bloquear el bucle principal. Thread(target=self.events_player_thread).start() def set_transparency_value(self, value): self.transparency_label.setText("Transparency: %d%%." % value) def start_record(self): self.recording = True self.recorded_events = [] self.last_time = time() # Ocultar controles. self.central_widget.hide() # Establecer transparencia. self.setWindowOpacity( (100. - self.transparency_slider.value()) / 100. ) # Pantalla completa. self.showFullScreen() def stop_record(self): # Restaurar la configuración inicial. self.recording = False self.central_widget.show() self.setWindowOpacity(1.0) self.showNormal() self.key_label.setText("") if self.recorded_events: self.play_button.setEnabled(True) if __name__ == "__main__": app = QApplication([]) window = Window() window.show() sys.exit(app.exec_())
Curso online 👨💻
¡Ya lanzamos el curso oficial de Recursos Python en Udemy!
Un curso moderno para aprender Python desde cero con programación orientada a objetos, SQL y tkinter
en 2024.
Consultoría 💡
Ofrecemos servicios profesionales de desarrollo y capacitación en Python a personas y empresas. Consultanos por tu proyecto.
Luis Pallares says:
podrias convertirlo en ejecutable? no tengo python 2.7 ni pyqt4 , tengo 3.6 y pyqt5