Ir al contenido principal

Ralsina.Me — El sitio web de Roberto Alsina

Publicaciones sobre python (publicaciones antiguas, página 64)

Por esto es que Qt y PyQt valen la pena

¿Por qué es­tán bue­nos Qt y Py­Q­t?

Wi­dget re­pro­duc­tor de au­dio:

# -*- coding: utf-8 -*-

import sys, os
from PyQt4 import QtCore, QtGui, uic
from PyQt4.phonon import Phonon
import icons_rc

class AudioPlayer(QtGui.QWidget):
    def __init__(self, url, parent = None):

        self.url = url

        QtGui.QWidget.__init__(self, parent)
        self.setSizePolicy(QtGui.QSizePolicy.Expanding,
            QtGui.QSizePolicy.Preferred)


        self.player = Phonon.createPlayer(Phonon.MusicCategory,
            Phonon.MediaSource(url))
        self.player.setTickInterval(100)
        self.player.tick.connect(self.tock)

        self.play_pause = QtGui.QPushButton(self)
        self.play_pause.setIcon(QtGui.QIcon(':/icons/player_play.svg'))
        self.play_pause.clicked.connect(self.playClicked)
        self.player.stateChanged.connect(self.stateChanged)

        self.slider = Phonon.SeekSlider(self.player , self)

        self.status = QtGui.QLabel(self)
        self.status.setAlignment(QtCore.Qt.AlignRight |
            QtCore.Qt.AlignVCenter)

        self.download = QtGui.QPushButton("Download", self)
        self.download.clicked.connect(self.fetch)

        layout = QtGui.QHBoxLayout(self)
        layout.addWidget(self.play_pause)
        layout.addWidget(self.slider)
        layout.addWidget(self.status)
        layout.addWidget(self.download)

    def playClicked(self):
        if self.player.state() == Phonon.PlayingState:
            self.player.pause()
        else:
            self.player.play()

    def stateChanged(self, new, old):
        if new == Phonon.PlayingState:
            self.play_pause.setIcon(QtGui.QIcon(':/icons/player_pause.svg'))
        else:
            self.play_pause.setIcon(QtGui.QIcon(':/icons/player_play.svg'))

    def tock(self, time):
        time = time/1000
        h = time/3600
        m = (time-3600*h) / 60
        s = (time-3600*h-m*60)
        self.status.setText('%02d:%02d:%02d'%(h,m,s))

    def fetch(self):
        print 'Should download %s'%self.url

def main():
    app = QtGui.QApplication(sys.argv)
    window=AudioPlayer(sys.argv[1])
    window.show()
    # It's exec_ because exec is a reserved word in Python
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()

Wi­dget re­pro­duc­tor de vi­deo:

import sys, os
from PyQt4 import QtCore, QtGui, uic
from PyQt4.phonon import Phonon
import icons_rc

class VideoPlayer(QtGui.QWidget):
    def __init__(self, url, parent = None):

        self.url = url

        QtGui.QWidget.__init__(self, parent)
        self.setSizePolicy(QtGui.QSizePolicy.Expanding,
            QtGui.QSizePolicy.Preferred)


        self.player = Phonon.VideoPlayer(Phonon.VideoCategory,self)
        self.player.load(Phonon.MediaSource(self.url))
        self.player.mediaObject().setTickInterval(100)
        self.player.mediaObject().tick.connect(self.tock)

        self.play_pause = QtGui.QPushButton(self)
        self.play_pause.setIcon(QtGui.QIcon(':/icons/player_play.svg'))
        self.play_pause.clicked.connect(self.playClicked)
        self.player.mediaObject().stateChanged.connect(self.stateChanged)

        self.slider = Phonon.SeekSlider(self.player.mediaObject() , self)

        self.status = QtGui.QLabel(self)
        self.status.setAlignment(QtCore.Qt.AlignRight |
            QtCore.Qt.AlignVCenter)

        self.download = QtGui.QPushButton("Download", self)
        self.download.clicked.connect(self.fetch)
        topLayout = QtGui.QVBoxLayout(self)
        topLayout.addWidget(self.player)
        layout = QtGui.QHBoxLayout(self)
        layout.addWidget(self.play_pause)
        layout.addWidget(self.slider)
        layout.addWidget(self.status)
        layout.addWidget(self.download)
        topLayout.addLayout(layout)
        self.setLayout(topLayout)

    def playClicked(self):
        if self.player.mediaObject().state() == Phonon.PlayingState:
            self.player.pause()
        else:
            self.player.play()

    def stateChanged(self, new, old):
        if new == Phonon.PlayingState:
            self.play_pause.setIcon(QtGui.QIcon(':/icons/player_pause.svg'))
        else:
            self.play_pause.setIcon(QtGui.QIcon(':/icons/player_play.svg'))

    def tock(self, time):
        time = time/1000
        h = time/3600
        m = (time-3600*h) / 60
        s = (time-3600*h-m*60)
        self.status.setText('%02d:%02d:%02d'%(h,m,s))

    def fetch(self):
        print 'Should download %s'%self.url

def main():
    app = QtGui.QApplication(sys.argv)
    window=VideoPlayer(sys.argv[1])
    window.show()
    # It's exec_ because exec is a reserved word in Python
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()

...

Aplicaciones de escritorio y nubes (con video)

Lo ma­lo es, por su­pues­to, que a ve­ces es mu­cho más con­ve­nien­te usar una apli­ca­ción we­b. Por ejem­plo, he aban­do­na­do a mi pro­pio be­bé (uR­S­Sus) por­que google rea­der es más fá­cil y con­ve­nien­te.

Pe­ro en­ton­ces pen­sé... ¿qué me mo­les­ta de uR­S­Sus? ¡Y son bas­tan­tes co­sas!

  1. No es­­tá en to­­­das las co­m­­pu­­ta­­do­­­ras que uso. Eso quie­­re de­­cir que ja­­más po­­­dré usar­­la de fo­r­­ma ex­­clu­­si­­va.

  2. Es ba­s­­tan­­te inú­­til sin una co­­­ne­­xión a In­­te­r­­net (pe­­ro ta­m­­bién lo es google rea­­de­­r).

  3. Co­­­mo no la pue­­do usar ex­­clu­­si­­va­­men­­te, te­r­­mino con fee­­ds en uR­S­­Sus que no es­­tán en google rea­­der y vi­­ce­­ve­r­­s­a.

  4. Es len­­tí­­si­­ma.

En­ton­ces de­ci­dí ver que pue­do ha­cer al res­pec­to sin aban­do­nar el la­do bue­no de uR­S­Sus:

  1. Me gus­­ta más que una apli­­ca­­ción we­­b, po­r­­que es de es­­cri­­to­­­rio.

  2. Ha­­ce co­­sas co­­­mo abrir el si­­tio en vez de mo­s­­trar el post del feed (bue­­no pa­­ra fee­­ds de co­n­­te­­ni­­do pa­r­­cia­­l)

  3. La hi­­ce yo (sí, eso es un fea­­tu­­re pa­­ra mí. Me gus­­ta te­­ner pro­­­gra­­mas que yo hi­­ce)

En­ton­ce­s, es­te in­ten­to de rees­cri­bir el lec­tor RSS de es­cri­to­rio pro­du­jo es­to:

Co­mo se pue­de ver en el vi­deo, es­te lec­tor sin­cro­ni­za la lis­ta de sus­crip­cio­nes con google. Tam­bién even­tual­men­te sin­cro­ni­za­rá pos­ts leí­do­s/no leí­do­s.

Si­gue pu­dien­do abrir si­tios com­ple­tos en vez de pos­ts, tie­ne/­ten­drá un muy buen mo­do offli­ne (pá­gi­nas com­ple­tas cap­tu­ra­das co­mo imá­ge­nes, por ejem­plo­), y... es muy muy rá­pi­do.

Es mu­cho más rá­pi­do que google rea­der en ch­ro­miu­m, y mu­chí­si­mo más rá­pi­do que uR­S­Sus. Eso es por­que es­tá me­jor el có­di­go, así que pro­ba­ble­men­te sig­ni­fi­ca que an­tes te­nía muer­te ce­re­bral y he ex­pe­ri­men­ta­do una le­ve me­jo­ría.

El có­di­go no es ap­to pa­ra pu­bli­ca­ción (por ejem­plo, el sche­ma de la ba­se de da­tos va a cam­bia­r) pe­ro se pue­de pro­ba­r: http://­co­de.­google.­co­m/­p/kakawa­na/­sour­ce/­che­ckout

Capturing a webpage as an image using Pyhon and Qt

En­ton­ces googleé y me en­contré con Cu­ty­Capt que usa Qt y We­bKit pa­ra con­ver­tir pá­gi­nas web en imá­ge­nes. ¡Me sir­ve!

Co­mo quie­ro usar­lo des­de una apli­ca­ción Py­Q­t, tie­ne sen­ti­do ha­cer lo mis­mo que Cu­ty­Capt ha­ce, pe­ro des­de un mó­du­lo py­thon así que acá es­tá una im­ple­men­ta­ción ra­pi­di­ta que fun­cio­na pa­ra mí, un­que ca­re­ce de mu­chos fea­tu­res de Cu­ty­Cap­t.

Con un po­co más de es­fuer­zo, pue­de guar­dar co­mo PDF o SV­G, lo que per­mi­ti­ría usar­la ca­si co­mo una pá­gi­na web de ver­da­d.

Se usa así:

python  capty.py http://www.kde.org kde.png

Y acá es­tá el có­di­go [des­car­gar cap­ty.­py]

# -*- coding: utf-8 -*-

"""This tries to do more or less the same thing as CutyCapt, but as a
python module.

This is a derived work from CutyCapt: http://cutycapt.sourceforge.net/

////////////////////////////////////////////////////////////////////
//
// CutyCapt - A Qt WebKit Web Page Rendering Capture Utility
//
// Copyright (C) 2003-2010 Bjoern Hoehrmann <bjoern@hoehrmann.de>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// $Id$
//
////////////////////////////////////////////////////////////////////

"""

import sys
from PyQt4 import QtCore, QtGui, QtWebKit


class Capturer(object):
    """A class to capture webpages as images"""

    def __init__(self, url, filename):
        self.url = url
        self.filename = filename
        self.saw_initial_layout = False
        self.saw_document_complete = False

    def loadFinishedSlot(self):
        self.saw_document_complete = True
        if self.saw_initial_layout and self.saw_document_complete:
            self.doCapture()

    def initialLayoutSlot(self):
        self.saw_initial_layout = True
        if self.saw_initial_layout and self.saw_document_complete:
            self.doCapture()

    def capture(self):
        """Captures url as an image to the file specified"""
        self.wb = QtWebKit.QWebPage()
        self.wb.mainFrame().setScrollBarPolicy(
            QtCore.Qt.Horizontal, QtCore.Qt.ScrollBarAlwaysOff)
        self.wb.mainFrame().setScrollBarPolicy(
            QtCore.Qt.Vertical, QtCore.Qt.ScrollBarAlwaysOff)

        self.wb.loadFinished.connect(self.loadFinishedSlot)
        self.wb.mainFrame().initialLayoutCompleted.connect(
            self.initialLayoutSlot)

        self.wb.mainFrame().load(QtCore.QUrl(self.url))

    def doCapture(self):
        self.wb.setViewportSize(self.wb.mainFrame().contentsSize())
        img = QtGui.QImage(self.wb.viewportSize(), QtGui.QImage.Format_ARGB32)
        painter = QtGui.QPainter(img)
        self.wb.mainFrame().render(painter)
        painter.end()
        img.save(self.filename)
        QtCore.QCoreApplication.instance().quit()

if __name__ == "__main__":
    """Run a simple capture"""
    app = QtGui.QApplication(sys.argv)
    c = Capturer(sys.argv[1], sys.argv[2])
    c.capture()
    app.exec_()

Aprendé python! Gratis! Conmigo! (una parte)

Ca­da sá­ba­do po­dés apren­der al­go de al­gu­nos de los me­jo­res pro­gra­ma­do­res Py­thon de la co­mar­ca (o de mí).

Voy a en­se­ñar vir­tua­len­v, buil­dou­t, no­se y otras co­sas el 21/8, co­sas de GUI el 25/9 y 2/10 y Py­Qt el 30/10.

¡To­do es gra­tis, y oja­lá ven­ga mu­cha gen­te!

Cro­no­gra­ma com­ple­to acá.


Contents © 2000-2023 Roberto Alsina