├── .gitattributes ├── .gitignore ├── 01-ventanas ├── icon.ico └── ventana.py ├── 02-layout ├── absolute.py ├── box-layout.py └── grid-layout.py ├── 03-eventos └── events.py ├── 04-dibujar ├── image │ ├── image.jpg │ └── small_image.jpg └── paint.py ├── 05_A-widgets └── widgets.py ├── 06-items-views └── item-view.py ├── 07-dialogs └── dialogs.py ├── 08-qss └── untitled.ui ├── 09-base de datos └── database.py ├── 10-opencv └── main.py ├── 11-web └── web.py ├── 12-menu └── menu.py ├── 13-multimedia └── multimedia.py └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | 30 | # ========================= 31 | # Operating System Files 32 | # ========================= 33 | 34 | # OSX 35 | # ========================= 36 | 37 | .DS_Store 38 | .AppleDouble 39 | .LSOverride 40 | 41 | # Thumbnails 42 | ._* 43 | 44 | # Files that might appear in the root of a volume 45 | .DocumentRevisions-V100 46 | .fseventsd 47 | .Spotlight-V100 48 | .TemporaryItems 49 | .Trashes 50 | .VolumeIcon.icns 51 | 52 | # Directories potentially created on remote AFP share 53 | .AppleDB 54 | .AppleDesktop 55 | Network Trash Folder 56 | Temporary Items 57 | .apdisk 58 | 59 | # Windows 60 | # ========================= 61 | 62 | # Windows image file caches 63 | Thumbs.db 64 | ehthumbs.db 65 | 66 | # Folder config file 67 | Desktop.ini 68 | 69 | # Recycle Bin used on file shares 70 | $RECYCLE.BIN/ 71 | 72 | # Windows Installer files 73 | *.cab 74 | *.msi 75 | *.msm 76 | *.msp 77 | 78 | # Windows shortcuts 79 | *.lnk 80 | -------------------------------------------------------------------------------- /01-ventanas/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TutorProgramacion/pyqt-tutorial/67bdc86dc6e7251457487ed55b6901fae6a857c1/01-ventanas/icon.ico -------------------------------------------------------------------------------- /01-ventanas/ventana.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | from PyQt5.QtCore import QCoreApplication 4 | from PyQt5.QtGui import QIcon 5 | from PyQt5.QtWidgets import QApplication, QWidget, QPushButton 6 | 7 | 8 | if __name__ == '__main__': 9 | app = QApplication(sys.argv) 10 | 11 | w = QWidget() 12 | w.setWindowTitle('Ventana PyQT-5') 13 | w.setWindowIcon(QIcon('icon.ico')) 14 | 15 | btn = QPushButton('Este es un Button', w) 16 | btn.setToolTip('This is a QPushButton widget') 17 | btn.move(150, 50) 18 | 19 | btn.setIcon(QIcon('icon.ico')) 20 | btn.clicked.connect(QCoreApplication.instance().quit) 21 | 22 | w.resize(1280, 720) 23 | w.show() 24 | 25 | sys.exit(app.exec_()) 26 | -------------------------------------------------------------------------------- /02-layout/absolute.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLabel, QLineEdit 4 | 5 | 6 | if __name__ == '__main__': 7 | app = QApplication(sys.argv) 8 | 9 | w = QWidget() 10 | w.setWindowTitle('Layout PyQT-5') 11 | w.resize(250, 120) 12 | 13 | lblName = QLabel("Nombre:", w) 14 | lblName.move(20, 20) 15 | 16 | lblPass = QLabel("Contraseña:", w) 17 | lblPass.move(20, 50) 18 | 19 | txtName = QLineEdit(w) 20 | txtName.setPlaceholderText("Nombre de usuario") 21 | txtName.move(100, 15) 22 | 23 | txtPass = QLineEdit(w) 24 | txtPass.setPlaceholderText("Contraseña de usuario") 25 | txtPass.move(100, 45) 26 | 27 | btnLogin = QPushButton("Login", w) 28 | btnLogin.move(20, 80) 29 | btnLogin.resize(218, 30) 30 | 31 | w.show() 32 | 33 | sys.exit(app.exec_()) 34 | -------------------------------------------------------------------------------- /02-layout/box-layout.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout, QHBoxLayout 3 | 4 | 5 | if __name__ == '__main__': 6 | app = QApplication(sys.argv) 7 | 8 | w = QWidget() 9 | w.setWindowTitle('Layout PyQT-5') 10 | w.resize(250, 120) 11 | 12 | vbox = QVBoxLayout() 13 | vbox.setSpacing(20) 14 | 15 | for n in range(5): 16 | if n == 2: 17 | hbox = QHBoxLayout() 18 | for m in range(3): 19 | hbox.addWidget(QPushButton("Button #" + str(m))) 20 | vbox.addLayout(hbox) 21 | else: 22 | vbox.addWidget(QPushButton("Button #" + str(n))) 23 | 24 | w.setLayout(vbox) 25 | w.show() 26 | 27 | sys.exit(app.exec_()) 28 | -------------------------------------------------------------------------------- /02-layout/grid-layout.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLabel, QLineEdit, QGridLayout 4 | 5 | 6 | if __name__ == '__main__': 7 | app = QApplication(sys.argv) 8 | 9 | w = QWidget() 10 | w.setWindowTitle('Layout PyQT-5') 11 | w.resize(250, 120) 12 | 13 | lblName = QLabel("Nombre:") 14 | txtName = QLineEdit() 15 | txtName.setPlaceholderText("Nombre de usuario") 16 | 17 | lblPass = QLabel("Contraseña:") 18 | txtPass = QLineEdit(w) 19 | txtPass.setPlaceholderText("Contraseña de usuario") 20 | 21 | grid = QGridLayout() 22 | grid.addWidget(lblName, 0, 0) 23 | grid.addWidget(txtName, 0, 1) 24 | grid.addWidget(lblPass, 1, 0) 25 | grid.addWidget(txtPass, 1, 1) 26 | 27 | btnLogin = QPushButton("Login", w) 28 | grid.addWidget(btnLogin, 2, 0, 1, 2) 29 | 30 | w.setLayout(grid) 31 | w.show() 32 | 33 | sys.exit(app.exec_()) 34 | -------------------------------------------------------------------------------- /03-eventos/events.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from PyQt5.QtCore import Qt 3 | from PyQt5.QtWidgets import QPushButton, QApplication, QMessageBox, QWidget 4 | 5 | 6 | class Example(QWidget): 7 | def __init__(self): 8 | super().__init__() 9 | self.initUI() 10 | 11 | def initUI(self): 12 | btn1 = QPushButton("Button 1", self) 13 | btn1.resize(150, 40) 14 | btn1.move(400 / 2 - 150 / 2, 200 / 2 - 40) 15 | btn1.clicked.connect(self.buttonClicked) 16 | 17 | btn2 = QPushButton("Button 2", self) 18 | btn2.resize(150, 40) 19 | btn2.move(400 / 2 - 150 / 2, 200 / 2) 20 | btn2.clicked.connect(self.buttonClicked) 21 | 22 | self.resize(400, 200) 23 | self.setMaximumSize(400, 200) 24 | self.setWindowTitle('Event PyQT5') 25 | self.show() 26 | 27 | def buttonClicked(self, e): 28 | btn_txt = self.sender().text() 29 | QMessageBox.information(self, 'Events - Slot', 'click en: ' + btn_txt) 30 | 31 | def closeEvent(self, event): 32 | reply = QMessageBox.question(self, 33 | 'Events - Slot', 34 | "Realmente desea cerrar la aplicacion", 35 | QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) 36 | 37 | if reply == QMessageBox.Yes: 38 | event.accept() 39 | else: 40 | event.ignore() 41 | 42 | def keyPressEvent(self, event): 43 | if event.key() == Qt.Key_Escape: 44 | self.close() 45 | 46 | 47 | if __name__ == '__main__': 48 | app = QApplication(sys.argv) 49 | win = Example() 50 | sys.exit(app.exec_()) 51 | 52 | 53 | -------------------------------------------------------------------------------- /04-dibujar/image/image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TutorProgramacion/pyqt-tutorial/67bdc86dc6e7251457487ed55b6901fae6a857c1/04-dibujar/image/image.jpg -------------------------------------------------------------------------------- /04-dibujar/image/small_image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TutorProgramacion/pyqt-tutorial/67bdc86dc6e7251457487ed55b6901fae6a857c1/04-dibujar/image/small_image.jpg -------------------------------------------------------------------------------- /04-dibujar/paint.py: -------------------------------------------------------------------------------- 1 | __author__ = 'Carmelo Marin Abrego' 2 | 3 | import sys 4 | 5 | from PyQt5.QtGui import QPainter, QFont, QColor, QPixmap, QPen, QBrush 6 | from PyQt5.QtCore import Qt, QRect, QPoint 7 | from PyQt5.QtWidgets import QApplication, QWidget, QPushButton 8 | 9 | 10 | class Example(QWidget): 11 | def __init__(self): 12 | super().__init__() 13 | self.initUI() 14 | 15 | def initUI(self): 16 | self.resize(1280, 720) 17 | self.setWindowTitle('PyQT5 Paint Event') 18 | 19 | def paintEvent(self, event): 20 | qp = QPainter() 21 | qp.begin(self) 22 | self.drawImage(event, qp, 'image/image.jpg') 23 | self.drawText(event, qp, 'Tutor de Programación\nPintar con PyQT5') 24 | self.drawPoint(event, qp) 25 | self.drawLine(event, qp) 26 | self.drawShape(event, qp) 27 | qp.end() 28 | 29 | def drawShape(self, event, qp): 30 | pen = QPen(Qt.yellow) 31 | pen.setWidth(3) 32 | # rellenar fondo con patron de imagen 33 | brush = QBrush() 34 | brush.setTexture(QPixmap('image/small_image.jpg')) 35 | # establecer el QBrush 36 | qp.setBrush(brush) 37 | qp.setPen(pen) 38 | qp.drawRoundedRect(QRect(50, 50, 200, 150), 15, 15) 39 | # utilizar un patron predefinido 40 | brush.setStyle(Qt.DiagCrossPattern) 41 | qp.setBrush(brush) 42 | qp.drawEllipse(350, 50, 150, 150) 43 | 44 | def drawPoint(self, event, qp): 45 | pen = QPen(Qt.red) 46 | pen.setWidth(10) 47 | 48 | qp.setPen(pen) 49 | qp.drawPoint(event.rect().width() / 2, event.rect().height() / 2) 50 | 51 | def drawLine(self, event, qp): 52 | pen = QPen() 53 | pen.setWidth(3) 54 | pen.setColor(QColor(128, 250, 25, 255)) 55 | pen.setStyle(Qt.DotLine) 56 | 57 | qp.setPen(pen) 58 | qp.drawLine(QPoint(10, 10), QPoint(1280 - 10, 10)) 59 | 60 | color = QColor() 61 | color.setNamedColor('#c2h6b4') 62 | 63 | pen.setColor(color) 64 | pen.setStyle(Qt.DashLine) 65 | 66 | qp.setPen(pen) 67 | qp.drawLine(QPoint(10, 10 + 20), QPoint(1280 - 10, 10 + 20)) 68 | 69 | 70 | def drawImage(self, event, qp, image): 71 | pixmap = QPixmap(image) 72 | qp.drawPixmap(event.rect(), pixmap) 73 | # qp.drawPixmap(QRect(0, 0, 1280, 720), pixmap) 74 | 75 | def drawText(self, event, qp, text): 76 | qp.setPen(QColor(0, 255, 255)) 77 | qp.setFont(QFont('Consolas', 48)) 78 | qp.drawText(event.rect(), Qt.AlignCenter, text) 79 | 80 | 81 | if __name__ == '__main__': 82 | app = QApplication(sys.argv) 83 | win = Example() 84 | win.show() 85 | sys.exit(app.exec_()) 86 | 87 | 88 | -------------------------------------------------------------------------------- /05_A-widgets/widgets.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | from PyQt5.QtWidgets import QWidget, QApplication, QCheckBox, QLineEdit, QLabel, QSlider, QLCDNumber, QCalendarWidget, \ 4 | QGroupBox, QRadioButton, QVBoxLayout 5 | from PyQt5.QtCore import Qt 6 | 7 | 8 | class Example(QWidget): 9 | def __init__(self): 10 | super().__init__() 11 | self.initUI() 12 | 13 | def initUI(self): 14 | 15 | self.addCheckBox() 16 | self.addLineEdit() 17 | self.addSlider() 18 | self.addCalendar() 19 | self.addRadioBoton() 20 | 21 | self.resize(640, 320) 22 | self.setWindowTitle('Controles PyQT 5 by Tutor de Programacion') 23 | 24 | def addRadioBoton(self): 25 | gbx = QGroupBox('Tu Lenguaje Favorito', self) 26 | gbx.setGeometry(20, 150, 185, 120) 27 | # crear tres QRadioButton 28 | radio1 = QRadioButton("C/C++") 29 | radio2 = QRadioButton("Python") 30 | radio3 = QRadioButton("Java") 31 | # agregar los widgets al layout vertical 32 | vbox = QVBoxLayout(self) 33 | vbox.addWidget(radio1) 34 | vbox.addWidget(radio2) 35 | vbox.addWidget(radio3) 36 | # establecer el layout del QGroupBox 37 | gbx.setLayout(vbox) 38 | 39 | # radio1.setChecked(True) 40 | # print(radio1.isChecked()) 41 | 42 | 43 | def addCalendar(self): 44 | cal = QCalendarWidget(self) 45 | cal.setGridVisible(True) 46 | cal.clicked.connect(self.timeSelected) 47 | cal.move(300, 20) 48 | 49 | def timeSelected(self, date): 50 | print('La Fecha es: ', date.toString()) 51 | 52 | def addSlider(self): 53 | sld = QSlider(Qt.Horizontal, self) 54 | # establecer posicion (x,y) y dimenciones (ancho, alto) 55 | sld.setGeometry(20, 80, 150, 30) 56 | # indicar rango de valores validos 57 | sld.setRange(50, 250) 58 | # establecer valor inicial 59 | sld.setValue(120) 60 | # evento producido cada vez que cambia el valor 61 | sld.valueChanged.connect(self.valChange) 62 | 63 | num = QLCDNumber(self) 64 | num.setGeometry(180, 80, 50, 30) 65 | # mostrar valor inicial 66 | num.display(sld.value()) 67 | # cambiar valor QLCDNumber cuando cambiar QSlider 68 | sld.valueChanged.connect(num.display) 69 | 70 | def valChange(self, value): 71 | print('QSlider value: ', value) 72 | 73 | def addLineEdit(self): 74 | # crea un texto no es editable 75 | lbl = QLabel('Nombre:', self) 76 | lbl.move(20, 52) 77 | 78 | # crea un widget que permite editar una linea de texto 79 | txt = QLineEdit(self) 80 | txt.move(72, 50) 81 | # establece un texto informativo 82 | txt.setPlaceholderText('Dime tu nombre') 83 | # evento producido cada vez que cambia el texto 84 | txt.textChanged.connect(self.textChange) 85 | # establece el foco en el widget 86 | txt.setFocus() 87 | # obtiene el texto escrito 88 | nombre = txt.text() 89 | 90 | def textChange(self, text): 91 | print('El nuevo texto es: ', text) 92 | 93 | 94 | def addCheckBox(self): 95 | # Crear el widget 96 | cbx = QCheckBox('Mostrar/Ocultar', self) 97 | # Cambiar estado del CheckBox puede ser: Qt.PartiallyChecked, Qt.Checked, Qt.Unchecked 98 | cbx.setCheckState(Qt.PartiallyChecked) 99 | # Responder al evento de cambio de estado 100 | cbx.stateChanged.connect(self.cbxChange) 101 | # Ubicar el control en la posicion (x, y) 102 | cbx.move(20, 20) 103 | 104 | def cbxChange(self, state): 105 | print('CheckBox State: ', state) 106 | 107 | 108 | if __name__ == '__main__': 109 | app = QApplication(sys.argv) 110 | win = Example() 111 | win.show() 112 | sys.exit(app.exec_()) 113 | -------------------------------------------------------------------------------- /06-items-views/item-view.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | from PyQt5.QtCore import Qt 4 | from PyQt5.QtWidgets import QWidget, QApplication, QVBoxLayout, QPushButton, QComboBox, QStyleFactory, QListWidget, \ 5 | QTableWidget, QTableWidgetItem, QListWidgetItem 6 | 7 | 8 | class Example(QWidget): 9 | def __init__(self, parent=None): 10 | super(Example, self).__init__(parent) 11 | QApplication.setStyle(QStyleFactory.create('Fusion')) 12 | 13 | # -------------- QCOMBOBOX ---------------------- 14 | cbx = QComboBox() 15 | # agregar lista de nombres de estilos disponibles 16 | cbx.addItems(QStyleFactory.keys()) 17 | # responder al evento cambio de texto 18 | cbx.currentTextChanged.connect(self.textChanged) 19 | # seleccionar el ultimo elemento 20 | cbx.setItemText(4, 'Fusion') 21 | 22 | # -------------- QLISTWIDGET --------------------- 23 | items = ['Ubuntu', 'Linux', 'Mac OS', 'Windows', 'Fedora', 'Chrome OS', 'Android', 'Windows Phone'] 24 | 25 | self.lv = QListWidget() 26 | self.lv.addItems(items) 27 | self.lv.itemSelectionChanged.connect(self.itemChanged) 28 | 29 | # -------------- QTABLEWIDGET -------------------- 30 | self.table = QTableWidget(10, 3) 31 | # establecer nombre de cabecera de las columnas 32 | self.table.setHorizontalHeaderLabels(['Nombre', 'Edad', 'Nacionalidad']) 33 | # evento producido cuando cambia el elemento seleccionado 34 | self.table.itemSelectionChanged.connect(self.tableItemChanged) 35 | # alternar color de fila 36 | self.table.setAlternatingRowColors(True) 37 | # seleccionar solo filas 38 | self.table.setSelectionBehavior(QTableWidget.SelectRows) 39 | # usar seleccion simple, una fila a la vez 40 | self.table.setSelectionMode(QTableWidget.SingleSelection) 41 | 42 | table_data = [ 43 | ("Alice", 15, "Panama"), 44 | ("Dana", 25, "Chile"), 45 | ("Fernada", 18, "Ecuador") 46 | ] 47 | 48 | # agregar cada uno de los elementos al QTableWidget 49 | for i, (name, age, city) in enumerate(table_data): 50 | self.table.setItem(i, 0, QTableWidgetItem(name)) 51 | self.table.setItem(i, 1, QTableWidgetItem(str(age))) 52 | self.table.setItem(i, 2, QTableWidgetItem(city)) 53 | 54 | vbx = QVBoxLayout() 55 | vbx.addWidget(QPushButton('Tutoriales PyQT-5')) 56 | vbx.setAlignment(Qt.AlignTop) 57 | vbx.addWidget(cbx) 58 | vbx.addWidget(self.lv) 59 | vbx.addWidget(self.table) 60 | 61 | self.setWindowTitle("Items View") 62 | self.resize(362, 320) 63 | self.setLayout(vbx) 64 | 65 | def textChanged(self, txt): 66 | QApplication.setStyle(QStyleFactory.create(txt)) 67 | 68 | def itemChanged(self): 69 | item = QListWidgetItem(self.lv.currentItem()) 70 | print("Sistema seleccionado: ", item.text()) 71 | 72 | def tableItemChanged(self): 73 | name, age, city = self.table.selectedItems() 74 | print("Data:", name.text(), age.text(), city.text()) 75 | 76 | 77 | if __name__ == '__main__': 78 | app = QApplication(sys.argv) 79 | ejm = Example() 80 | ejm.show() 81 | sys.exit(app.exec_()) 82 | -------------------------------------------------------------------------------- /07-dialogs/dialogs.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | from PyQt5.QtCore import Qt, QDir 4 | from PyQt5.QtGui import QPalette 5 | from PyQt5.QtWidgets import QWidget, QApplication, QInputDialog, QVBoxLayout, QPushButton, QFileDialog, QColorDialog, \ 6 | QFontDialog, QMessageBox 7 | 8 | 9 | class Example(QWidget): 10 | def __init__(self, parent=None): 11 | super(Example, self).__init__(parent) 12 | 13 | btn0 = QPushButton('Mostrar QInputDialog') 14 | btn0.clicked.connect(self.showIntDialog) 15 | 16 | btn1 = QPushButton('Mostrar QFileDialog') 17 | btn1.clicked.connect(self.buscarArchivo) 18 | 19 | btn2 = QPushButton('Mostrar QColorDialog') 20 | btn2.clicked.connect(self.buscarColor) 21 | 22 | btn3 = QPushButton('Mostrar QFontDialog') 23 | btn3.clicked.connect(self.cambiarFuente) 24 | 25 | btn4 = QPushButton('Mostrar QMessageBox') 26 | btn4.clicked.connect(self.showDialog) 27 | 28 | vbox = QVBoxLayout() 29 | vbox.addWidget(btn0) 30 | vbox.addWidget(btn1) 31 | vbox.addWidget(btn2) 32 | vbox.addWidget(btn3) 33 | vbox.addWidget(btn4) 34 | vbox.addStretch(0) 35 | 36 | self.setLayout(vbox) 37 | self.setWindowTitle("Cuadros de Dialogo") 38 | self.resize(250, 320) 39 | 40 | def buscarArchivo(self): 41 | file, _ = QFileDialog.getOpenFileName(self, 'Buscar Archivo')#, QDir.homePath(), "All Files (*);;Text Files (*.txt)") 42 | if file: 43 | print("Archivo seleccionado: ", file) 44 | 45 | def showIntDialog(self): 46 | value, ok = QInputDialog.getText(self, "getText()", "Como te llamas:") 47 | if ok and value != '' : print('Nombre:', value) 48 | 49 | value, ok = QInputDialog.getInt(self, "getInt()", "Dime Tu Edad:", 18, 1, 150) 50 | if ok : print('Edad:', value) 51 | 52 | value, ok = QInputDialog.getDouble(self, "getDouble()", "Cuanto Pesas:") 53 | if ok : print('Peso:', value) 54 | 55 | items = ("Perro", "Gato", "Aves", "Serpientes", "Otros") 56 | value, ok = QInputDialog.getItem(self, "getItem()", "Mascota favorita:", items, 2) 57 | if ok : print('Mascota:', value) 58 | 59 | def buscarColor(self): 60 | color = QColorDialog.getColor(Qt.red, self) 61 | if color.isValid(): 62 | self.setPalette(QPalette(color)) 63 | 64 | def cambiarFuente(self): 65 | font, ok = QFontDialog.getFont(self) 66 | if ok: 67 | self.setFont(font) 68 | 69 | def showDialog(self): 70 | # QMessageBox.warning(self, "Warning Dialog", "Peligro Alto Voltage") 71 | reply = QMessageBox.critical(self, "QMessageBox.critical()", 72 | "Error irrecuperable en la aplicacion \n que desea hacer para proceder.", 73 | QMessageBox.Abort | QMessageBox.Retry | QMessageBox.Ignore) 74 | if reply == QMessageBox.Abort: 75 | print("Abortar la mision") 76 | elif reply == QMessageBox.Retry: 77 | print("Intentar nuevamente") 78 | else: 79 | print("Nada por ahora") 80 | 81 | if __name__ == '__main__': 82 | app = QApplication(sys.argv) 83 | dialog = Example() 84 | dialog.show() 85 | sys.exit(app.exec_()) -------------------------------------------------------------------------------- /08-qss/untitled.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 327 10 | 172 11 | 12 | 13 | 14 | MainWindow 15 | 16 | 17 | QLabel { 18 | color: rgb(0, 0, 255); 19 | font: 75 8pt "Roboto Medium"; 20 | } 21 | 22 | QPushButton 23 | { 24 | color: red; 25 | background: white; 26 | border: 1px solid red; 27 | border-radius: 10px; 28 | } 29 | 30 | QPushButton#aceptar 31 | { 32 | color: green; 33 | border-color: green; 34 | } 35 | 36 | QLineEdit { 37 | border: 1px solid blue; 38 | border-radius: 4px; 39 | } 40 | 41 | 42 | 43 | 44 | 45 | 170 46 | 90 47 | 141 48 | 27 49 | 50 | 51 | 52 | Aceptar 53 | 54 | 55 | 56 | 57 | 58 | 20 59 | 90 60 | 131 61 | 27 62 | 63 | 64 | 65 | Cancelar 66 | 67 | 68 | 69 | 70 | 71 | 90 72 | 20 73 | 221 74 | 22 75 | 76 | 77 | 78 | 79 | 80 | 81 | 90 82 | 50 83 | 221 84 | 22 85 | 86 | 87 | 88 | 89 | 90 | 91 | 20 92 | 20 93 | 53 94 | 16 95 | 96 | 97 | 98 | Nombre 99 | 100 | 101 | 102 | 103 | 104 | 20 105 | 50 106 | 71 107 | 16 108 | 109 | 110 | 111 | Contraseña 112 | 113 | 114 | 115 | 116 | 117 | 118 | 0 119 | 0 120 | 327 121 | 25 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /09-base de datos/database.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | from PyQt5.QtSql import * 4 | from PyQt5.QtCore import Qt, QModelIndex 5 | from PyQt5.QtWidgets import QWidget, QApplication, QVBoxLayout, QPushButton, \ 6 | QTableWidget, QTableWidgetItem, QMessageBox, QHBoxLayout, QLineEdit, QLabel, QGridLayout 7 | 8 | 9 | class Example(QWidget): 10 | def __init__(self, parent=None): 11 | super(Example, self).__init__(parent) 12 | 13 | self.table = QTableWidget(0, 3) 14 | self.table.setHorizontalHeaderLabels(['ID', 'NOMBRE', 'APELLIDO']) 15 | self.table.setAlternatingRowColors(True) 16 | self.table.setEditTriggers(QTableWidget.NoEditTriggers) 17 | self.table.setSelectionBehavior(QTableWidget.SelectRows) 18 | self.table.setSelectionMode(QTableWidget.SingleSelection) 19 | 20 | self.lblID = QLabel("ID:") 21 | self.txtID = QLineEdit() 22 | self.txtID.setPlaceholderText("Numero identificador unico") 23 | 24 | self.lblName = QLabel("Nombre:") 25 | self.txtName = QLineEdit() 26 | self.txtName.setPlaceholderText("Nombre de la persona") 27 | 28 | self.lblApellido = QLabel("Apellido:") 29 | self.txtApellido = QLineEdit() 30 | self.txtApellido.setPlaceholderText("Apellido de la persona") 31 | 32 | grid = QGridLayout() 33 | grid.addWidget(self.lblID, 0, 0) 34 | grid.addWidget(self.txtID, 0, 1) 35 | grid.addWidget(self.lblName, 1, 0) 36 | grid.addWidget(self.txtName, 1, 1) 37 | grid.addWidget(self.lblApellido, 2, 0) 38 | grid.addWidget(self.txtApellido, 2, 1) 39 | 40 | btnCargar = QPushButton('Cargar Datos') 41 | btnCargar.clicked.connect(self.cargarDatos) 42 | 43 | btnInsertar = QPushButton('Insertar') 44 | btnInsertar.clicked.connect(self.insertarDatos) 45 | 46 | btnEliminar = QPushButton('Eliminar') 47 | btnEliminar.clicked.connect(self.eliminarDatos) 48 | 49 | hbx = QHBoxLayout() 50 | hbx.addWidget(btnCargar) 51 | hbx.addWidget(btnInsertar) 52 | hbx.addWidget(btnEliminar) 53 | 54 | vbx = QVBoxLayout() 55 | vbx.addLayout(grid) 56 | vbx.addLayout(hbx) 57 | vbx.setAlignment(Qt.AlignTop) 58 | vbx.addWidget(self.table) 59 | 60 | self.setWindowTitle("PyQT :: SQLite Data Access") 61 | self.resize(362, 320) 62 | self.setLayout(vbx) 63 | 64 | def cargarDatos(self, event): 65 | index = 0 66 | query = QSqlQuery() 67 | query.exec_("select * from person") 68 | 69 | while query.next(): 70 | ids = query.value(0) 71 | nombre = query.value(1) 72 | apellido = query.value(2) 73 | 74 | self.table.setRowCount(index + 1) 75 | self.table.setItem(index, 0, QTableWidgetItem(str(ids))) 76 | self.table.setItem(index, 1, QTableWidgetItem(nombre)) 77 | self.table.setItem(index, 2, QTableWidgetItem(apellido)) 78 | 79 | index += 1 80 | 81 | def insertarDatos(self, event): 82 | ids = int(self.txtID.text()) 83 | nombre = self.txtName.text() 84 | apellido = self.txtApellido.text() 85 | 86 | query = QSqlQuery() 87 | query.exec_("insert into person values({0}, '{1}', '{2}')".format(ids, nombre, apellido)) 88 | 89 | def eliminarDatos(self, event): 90 | selected = self.table.currentIndex() 91 | if not selected.isValid() or len(self.table.selectedItems()) < 1: 92 | return 93 | 94 | ids = self.table.selectedItems()[0] 95 | query = QSqlQuery() 96 | query.exec_("delete from person where id = " + ids.text()) 97 | 98 | self.table.removeRow(selected.row()) 99 | self.table.setCurrentIndex(QModelIndex()) 100 | 101 | def db_connect(self, filename, server): 102 | db = QSqlDatabase.addDatabase(server) 103 | db.setDatabaseName(filename) 104 | if not db.open(): 105 | QMessageBox.critical(None, "Cannot open database", 106 | "Unable to establish a database connection.\n" 107 | "This example needs SQLite support. Please read the Qt SQL " 108 | "driver documentation for information how to build it.\n\n" 109 | "Click Cancel to exit.", QMessageBox.Cancel) 110 | return False 111 | return True 112 | 113 | def db_create(self): 114 | query = QSqlQuery() 115 | query.exec_("create table person(id int primary key, " 116 | "firstname varchar(20), lastname varchar(20))") 117 | query.exec_("insert into person values(101, 'Danny', 'Young')") 118 | query.exec_("insert into person values(102, 'Christine', 'Holand')") 119 | query.exec_("insert into person values(103, 'Lars', 'Gordon')") 120 | query.exec_("insert into person values(104, 'Roberto', 'Robitaille')") 121 | query.exec_("insert into person values(105, 'Maria', 'Papadopoulos')") 122 | 123 | def init(self, filename, server): 124 | import os 125 | if not os.path.exists(filename): 126 | self.db_connect(filename, server) 127 | self.db_create() 128 | else: 129 | self.db_connect(filename, server) 130 | 131 | if __name__ == '__main__': 132 | app = QApplication(sys.argv) 133 | ejm = Example() 134 | ejm.init('datafile', 'QSQLITE') 135 | ejm.show() 136 | sys.exit(app.exec_()) 137 | 138 | -------------------------------------------------------------------------------- /10-opencv/main.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import cv2 3 | import numpy 4 | 5 | from PyQt5.QtGui import QImage, QPixmap 6 | from PyQt5.QtWidgets import QWidget, QApplication, QLabel, QVBoxLayout, QHBoxLayout, QPushButton, QFileDialog 7 | from PyQt5.QtCore import Qt 8 | 9 | 10 | class Example(QWidget): 11 | def __init__(self): 12 | super().__init__() 13 | self.image = None 14 | self.label = QLabel() 15 | self.initUI() 16 | 17 | def initUI(self): 18 | self.label.setText('OpenCV Image') 19 | self.label.setAlignment(Qt.AlignCenter) 20 | self.label.setStyleSheet('border: gray; border-style:solid; border-width: 1px;') 21 | 22 | btn_open = QPushButton('Abir Imagen...') 23 | btn_open.clicked.connect(self.abrirImagen) 24 | 25 | btn_procesar = QPushButton('Processar Imagen') 26 | btn_procesar.clicked.connect(self.procesarImagen) 27 | 28 | top_bar = QHBoxLayout() 29 | top_bar.addWidget(btn_open) 30 | top_bar.addWidget(btn_procesar) 31 | 32 | root = QVBoxLayout(self) 33 | root.addLayout(top_bar) 34 | root.addWidget(self.label) 35 | 36 | self.resize(540, 574) 37 | self.setWindowTitle('OpenCV & PyQT 5 by Tutor de Programacion') 38 | 39 | def abrirImagen(self): 40 | filename, _ = QFileDialog.getOpenFileName(None, 'Buscar Imagen', '.', 'Image Files (*.png *.jpg *.jpeg *.bmp)') 41 | if filename: 42 | with open(filename, "rb") as file: 43 | data = numpy.array(bytearray(file.read())) 44 | 45 | self.image = cv2.imdecode(data, cv2.IMREAD_UNCHANGED) 46 | # self.image = cv2.imread(filename, cv2.IMREAD_UNCHANGED) 47 | self.mostrarImagen() 48 | 49 | def procesarImagen(self): 50 | if self.image is not None: 51 | # self.image = cv2.GaussianBlur(self.image, (5, 5), 0) 52 | # self.image = cv2.Canny(self.image, 100, 200) 53 | 54 | gray = cv2.cvtColor(self.image, cv2.COLOR_RGB2GRAY) \ 55 | if len(self.image.shape) >= 3 else self.image 56 | 57 | blur = cv2.GaussianBlur(gray, (21, 21), 0, 0) 58 | 59 | self.image = cv2.divide(gray, blur, scale=256) 60 | self.mostrarImagen() 61 | 62 | def mostrarImagen(self): 63 | size = self.image.shape 64 | step = self.image.size / size[0] 65 | qformat = QImage.Format_Indexed8 66 | 67 | if len(size) == 3: 68 | if size[2] == 4: 69 | qformat = QImage.Format_RGBA8888 70 | else: 71 | qformat = QImage.Format_RGB888 72 | 73 | img = QImage(self.image, size[1], size[0], step, qformat) 74 | img = img.rgbSwapped() 75 | 76 | self.label.setPixmap(QPixmap.fromImage(img)) 77 | self.resize(self.label.pixmap().size()) 78 | 79 | if __name__ == '__main__': 80 | app = QApplication(sys.argv) 81 | win = Example() 82 | win.show() 83 | sys.exit(app.exec_()) -------------------------------------------------------------------------------- /11-web/web.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | from PyQt5.QtWebEngineWidgets import QWebEngineView 4 | from PyQt5.QtWidgets import QWidget, QApplication, QLineEdit, QVBoxLayout, QHBoxLayout, QPushButton, QProgressBar 5 | from PyQt5.QtCore import QUrl 6 | 7 | 8 | class Example(QWidget): 9 | def __init__(self): 10 | super().__init__() 11 | self.resize(640, 320) 12 | self.setWindowTitle('PyQt-5 WebEngine') 13 | 14 | page = "https://www.google.com" 15 | 16 | self.url = QLineEdit(page) 17 | self.url.setPlaceholderText(page) 18 | 19 | self.go = QPushButton("Ir") 20 | self.go.clicked.connect(self.btnIrClicked) 21 | 22 | self.nav_bar = QHBoxLayout() 23 | self.nav_bar.addWidget(self.url) 24 | self.nav_bar.addWidget(self.go) 25 | 26 | self.progress = QProgressBar() 27 | self.progress.setValue(0) 28 | 29 | html = """ 30 | 31 | 32 | 33 | Example Local HTML 34 | 35 | 36 |

Este es un archivo HTML local.

37 |

Si deseas acceder página indica su URL y presiona Ir

38 | 39 | 40 | """ 41 | 42 | self.web_view = QWebEngineView() 43 | self.web_view.loadProgress.connect(self.webLoading) 44 | self.web_view.setHtml(html) 45 | 46 | root = QVBoxLayout() 47 | root.addLayout(self.nav_bar) 48 | root.addWidget(self.web_view) 49 | root.addWidget(self.progress) 50 | 51 | self.setLayout(root) 52 | 53 | def btnIrClicked(self, event): 54 | url = QUrl(self.url.text()) 55 | self.web_view.page().load(url) 56 | 57 | def webLoading(self, event): 58 | self.progress.setValue(event) 59 | 60 | 61 | if __name__ == '__main__': 62 | app = QApplication(sys.argv) 63 | win = Example() 64 | win.show() 65 | sys.exit(app.exec_()) -------------------------------------------------------------------------------- /12-menu/menu.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from PyQt5.QtWidgets import QMainWindow, QAction, qApp, QApplication 3 | from PyQt5.QtGui import QIcon 4 | 5 | class Example(QMainWindow): 6 | def __init__(self): 7 | super().__init__() 8 | self.initUI() 9 | 10 | def initUI(self): 11 | exitAction = QAction(QIcon('exit.png'), '&Exit', self) 12 | exitAction.setShortcut('Ctrl+Q') 13 | exitAction.setStatusTip('Exit application') 14 | exitAction.triggered.connect(qApp.quit) 15 | 16 | statusbar = self.statusBar() 17 | menubar = self.menuBar() 18 | 19 | fileMenu = menubar.addMenu('&File') 20 | fileMenu.addAction(exitAction) 21 | 22 | copyAction = QAction(QIcon('copy.png'), 'Copy', self) 23 | pasteAction = QAction(QIcon('paste.png'), 'Paste', self) 24 | cutAction = QAction(QIcon('cut.png'), 'Cut', self) 25 | 26 | editMenu = menubar.addMenu('Ed&it') 27 | editMenu.addAction(copyAction) 28 | editMenu.addAction(pasteAction) 29 | editMenu.addAction(cutAction) 30 | 31 | findMenu = editMenu.addMenu(QIcon('image/find_disabled.png'), 'Find') 32 | 33 | findAction = QAction('Find', self) 34 | findAction.setShortcut('Ctrl+F') 35 | findAction.setStatusTip('Buscar texto indicado') 36 | 37 | replaceAction = QAction('Replace', self) 38 | replaceAction.setShortcut('Ctrl+R') 39 | replaceAction.setStatusTip('Reemplazar texto seleccionado') 40 | 41 | findMenu.addAction(findAction) 42 | findMenu.addAction(replaceAction) 43 | 44 | aboutAction = QAction('&About', self) 45 | helpMenu = menubar.addMenu('&Help') 46 | helpMenu.addAction(aboutAction) 47 | 48 | self.resize(420, 280) 49 | self.setWindowTitle('Menubar And Statusbar') 50 | self.show() 51 | 52 | if __name__ == '__main__': 53 | app = QApplication(sys.argv) 54 | ex = Example() 55 | sys.exit(app.exec_()) -------------------------------------------------------------------------------- /13-multimedia/multimedia.py: -------------------------------------------------------------------------------- 1 | from PyQt5.QtCore import QDir, Qt, QUrl 2 | from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer 3 | from PyQt5.QtMultimediaWidgets import QVideoWidget 4 | from PyQt5.QtWidgets import (QApplication, QFileDialog, QHBoxLayout, QLabel, 5 | QPushButton, QSizePolicy, QSlider, QStyle, QVBoxLayout, QWidget) 6 | 7 | 8 | class VideoPlayer(QWidget): 9 | 10 | def __init__(self, parent=None): 11 | super(VideoPlayer, self).__init__(parent) 12 | 13 | openButton = QPushButton("Buscar...") 14 | openButton.clicked.connect(self.openFile) 15 | 16 | self.playButton = QPushButton() 17 | self.playButton.setEnabled(False) 18 | self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) 19 | self.playButton.clicked.connect(self.play) 20 | 21 | self.positionSlider = QSlider(Qt.Horizontal) 22 | self.positionSlider.setRange(0, 0) 23 | self.positionSlider.sliderMoved.connect(self.setPosition) 24 | 25 | controlLayout = QHBoxLayout() 26 | controlLayout.setContentsMargins(0, 0, 0, 0) 27 | controlLayout.addWidget(openButton) 28 | controlLayout.addWidget(self.playButton) 29 | controlLayout.addWidget(self.positionSlider) 30 | 31 | videoWidget = QVideoWidget() 32 | 33 | layout = QVBoxLayout() 34 | layout.addWidget(videoWidget) 35 | layout.addLayout(controlLayout) 36 | 37 | self.setLayout(layout) 38 | 39 | self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) 40 | self.mediaPlayer.setVideoOutput(videoWidget) 41 | self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) 42 | self.mediaPlayer.positionChanged.connect(self.positionChanged) 43 | self.mediaPlayer.durationChanged.connect(self.durationChanged) 44 | 45 | def openFile(self): 46 | fileName, _ = QFileDialog.getOpenFileName(self, "Archivo de video", QDir.homePath()) 47 | 48 | if fileName != '': 49 | self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(fileName))) 50 | self.playButton.setEnabled(True) 51 | 52 | def play(self): 53 | if self.mediaPlayer.state() == QMediaPlayer.PlayingState: 54 | self.mediaPlayer.pause() 55 | else: 56 | self.mediaPlayer.play() 57 | 58 | def mediaStateChanged(self, state): 59 | if self.mediaPlayer.state() == QMediaPlayer.PlayingState: 60 | self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPause)) 61 | else: 62 | self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) 63 | 64 | def positionChanged(self, position): 65 | self.positionSlider.setValue(position) 66 | 67 | def durationChanged(self, duration): 68 | self.positionSlider.setRange(0, duration) 69 | 70 | def setPosition(self, position): 71 | self.mediaPlayer.setPosition(position) 72 | 73 | if __name__ == '__main__': 74 | 75 | import sys 76 | 77 | app = QApplication(sys.argv) 78 | 79 | player = VideoPlayer() 80 | player.setWindowTitle('PyQT5 Reproducir Video AVI') 81 | player.resize(800, 600) 82 | player.show() 83 | 84 | sys.exit(app.exec_()) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tutorial GUI PyQT-5 2 | Esta serie de tutoriales contiene la información necesaria para introducirse en el desarrollo de Interfaces Gráficas de Usuario con la biblioteca PyQT 5 y el lenguaje de programación Python 3.x. 3 | 4 | Más información en: [Tutoriales PyQT-5 Python 3.x](http://acodigo.blogspot.com/p/python.html) --------------------------------------------------------------------------------