3ENGINE

Programación y otros cachivaches

Archivo

Página 8/104

Tecnologia

Cómo incrustar imágenes en una aplicación Qt en Python


En este post voy a explicar mediante una pequeña demo cómo incrustar imágenes dentro de una aplicación. El principal objetivo de esto es no tener que distribuir las imágenes junto con la aplicación. Pero antes, un poco de teoria:

El Sistema de Recursos de Qt

Se trata de un sistema independiente de la plataforma que permite almacenar archivos binarios en el ejecutable de la aplicación. Esto es útil si la aplicación necesita de un cierto conjunto de archivos (iconos, archivos de traducción, etc.) y no queremos correr el riesgo de perder los archivos.

Recursos Archivos Colección (.qrc)

Los recursos asociados con la aplicación se especifican en un archivo .qrc. Es un formato de archivo basado en XML que enumera los archivos y opcionalmente un nombre de recurso que la aplicación debe utilizar para acceder al recurso. Los archivos de recursos que figuran en el archivo .qrc son archivos que forman parte del árbol de código fuente de la aplicación. Las rutas especificadas son relativas al directorio que contiene el archivo .qrc.

Utilidad pyrcc4

pyrcc4 es equivalente a la utilidad rcc de Qt y se utiliza exactamente de la misma manera. Lee el archivo .qrc, y los archivos de recursos, y genera un módulo de Python que sólo necesita ser importado por la aplicación para que los recursos estén disponibles como si se tratara de los archivos originales.

Para mas información leer The Qt Resource System

Ejemplo

Paso 1: generar el fichero .qrc




    img/icon_ok.png
    img/icon_cancel.png


    img/image_qt.png


Por defecto, los recursos son accesibles en la aplicación bajo el mismo nombre de archivo. Opcionalmente el atributo alias permite cambiar el nombre. Al especificar un prefijo de ruta mediante la etiqueta qresource y el atributo prefix se han agrupado las imágenes en dos grupos. En este caso, las imagenes son accesibles con: :icons/ok.png , :icons/cancel.png y :img/image_qt.png respectivamente.

Paso 2: generar el módulo Python con los recursos

pyrcc4 -o images_rc.py images.qrc

Le indicamos a la herramienta que genere a partir de images.qrc un módulo Python images_rc.py con los recursos.

Paso 3: código fuente

# -*- coding: utf-8 -*-
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import images_rc
import sys


class MainWindow(QMainWindow):

    def accept(self):
        QMessageBox.information(self, 'Thanks!', 'Thanks for testing the demo', QMessageBox.AcceptRole)
        self.close()
        
    def __init__(self, *args):
        QMainWindow.__init__(self, *args)
       
        # añadir imagen 
        title = QLabel() 
        pixmap = QPixmap(':images/title.png')
        title.setPixmap(pixmap)

        # añadir texto              
        info = QLabel('visit my blog at:3engine.net') 

        # crear botones 
        acceptButton = QPushButton('Accept', self)
        acceptButton.setIcon(QIcon(':icons/ok.png'))

        cancelButton = QPushButton('Cancel', self)
        cancelButton.setIcon(QIcon(':icons/cancel.png'))

        # añadir botones al diálogo
        buttonBox = QDialogButtonBox()
        buttonBox.addButton(acceptButton, QDialogButtonBox.AcceptRole)
        buttonBox.addButton(cancelButton, QDialogButtonBox.RejectRole)
        buttonBox.accepted.connect(lambda: self.accept())
        buttonBox.rejected.connect(lambda: self.close())

        # crear layout principal           
        vbox = QVBoxLayout()
        vbox.addWidget(title)
        vbox.addSpacing(10)
        vbox.addWidget(info)
        vbox.addSpacing(10)
        vbox.addStretch()
        vbox.addWidget(buttonBox)

        centralWidget = QWidget()
        centralWidget.setLayout(vbox)
        self.setCentralWidget(centralWidget)
        self.resize(100, 100)
        self.setWindowTitle('demo')       


if __name__ == "__main__":
    app = QApplication(sys.argv)
    main = MainWindow()
    main.show()    
    sys.exit(app.exec_())

En el código vemos el uso de los recursos incrustados en los widgets de tipo QPixmap y QIcon

El resultado es el siguiente

cap_qt

Enlace a la demo




Tecnologia

pyqt: cómo hacer que QLabel sea clicable.


En Qt el widget QLabel no es clicable. Para emular el click del ratón basta añadir una propiedad que use la clase Signal y sobreescribir el evento mouseRelease de QLabel de modo que emita un señal clicked.

class QLabelClickable(QLabel):

    clicked = pyqtSignal()
    
    def __init__(self, *args):
        QLabel.__init__(self, *args)
   
    def mouseReleaseEvent(self, ev):
        self.clicked.emit()

Y este es el código para probarlo:

class MainWindow(QMainWindow):

    def label_clicked(self):
        print "click"
        
    def __init__(self, *args):
        QMainWindow.__init__(self, *args)
        self.mylabel = QLabelClickable('click me!')
        self.mylabel.clicked.connect(self.label_clicked)
        self.setCentralWidget(self.mylabel)

app = QApplication(sys.argv)
main = MainWindow()
main.show()     
sys.exit(app.exec_())

En este otro ejemplo ahora QLabel incorpora una imagen y además hago uso del antiguo sistema para conectar eventos:

class MainWindow(QMainWindow):

    def label_clicked(self):
        print "click"
        
    def __init__(self, *args):
        QMainWindow.__init__(self, *args)
        self.mylabel = QLabelClickable('')
        self.mylabel.setPixmap(QPixmap('myimage.png').scaled(10, 10, Qt.KeepAspectRatio))
        self.connect(self.mylabel, SIGNAL('clicked()'), self.label_clicked)
        self.setCentralWidget(self.mylabel)

app = QApplication(sys.argv)
main = MainWindow()
main.show()     
sys.exit(app.exec_())




Tecnologia

Cómo deshabilitar la tecla enter en una página web


De modo predeterminado el envio de un formulario se puede ejecutar con un botón submit asociado al formulario o pulsando enter.

deshabilitar la tecla enter en una página web

Para desactivar el envio del formulario mediante la tecla enter con javascript + jquery:

$(function () {
    $("form").keypress(function (e) {
        var key;
        if (window.event)
            key = window.event.keyCode; //IE
        else
            key = e.which; //firefox     
        return (key != 13);
    });
});

Este código asigna el evento keypress al formulario. Si queremos el mismo comportamiento para toda la página entonces tenemos que sustituir $(«form») por $(«body») u otro selector jquery que se adapte a tus necesidades.




Tecnologia

Cómo generar archivos Excel en C# con Open XML


Office Open XML es un formato de archivo abierto y estándar cuyas extensiones más comunes son .docx, .xlsx y .pptx. Principalmente contiene datos en XML comprimidos en un .zip. .NET dispone de librerias capaces de trabajar con este formato y de esta manera prescindir de instalar Office y sus temidas Microsoft.Office.Interop.

Generar archivos Excel en C# con Open XML

Para la demo es necesario instalar el paquete DocumentFormat.OpenXml:

generar archivos Excel en C# con Open XML

O desde la consola de Nuget:

Install-Package DocumentFormat.OpenXml 

El código es el siguiente:

 
namespace SaveExcelApp
{
    public static class SaveExcel
    {
        
        public static void BuildExcel(DataTable dataTable, string ExcelPath)        
        {
            using (SpreadsheetDocument myWorkbook = 
                SpreadsheetDocument.Create(ExcelPath, 
                SpreadsheetDocumentType.Workbook))
            {
                // workbook Part
                WorkbookPart workbookPart = myWorkbook.AddWorkbookPart();
                var worksheetPart = workbookPart.AddNewPart();
                string relId = workbookPart.GetIdOfPart(worksheetPart);

                // file Version
                var fileVersion = new FileVersion { ApplicationName = "Microsoft Office Excel" };

                // sheets               
                var sheets = new Sheets();
                var sheet = new Sheet { Name = dataTable.TableName, SheetId = 1, Id = relId };
                sheets.Append(sheet);

                // data
                SheetData sheetData = new SheetData(CreateSheetData(dataTable));

                // add the parts to the workbook and save
                var workbook = new Workbook();
                workbook.Append(fileVersion);
                workbook.Append(sheets);
                var worksheet = new Worksheet();
                worksheet.Append(sheetData);
                worksheetPart.Worksheet = worksheet;
                worksheetPart.Worksheet.Save();
                myWorkbook.WorkbookPart.Workbook = workbook;
                myWorkbook.WorkbookPart.Workbook.Save();
                myWorkbook.Close();
            }
        }

        private static List CreateSheetData(DataTable dataTable)
        {
            List elements = new List();

            // row header
            var rowHeader = new Row();
            Cell[] cellsHeader = new Cell[dataTable.Columns.Count];
            for (int i = 0; i < dataTable.Columns.Count; i++)
            {
                cellsHeader[i] = new Cell();
                cellsHeader[i].DataType = CellValues.String;
                cellsHeader[i].CellValue = new CellValue(dataTable.Columns[i].ColumnName);
            }
            rowHeader.Append(cellsHeader);
            elements.Add(rowHeader); 
            
           // rows data
           foreach (DataRow rowDataTable in dataTable.Rows)
           {     
                var row = new Row();
                Cell[] cells = new Cell[dataTable.Columns.Count];

                for (int i = 0; i < dataTable.Columns.Count; i++)
                {
                    cells[i] = new Cell();
                    cells[i].DataType = CellValues.String;
                    cells[i].CellValue = new CellValue((string)rowDataTable[i]);
                }
                row.Append(cells); 
                elements.Add(row);            
            }                      
            return elements;
        }
    }
}

Para mi demo los datos que deseo guardar en el archivo Excel los tengo en un DataTable. Al método BuildExcel se le pasa el DataTable con los datos y la ruta completa del archivo Excel a generar. El método CreateSheetData se encarga de leer los datos del DataTable y generar las celdas. El nombre de la hoja Excel se obtiene del nombre de la tabla.

Se trata de un código sencillo pero que puede servir como punto de partida.

Y ahora una pequeña demo:

var demoTable = new DataTable("mi demo");
demoTable.Columns.Add("name");
demoTable.Columns.Add("surname");
demoTable.Columns.Add("favorite color");
demoTable.Rows.Add(new Object[] { "David", "Miro", "blue" });
demoTable.Rows.Add(new Object[] { "Pablo", "Iglesias", "yellow" });
demoTable.Rows.Add(new Object[] { "Ratoncito", "Perez", "green" });
SaveExcel.BuildExcel(demoTable, "demo.xlsx");

Y el archivo generado:

generar archivos Excel en C# con Open XML

Enlace a la demo: SaveExcel.zip