Why this code works:
from PySide.QtCore import *
from PySide.QtGui import *
import sys
from functools import partial
import pyside # my code generated by QT Design
class MainDialog(QMainWindow, pyside.Ui_MainWindow):
def __init__(self, parent=None):
super(MainDialog,self).__init__(parent)
self.setupUi(self)
self.connect(self.Connect_buttom, SIGNAL("clicked()"), partial(self.get_fb_token, "aaaaa","bbbbbb"))
def get_fb_token(self,email,passwd):
print email
print passwd
app = QApplication(sys.argv)
form = MainDialog()
form.show()
app.exec_()
And prints aaaaa and bbbbb
But if I change:
self.connect(self.Connect_buttom, SIGNAL("clicked()"), partial(self.get_fb_token, "aaaaa","bbbbbb"))
to
self.connect(self.Connect_buttom, SIGNAL("clicked()"), partial(self.get_fb_token, self.FB_username.text() ,self.FB_password.text()))
it does not print what I am introducing in the text boxes FB_password and FB_username (it does not crash but it does not print anything like if it is not sending both arguments to the function get_fb_token) ???
** Took the example from: http://www.blog.pythonlibrary.org/2013/04/10/pyside-connecting-multiple-widgets-to-the-same-slot/
Im using QT and pyside
The partial object is created when you define the connection, not when the event is triggered. Which means the FB_username.text() is called when connecting, so it will always print the contents that you have set in the designer.
To achieve what you want you have to use a function that retrieves those values when called.
The simplest solution would be:
from PySide.QtCore import *
from PySide.QtGui import *
import sys
import pyside # my code generated by QT Design
class MainDialog(QMainWindow, pyside.Ui_MainWindow):
def __init__(self, parent=None):
super(MainDialog,self).__init__(parent)
self.setupUi(self)
# use new-style signals & slots!
self.Connect_buttom.clicked.connect(self.get_fb_token)
def get_fb_token(self):
email = self.FB_username.text()
password = self.FB_password.text()
print email
print passwd
app = QApplication(sys.argv)
form = MainDialog()
form.show()
app.exec_()
If, for some reason, you don't want to modify get_fb_token, you can use a lambda like this:
self.Connect_buttom.clicked.connect(lambda: self.get_fb_token(self.FB_username.text(), self.FB_password.text()))
Related
I have two python programs opened at the same time, and i would like that when i click one button in the first app, "send" some information to the second app.
Im trying to do by signals from PySide. I get how to send it with this little code:
from PySide.QtGui import *
from PySide.QtCore import *
from PySide import QtGui, QtCore, QtUiTools
class Foo(object):
pass
class MyWidget(QWidget):
mysignal = QtCore.Signal(int, str)
def __init__(self, parent=None):
super(MyWidget, self).__init__(parent)
self.hlayout = QHBoxLayout()
self.setLayout(self.hlayout)
self.b = QPushButton("Emit your signal!", self)
self.hlayout.addWidget(self.b)
self.b.clicked.connect(self.clickHandler)
self.mysignal.connect(self.mySignalHandler)
def clickHandler(self):
self.mysignal.emit(123, "")
def mySignalHandler(self, n):
print n
# print l
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
w = MyWidget()
w.show()
sys.exit(app.exec_())
but i dont know how can i "recieve" this signal in the other python app.
Thanks for your help!
You need to think about the apps communication ways, it's multi-thread or multi-process?
I try to get the value of Count_total_value in my user interface when I call Continusread method, (it should be "toto" according to what I want to do) but it is always the default value "azerty" which is displayed. Please can you tell me where I am wrong?
This is my code:
#!/usr/bin/env python3
from PyQt4 import QtCore, QtGui
import sys
import os
import subprocess
import time
import threading
from ctypes import *
import ctypes
#import Converted Python UI File
from test_error_rx import Ui_MainWindow
class MyThread(QtCore.QThread):
Count_total_valuechanged = QtCore.pyqtSignal(str)
def __init__(self, parent=None):
super(MyThread, self).__init__(parent=parent)
self.Count_total_value = 'Azerty'
def run(self):
##do things to calculate Count_total_value
Count_total_value='toto'
self.Count_total_valuechanged.emit((self.Count_total_value))
time.sleep(0.1)
class Main( QtGui.QMainWindow,QtGui.QWidget):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
# Connect the Buttons
QtCore.QObject.connect(self.ui.Continusread,QtCore.SIGNAL("clicked()"),self.Continusread)
self.__thread = MyThread(self)
self.__thread.Count_total_valuechanged.connect(self.ui.Count_total.setText)
def Continusread(self):
self.__thread.start()
def main():
app = QtGui.QApplication(sys.argv)
window = Main()
window.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
In the run() method of your thread class MyThread you set Count_total_value='toto' when it should be self.Count_total_value='toto'.
Note that when posting on stackoverflow you should:
post a minimilistic working example (you haven't included your UI in the above code so no-one can run your script)
Check the posted code has the correct indentation and fix any mistakes (your posted code is a mess of incorrect indentation)
I am trying to show the loop data in Lineedit but it is not updating. Even the print command does not print the data on the terminal till I press any key other than return in lineedit. Have a look at the program and suggest me the changes:
import sys
import time
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class MyFrame(QWidget):
def __init__(self):
QWidget.__init__(self)
self.le = QLineEdit(self)
self.le.setGeometry(200,200,75,35)
i=0
self.le.setText(str(i))
self.connect(self.le, SIGNAL("textChanged(QString)"),self.updatedvalue)
def updatedvalue(self):
for i in range(1,5):
self.le.setText(str(i))
print(i)
time.sleep(1)
app=QApplication(sys.argv)
f=MyFrame()
f.show()
app.exec_()
You'll need to call QApplication.instance.processEvents() after updating your QLineEdit's text to force an update, otherwise you won't see anything until the final number.
You also need to change your textChanged() signal to textEdited(). Using textChanged() your updatedvalue() function will be called again on the first pass of your loop once setText() is called because you're updating the QLineEdit's text. The textEdited() signal won't be triggered if you update the text programmatically.
import sys
import time
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class MyFrame(QWidget):
def __init__(self):
QWidget.__init__(self)
self.le = QLineEdit(self)
self.le.setGeometry(200,200,75,35)
i = 0
self.le.setText(str(i))
self.connect(self.le, SIGNAL("textEdited(QString)"),self.updatedvalue)
def updatedvalue(self):
for i in range(1,5):
self.le.setText(str(i))
QApplication.instance().processEvents()
print(i)
time.sleep(1)
app=QApplication(sys.argv)
f=MyFrame()
f.show()
app.exec_()
As Bob mentioned, using a QTimer would be much better.
Why doesn't the following example work?
from PyQt4 import QtGui
import sys
class TestView(QtGui.QWidget):
def __init__(self):
super(TestView, self).__init__()
self.initUI()
def initUI(self):
self.btn = QtGui.QPushButton('Button', self)
self.btn.resize(self.btn.sizeHint())
self.btn.move(50, 50)
class TestViewController():
def __init__(self, view):
view.btn.clicked.connect(self.buttonClicked)
view.show()
def buttonClicked(self):
print 'clicked'
def main():
app = QtGui.QApplication(sys.argv)
view = TestView()
TestViewController(view)
app.exec_()
if __name__ == '__main__':
main()
The example is supposed to represent an MVC structure (like the one in Figure 4 -- without the Model) where the controller (TestViewController) receives a reference to the view (TestView) and connects the clicked signal from the view's button view.btn to its function self.buttonClicked.
I'm sure the line view.btn.clicked.connect(self.buttonClicked) is executed but, apparently, it has no effect. Does anyone knows how to solve that?
Update (awful solution):
In the example, if I replace the line
view.btn.clicked.connect(self.buttonClicked)
with
view.clicked = self.clicked
view.btn.clicked.connect(view.clicked)
it works. I'm still not happy with that.
The reason it is not working is because the controller class is being garbage collected before you can ever click anything for it.
When you set view.clicked = self.clicked, what you're actually doing is making one of the objects from the controller persist on the view object so it never gets cleaned up - which isn't really the solution.
If you store your controller to a variable, it will protect it from collection.
So if you change your code above to read:
ctrl = TestViewController(view)
You'll be all set.
That being said - what exactly you are trying to do here, I am not sure...it seems you're trying to setup an MVC system for Qt - but Qt already has a pretty good system for that using the Qt Designer to separate the interface components into UI (view/template) files from controller logic (QWidget subclasses). Again, I don't know what you are trying to do and this may be a dumb down version of it, but I'd recommend making it all one class like so:
from PyQt4 import QtGui
import sys
class TestView(QtGui.QWidget):
def __init__(self):
super(TestView, self).__init__()
self.initUI()
def initUI(self):
self.btn = QtGui.QPushButton('Button', self)
self.btn.resize(self.btn.sizeHint())
self.btn.move(50, 50)
self.btn.clicked.connect(self.buttonClicked)
def buttonClicked(self):
print 'clicked'
def main():
app = QtGui.QApplication(sys.argv)
view = TestView()
view.show()
app.exec_()
if __name__ == '__main__':
main()
Edit: Clarifying the MVC of Qt
So this above example doesn't actually load the ui dynamically and create a controller/view separation. Its a bit hard to show on here. Best to work through some Qt/Designer based examples/tutorials - I have one here http://bitesofcode.blogspot.com/2011/10/introduction-to-designer.html but many can be found online.
The short answer is, your loadUi method can be replace with a PyQt4.uic dynamic load (and there are a number of different ways to set that up) such that your code ultimately reads something like this:
from PyQt4 import QtGui
import PyQt4.uic
import sys
class TestController(QtGui.QWidget):
def __init__(self):
super(TestController, self).__init__()
# load view
uifile = '/path/to/some/widget.ui'
PyQt4.uic.loadUi(uifile, self)
# create connections (assuming there is a widget called 'btn' that is loaded)
self.btn.clicked.connect(self.buttonClicked)
def buttonClicked(self):
print 'clicked'
def main():
app = QtGui.QApplication(sys.argv)
view = TestController()
view.show()
app.exec_()
if __name__ == '__main__':
main()
Edit 2: Storing UI references
If it is easier to visualize this concept, you Can also store a reference to the generated UI object:
from PyQt4 import QtGui
import PyQt4.uic
import sys
class TestController(QtGui.QWidget):
def __init__(self):
super(TestController, self).__init__()
# load a view from an external template
uifile = '/path/to/some/widget.ui'
self.ui = PyQt4.uic.loadUi(uifile, self)
# create connections (assuming there is a widget called 'btn' that is loaded)
self.ui.btn.clicked.connect(self.buttonClicked)
def buttonClicked(self):
print 'clicked'
def main():
app = QtGui.QApplication(sys.argv)
view = TestController()
view.show()
app.exec_()
if __name__ == '__main__':
main()
I am working on pyqt4 and python26 application.I created forms using qt designer (.ui files).
I converted them to .py and .pyc files.But when i try to run .py file ,python command line comes and goes within a second,the form (corresponding .ui file) cannot be seen...what can be the problem??
this is my code:(.py file)
from DlgAbout_ui import Ui_DlgAbout
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import resources
class DlgAbout(QDialog, Ui_DlgAbout):
def __init__(self, parent=None):
QDialog.__init__(self, parent)
self.setupUi(self)
self.logo.setPixmap( QPixmap( ":/icons/faunalia_logo.png" ) )
text = self.txt.toHtml()
text = text.replace( "$PLUGIN_NAME$", "RT Sql Layer" )
self.txt.setHtml(text)
First, don't use:
from PyQt4.QtCore import *
from PyQt4.QtGui import *
Instead:
from PyQt4 import QtCore, QtGui
And reference the modules explicitly.
class DlgAbout(QtGui.QDialog, Ui_DlgAbout):
etc.
In your code, all you've done is defined a dialog box. You haven't defined any main application to run, or any way to show the dialog box.
For an example, here's a basic main application to run:
from PyQt4 import QtGui
import sys
class MyMainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MyMainWindow, self).__init__(parent)
self.form_widget = FormWidget(self)
self.setCentralWidget(self.form_widget)
class FormWidget(QtGui.QWidget):
def __init__(self, parent):
super(FormWidget, self).__init__(parent)
self.layout = QtGui.QVBoxLayout(self)
self.button = QtGui.QPushButton("Button!")
self.layout.addWidget(self.button)
if __name__ == "__main__":
app = QtGui.QApplication([])
foo = MyMainWindow()
foo.show()
sys.exit(app.exec_())
This defines a main window, and a form (Which MyMainWindow sets up, as you can see).
I then check if this is the main file being run (if __name__ == "__main__":), and I start the application (The app = QtGui.QApplication([]), create the main window, and show the main window.
In your case, you could define a main application like I did, and make it alert your QDialog.
Your python code just imports some modules and then defines a new class. It doesn't do anything with the class it has defined, though. In other words, once Python is done creating the new class, it is finished, and it exits.
I don't know PyQT at all, but most likely you need to start the GUI's main loop, and also instantiate an instance of your new class and pass it to PyQT.