No entanto o Python3 trouxe consigo diversas melhorias com relação à sua versão anterior, e a mais notável com certeza é a de uso de strings unicode, agora é possível criar uma variável com o nome "maçã" por exemplo. Em especial, o PyQt4 também sofreu muitas mudanças, na realidade ele ficou mais simples, uma porcão de objetos que antes existiam no PyQt4 para python2.x não existem mais para o PyQt4 para python3, o que causa problemas ao tentar executar programas em PyQt4 escritos para rodarem no Python2.x, existem algumas "gambiarras" como essa abaixo, no entanto esse método possui algumas falhas graves em relação a uma outra opção que eu coloquei no final do post que é o uso da biblioteca sip do python3, nesse exemplo a QString irá funcionar, no entanto os métodos dela estarão ausente causando dores de cabeça, em seguida eu coloquei um exemplo de uma calculadora simples em PyQt feita por uma amiga que está estudando a linguagem e eu resolvi alterar algumas coisas para colocar como exemplo aqui, é um bom começo para estudo, o código principal pode ser salvo com o nome calculadora.py e o da classe de interface obrigatoriamente tem que ser ui_calculadora.py porque ele é importado para a classe principal.
try: from PyQt4.QtCore import QString except ImportError: # we are using Python3 so QString is not defined QString = type("")
Eis o Exemplo em Python 2.x
#!/usr/bin/python # -*- coding: utf-8 -*- #importação dos módulos das bibliotecas Qt from PyQt4.QtCore import * from PyQt4.QtGui import * from PyQt4 import QtCore import ui_calculadora #Importação dos módulos personalizados class Calculadora(QMainWindow, ui_calculadora.Ui_Calculadora): ''' Classe Principal que cria uma agenda eletrônica Simples :D ''' # método init construtor da classe... def __init__(self, parent=None): #os dois comandos abaixo inicializa a classe com as duas das quais ela herdou métodos e atributos #QMainWindow que é uma classe base do Qt framework e ui_calculadora que é a interface criada super(Calculadora, self).__init__(parent) self.setupUi(self) self.edicao = True self.memoria = 0 #conectando os objetos da interface com as funções self.connect(self.btnMemoriaNegativa, SIGNAL("clicked()"), self.memoriaNegativa) self.connect(self.btnMemoriaPositiva, SIGNAL("clicked()"), self.memoriaPositiva) self.connect(self.btnLimparMemoria, SIGNAL("clicked()"), self.limparMemoria) self.connect(self.btnNumeros, SIGNAL("buttonClicked(QAbstractButton*)"), self.botaoClickado) self.connect(self.btnIgual, SIGNAL("clicked()"), self.resultado) def limparMemoria(self): self.memoria = 0 self.lblMensagem.setText("0") self.edicao = False def memoriaNegativa(self): self.memoria -= float(str(self.txtCalculo.text())) self.lblMensagem.setText(str(self.memoria)) self.edicao = False def memoriaPositiva(self): self.memoria += float(str(self.txtCalculo.text())) self.lblMensagem.setText(str(self.memoria)) self.edicao = False def botaoClickado(self, botao): if self.edicao: self.txtCalculo.insert(botao.text().toUpper()) else: self.txtCalculo.setText(botao.text().toUpper()) self.edicao = True def resultado(self): try: resultado = eval(str(self.txtCalculo.text() + ".")) self.txtCalculo.setText(str(resultado)) self.edicao = False except: # o caractere u antes da string indica que a mesma é unicode... QMessageBox.information(self, u"Expressão incorreta", u"Você digitou uma expressão incorreta", buttons=QMessageBox.Ok) self.txtCalculo.clear() #Função que inicializa o aplicativo if __name__ == "__main__": import sys app = QApplication(sys.argv) formulario = Calculadora() formulario.show() app.exec_()
Agora a Versão em Python3
#!/usr/bin/python # -*- coding: utf-8 -*- #importação dos módulos das bibliotecas Qt from PyQt4.QtCore import * from PyQt4.QtGui import * from PyQt4 import QtCore import ui_calculadora #Importação dos módulos personalizados class Calculadora(QMainWindow, ui_calculadora.Ui_Calculadora): ''' Classe Principal que cria uma agenda eletrônica Simples :D ''' # método init construtor da classe... def __init__(self, parent=None): #os dois comandos abaixo inicializa a classe com as duas das quais ela herdou métodos e atributos #QMainWindow que é uma classe base do Qt framework e ui_calculadora que é a interface criada super(Calculadora, self).__init__(parent) self.setupUi(self) self.edicao = True self.memoria = 0 #conectando os objetos da interface com as funções self.connect(self.btnMemoriaNegativa, SIGNAL("clicked()"), self.memoriaNegativa) self.connect(self.btnMemoriaPositiva, SIGNAL("clicked()"), self.memoriaPositiva) self.connect(self.btnLimparMemoria, SIGNAL("clicked()"), self.limparMemoria) self.connect(self.btnNumeros, SIGNAL("buttonClicked(QAbstractButton*)"), self.botaoClickado) self.connect(self.btnIgual, SIGNAL("clicked()"), self.resultado) def limparMemoria(self): self.memoria = 0 self.lblMensagem.setText("0") self.edicao = False def memoriaNegativa(self): self.memoria -= float(str(self.txtCalculo.text())) self.lblMensagem.setText(str(self.memoria)) self.edicao = False def memoriaPositiva(self): self.memoria += float(str(self.txtCalculo.text())) self.lblMensagem.setText(str(self.memoria)) self.edicao = False def botaoClickado(self, botao): if self.edicao: self.txtCalculo.insert(botao.text()) else: self.txtCalculo.setText(botao.text()) self.edicao = True def resultado(self): try: resultado = eval(str(self.txtCalculo.text() + ".")) self.txtCalculo.setText(str(resultado)) self.edicao = False except: # o caractere u antes da string indica que a mesma é unicode... QMessageBox.information(self, "Expressão incorreta", "Você digitou uma expressão incorreta", buttons=QMessageBox.Ok) self.txtCalculo.clear() #Função que inicializa o aplicativo if __name__ == "__main__": import sys app = QApplication(sys.argv) formulario = Calculadora() formulario.show() app.exec_()
Agora o arquivo de interface(ui_calculadora.py) ele funciona normal em python2 ou 3, lembrando que ele foi feito usando o pyuic4 através de um arquivo ui do QtDesigner.
# -*- coding: utf-8 -*- # Form implementation generated from reading ui file 'calculadora.ui' # # Created: Tue Nov 30 20:07:38 2010 # by: PyQt4 UI code generator 4.8.1 # # WARNING! All changes made in this file will be lost! from PyQt4 import QtCore, QtGui try: _fromUtf8 = QtCore.QString.fromUtf8 except AttributeError: _fromUtf8 = lambda s: s class Ui_Calculadora(object): def setupUi(self, Calculadora): Calculadora.setObjectName(_fromUtf8("Calculadora")) Calculadora.resize(419, 344) Calculadora.setMinimumSize(QtCore.QSize(419, 290)) self.centralwidget = QtGui.QWidget(Calculadora) self.centralwidget.setObjectName(_fromUtf8("centralwidget")) self.gridLayout_3 = QtGui.QGridLayout(self.centralwidget) self.gridLayout_3.setObjectName(_fromUtf8("gridLayout_3")) self.txtCalculo = QtGui.QLineEdit(self.centralwidget) self.txtCalculo.setMinimumSize(QtCore.QSize(401, 41)) self.txtCalculo.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) self.txtCalculo.setObjectName(_fromUtf8("txtCalculo")) self.gridLayout_3.addWidget(self.txtCalculo, 0, 0, 1, 2) self.btnLimpar = QtGui.QPushButton(self.centralwidget) self.btnLimpar.setMinimumSize(QtCore.QSize(61, 41)) self.btnLimpar.setMaximumSize(QtCore.QSize(120, 16777215)) self.btnLimpar.setObjectName(_fromUtf8("btnLimpar")) self.gridLayout_3.addWidget(self.btnLimpar, 2, 0, 1, 1) self.gridLayout = QtGui.QGridLayout() self.gridLayout.setObjectName(_fromUtf8("gridLayout")) self.btn7 = QtGui.QPushButton(self.centralwidget) self.btn7.setMinimumSize(QtCore.QSize(61, 41)) self.btn7.setObjectName(_fromUtf8("btn7")) self.btnNumeros = QtGui.QButtonGroup(Calculadora) self.btnNumeros.setObjectName(_fromUtf8("btnNumeros")) self.btnNumeros.addButton(self.btn7) self.gridLayout.addWidget(self.btn7, 0, 0, 1, 1) self.btn8 = QtGui.QPushButton(self.centralwidget) self.btn8.setMinimumSize(QtCore.QSize(61, 41)) self.btn8.setObjectName(_fromUtf8("btn8")) self.btnNumeros.addButton(self.btn8) self.gridLayout.addWidget(self.btn8, 0, 1, 1, 1) self.btn9 = QtGui.QPushButton(self.centralwidget) self.btn9.setMinimumSize(QtCore.QSize(61, 41)) self.btn9.setObjectName(_fromUtf8("btn9")) self.btnNumeros.addButton(self.btn9) self.gridLayout.addWidget(self.btn9, 0, 2, 1, 1) self.btn4 = QtGui.QPushButton(self.centralwidget) self.btn4.setMinimumSize(QtCore.QSize(61, 41)) self.btn4.setObjectName(_fromUtf8("btn4")) self.btnNumeros.addButton(self.btn4) self.gridLayout.addWidget(self.btn4, 1, 0, 1, 1) self.btn5 = QtGui.QPushButton(self.centralwidget) self.btn5.setMinimumSize(QtCore.QSize(61, 41)) self.btn5.setObjectName(_fromUtf8("btn5")) self.btnNumeros.addButton(self.btn5) self.gridLayout.addWidget(self.btn5, 1, 1, 1, 1) self.btn6 = QtGui.QPushButton(self.centralwidget) self.btn6.setMinimumSize(QtCore.QSize(61, 41)) self.btn6.setObjectName(_fromUtf8("btn6")) self.btnNumeros.addButton(self.btn6) self.gridLayout.addWidget(self.btn6, 1, 2, 1, 1) self.btn1 = QtGui.QPushButton(self.centralwidget) self.btn1.setMinimumSize(QtCore.QSize(61, 41)) self.btn1.setObjectName(_fromUtf8("btn1")) self.btnNumeros.addButton(self.btn1) self.gridLayout.addWidget(self.btn1, 2, 0, 1, 1) self.btn2 = QtGui.QPushButton(self.centralwidget) self.btn2.setMinimumSize(QtCore.QSize(61, 41)) self.btn2.setObjectName(_fromUtf8("btn2")) self.btnNumeros.addButton(self.btn2) self.gridLayout.addWidget(self.btn2, 2, 1, 1, 1) self.btn3 = QtGui.QPushButton(self.centralwidget) self.btn3.setMinimumSize(QtCore.QSize(61, 41)) self.btn3.setObjectName(_fromUtf8("btn3")) self.btnNumeros.addButton(self.btn3) self.gridLayout.addWidget(self.btn3, 2, 2, 1, 1) self.btnNegativo = QtGui.QPushButton(self.centralwidget) self.btnNegativo.setMinimumSize(QtCore.QSize(61, 41)) self.btnNegativo.setObjectName(_fromUtf8("btnNegativo")) self.gridLayout.addWidget(self.btnNegativo, 3, 0, 1, 1) self.btn0 = QtGui.QPushButton(self.centralwidget) self.btn0.setMinimumSize(QtCore.QSize(61, 41)) self.btn0.setObjectName(_fromUtf8("btn0")) self.btnNumeros.addButton(self.btn0) self.gridLayout.addWidget(self.btn0, 3, 1, 1, 1) self.btnPonto = QtGui.QPushButton(self.centralwidget) self.btnPonto.setMinimumSize(QtCore.QSize(61, 41)) self.btnPonto.setObjectName(_fromUtf8("btnPonto")) self.btnNumeros.addButton(self.btnPonto) self.gridLayout.addWidget(self.btnPonto, 3, 2, 1, 1) self.gridLayout_3.addLayout(self.gridLayout, 3, 0, 1, 1) self.gridLayout_2 = QtGui.QGridLayout() self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2")) self.btnDiv = QtGui.QPushButton(self.centralwidget) self.btnDiv.setMinimumSize(QtCore.QSize(61, 41)) self.btnDiv.setObjectName(_fromUtf8("btnDiv")) self.btnNumeros.addButton(self.btnDiv) self.gridLayout_2.addWidget(self.btnDiv, 0, 0, 1, 1) self.btnMult = QtGui.QPushButton(self.centralwidget) self.btnMult.setMinimumSize(QtCore.QSize(61, 41)) self.btnMult.setObjectName(_fromUtf8("btnMult")) self.btnNumeros.addButton(self.btnMult) self.gridLayout_2.addWidget(self.btnMult, 1, 0, 1, 1) self.btnMenos = QtGui.QPushButton(self.centralwidget) self.btnMenos.setMinimumSize(QtCore.QSize(61, 41)) self.btnMenos.setObjectName(_fromUtf8("btnMenos")) self.btnNumeros.addButton(self.btnMenos) self.gridLayout_2.addWidget(self.btnMenos, 2, 0, 1, 1) self.btnMais = QtGui.QPushButton(self.centralwidget) self.btnMais.setMinimumSize(QtCore.QSize(61, 41)) self.btnMais.setObjectName(_fromUtf8("btnMais")) self.btnNumeros.addButton(self.btnMais) self.gridLayout_2.addWidget(self.btnMais, 3, 0, 1, 1) self.btnIgual = QtGui.QPushButton(self.centralwidget) self.btnIgual.setMinimumSize(QtCore.QSize(61, 41)) self.btnIgual.setObjectName(_fromUtf8("btnIgual")) self.gridLayout_2.addWidget(self.btnIgual, 3, 2, 1, 1) self.btnMemoriaNegativa = QtGui.QPushButton(self.centralwidget) self.btnMemoriaNegativa.setMinimumSize(QtCore.QSize(61, 41)) self.btnMemoriaNegativa.setObjectName(_fromUtf8("btnMemoriaNegativa")) self.gridLayout_2.addWidget(self.btnMemoriaNegativa, 2, 2, 1, 1) self.btnMemoriaPositiva = QtGui.QPushButton(self.centralwidget) self.btnMemoriaPositiva.setMinimumSize(QtCore.QSize(61, 41)) self.btnMemoriaPositiva.setObjectName(_fromUtf8("btnMemoriaPositiva")) self.gridLayout_2.addWidget(self.btnMemoriaPositiva, 1, 2, 1, 1) self.btnLimparMemoria = QtGui.QPushButton(self.centralwidget) self.btnLimparMemoria.setMinimumSize(QtCore.QSize(61, 41)) self.btnLimparMemoria.setObjectName(_fromUtf8("btnLimparMemoria")) self.gridLayout_2.addWidget(self.btnLimparMemoria, 0, 2, 1, 1) self.gridLayout_3.addLayout(self.gridLayout_2, 3, 1, 1, 1) self.lblMensagem = QtGui.QLabel(self.centralwidget) self.lblMensagem.setText(_fromUtf8("")) self.lblMensagem.setObjectName(_fromUtf8("lblMensagem")) self.gridLayout_3.addWidget(self.lblMensagem, 2, 1, 1, 1) Calculadora.setCentralWidget(self.centralwidget) self.menubar = QtGui.QMenuBar(Calculadora) self.menubar.setGeometry(QtCore.QRect(0, 0, 419, 25)) self.menubar.setObjectName(_fromUtf8("menubar")) self.menu_Arquivo = QtGui.QMenu(self.menubar) self.menu_Arquivo.setObjectName(_fromUtf8("menu_Arquivo")) Calculadora.setMenuBar(self.menubar) self.statusbar = QtGui.QStatusBar(Calculadora) self.statusbar.setObjectName(_fromUtf8("statusbar")) Calculadora.setStatusBar(self.statusbar) self.actionSair = QtGui.QAction(Calculadora) self.actionSair.setObjectName(_fromUtf8("actionSair")) self.menu_Arquivo.addAction(self.actionSair) self.menubar.addAction(self.menu_Arquivo.menuAction()) self.retranslateUi(Calculadora) QtCore.QObject.connect(self.btnLimpar, QtCore.SIGNAL(_fromUtf8("clicked()")), self.txtCalculo.clear) QtCore.QMetaObject.connectSlotsByName(Calculadora) def retranslateUi(self, Calculadora): Calculadora.setWindowTitle(QtGui.QApplication.translate("Calculadora", "Calculadora Simples", None, QtGui.QApplication.UnicodeUTF8)) self.btnLimpar.setText(QtGui.QApplication.translate("Calculadora", "&C", None, QtGui.QApplication.UnicodeUTF8)) self.btn7.setText(QtGui.QApplication.translate("Calculadora", "7", None, QtGui.QApplication.UnicodeUTF8)) self.btn8.setText(QtGui.QApplication.translate("Calculadora", "8", None, QtGui.QApplication.UnicodeUTF8)) self.btn9.setText(QtGui.QApplication.translate("Calculadora", "9", None, QtGui.QApplication.UnicodeUTF8)) self.btn4.setText(QtGui.QApplication.translate("Calculadora", "4", None, QtGui.QApplication.UnicodeUTF8)) self.btn5.setText(QtGui.QApplication.translate("Calculadora", "5", None, QtGui.QApplication.UnicodeUTF8)) self.btn6.setText(QtGui.QApplication.translate("Calculadora", "6", None, QtGui.QApplication.UnicodeUTF8)) self.btn1.setText(QtGui.QApplication.translate("Calculadora", "1", None, QtGui.QApplication.UnicodeUTF8)) self.btn2.setText(QtGui.QApplication.translate("Calculadora", "2", None, QtGui.QApplication.UnicodeUTF8)) self.btn3.setText(QtGui.QApplication.translate("Calculadora", "3", None, QtGui.QApplication.UnicodeUTF8)) self.btnNegativo.setText(QtGui.QApplication.translate("Calculadora", "+/-", None, QtGui.QApplication.UnicodeUTF8)) self.btn0.setText(QtGui.QApplication.translate("Calculadora", "0", None, QtGui.QApplication.UnicodeUTF8)) self.btnPonto.setText(QtGui.QApplication.translate("Calculadora", ".", None, QtGui.QApplication.UnicodeUTF8)) self.btnDiv.setText(QtGui.QApplication.translate("Calculadora", "/", None, QtGui.QApplication.UnicodeUTF8)) self.btnMult.setText(QtGui.QApplication.translate("Calculadora", "*", None, QtGui.QApplication.UnicodeUTF8)) self.btnMenos.setText(QtGui.QApplication.translate("Calculadora", "-", None, QtGui.QApplication.UnicodeUTF8)) self.btnMais.setText(QtGui.QApplication.translate("Calculadora", "+", None, QtGui.QApplication.UnicodeUTF8)) self.btnIgual.setText(QtGui.QApplication.translate("Calculadora", "=", None, QtGui.QApplication.UnicodeUTF8)) self.btnMemoriaNegativa.setText(QtGui.QApplication.translate("Calculadora", "M-", None, QtGui.QApplication.UnicodeUTF8)) self.btnMemoriaPositiva.setText(QtGui.QApplication.translate("Calculadora", "M+", None, QtGui.QApplication.UnicodeUTF8)) self.btnLimparMemoria.setText(QtGui.QApplication.translate("Calculadora", "MC", None, QtGui.QApplication.UnicodeUTF8)) self.menu_Arquivo.setTitle(QtGui.QApplication.translate("Calculadora", "&Arquivo", None, QtGui.QApplication.UnicodeUTF8)) self.actionSair.setText(QtGui.QApplication.translate("Calculadora", "Sair", None, QtGui.QApplication.UnicodeUTF8)) if __name__ == "__main__": import sys app = QtGui.QApplication(sys.argv) Calculadora = QtGui.QMainWindow() ui = Ui_Calculadora() ui.setupUi(Calculadora) Calculadora.show() sys.exit(app.exec_())As diferenças são poucas porque o programa é pequeno, porém em programas maiores onde adicionamos objetos como:
QStringList e QString constantemente temos muitos problemas porque no PyQt para python3 os métodos ficarão diferentes por exemplo, o método QString para Strings maiúsculas é .toUpper() e para strings regulares do python é simplesmente .upper().
Dessa forma usando simplesmente a gambiarra que eu citei acima não irá funcionar porque quando invocarmos os métodos do QString eles não estarão presentes, felizmente existe no Python3 uma biblioteca que resolve isso pra nós, a sip, exemplo:
import sip
sip.setapi('QString', 1)
from PyQt4 import QtCore
Esse método funciona bem, no entanto quando temos funções que retornam QString's ou QStringList's do PyQt em Python2.x agora retornam objetos regulares do python e nem esse método e nem o anterior funcionam adequadamente, portanto é preciso realmente reescrever o código...