Pulling text from QLineEdit - python

I made a dialog with a simple QLineEdit and QbuttonBox (lineEdit and buttonBox respectively), now I'm trying to use what is in the line edit when I press OK. It simply comes out blank and doesn't print during go and prints "None" for the bottom of print(base). Surfed and found the text() but still no love. Any help is appreciated.
from PyQt4 import QtGui, QtCore
import sys
import x
class Dialog(QtGui.QDialog, x.Ui_Dialog):
def __init__(self):
super(Dialog, self).__init__()
self.setupUi(self)
global base
base = self.buttonBox.accepted.connect(self.go)
def go(self):
what = self.lineEdit.text()
return what
print(what)
app = QtGui.QApplication(sys.argv)
form = Dialog()
form.show()
app.exec_()
print(base)

The example code is mostly correct, except that the go() method is returning before it has a chance to print anything. So if you remove that line, it should work as expected, i.e:
class Dialog(QtGui.QDialog, x.Ui_Dialog):
def __init__(self):
super(Dialog, self).__init__()
self.setupUi(self)
self.buttonBox.accepted.connect(self.go)
def go(self):
what = self.lineEdit.text()
print(what)
Also, there is no point in grabbing the return value when you connect a signal to a handler. If the connection is invalid, it will just raise an error.
EDIT:
If you want to access the text of the line-edit from outside of the dialog, then you don't really need a signal. Just make sure the dialog blocks until the user has entered the text, and then access the line-edit directly:
dialog = Dialog()
if dialog.exec_() == QtGui.QDialog.Accepted:
text = dialog.lineEdit.text()
# do stuff with text...
else:
print('cancelled')

Related

Trying to copy text from other threads using a button

I am trying to figure out a way to make a decent copy to clipboard button function where I can copy text values from other threads inside a QTextEdit widget.
I pull the values from other threads and display them in a QTextEdit widget and have been trying to successfully copy to clipboard the contents of QTextEdit with a button but the only way I have been able to is my code below.
What I don't like is that the copy button makes a second call in order to copy the contents.
Is there some way that the values can be stored from the first request using the get_button button and be available to copy with the copy button without having to make the same call all over again? Thanks.
from PyQt4 import QtCore, QtGui
import sys
class WorkerThread(QtCore.QThread):
get_String = QtCore.pyqtSignal(str)
def __init__(self):
super(WorkerThread, self).__init__()
def run(self):
self.get_String.emit('Some text.')
class GUI(QtGui.QWidget):
def __init__(self):
super(GUI, self).__init__()
self.get_Button = QtGui.QPushButton('Get')
self.c_Button = QtGui.QPushButton('Copy')
self.text_Box = QtGui.QTextEdit(self)
vbox = QtGui.QVBoxLayout(self)
vbox.addWidget(self.get_Button)
vbox.addWidget(self.c_Button)
vbox.addWidget(self.text_Box)
vbox.addStretch()
self.setGeometry(300, 300, 300, 300)
self.show()
self._thread = WorkerThread()
self.get_Button.clicked.connect(self.doIt)
self._thread.get_String.connect(self.text_Box.append)
self.c_Button.clicked.connect(self.copy_Stuff)
def copy_Stuff(self):
self.clipboard = QtGui.QApplication.clipboard()
self._thread.get_String.connect(self.clipboard.setText)
self._thread.start()
def doIt(self):
self.text_Box.clear()
self.text_Box.setText('')
self._thread.start()
def main():
app = QtGui.QApplication(sys.argv)
gui = GUI()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
It turns out this was much easier than I initially thought. I was confused with how to copy text correctly because of all of the different ways I seen it done in other examples and posts. After reading the docs for awhile and trying to learn a bit more about pyqt I seen that it was as easy as using these 2 lines...
self.text_Box.selectAll()
self.text_Box.copy()
with those 2 lines and my button it seems to copy all the contents of the QTextEdit widget which is all I really needed. Here is my final working code in case someone else may find it useful.
from PyQt4 import QtCore, QtGui
import sys
class WorkerThread(QtCore.QThread):
get_String = QtCore.pyqtSignal(str)
def __init__(self):
super(WorkerThread, self).__init__()
def run(self):
self.get_String.emit('Some text.')
class GUI(QtGui.QWidget):
def __init__(self):
super(GUI, self).__init__()
self.get_Button = QtGui.QPushButton('Get')
self.c_Button = QtGui.QPushButton('Copy')
self.text_Box = QtGui.QTextEdit(self)
vbox = QtGui.QVBoxLayout(self)
vbox.addWidget(self.get_Button)
vbox.addWidget(self.c_Button)
vbox.addWidget(self.text_Box)
vbox.addStretch()
self.setGeometry(300, 300, 300, 300)
self.show()
self._thread = WorkerThread()
self.get_Button.clicked.connect(self.doIt)
self._thread.get_String.connect(self.text_Box.append)
self.c_Button.clicked.connect(self.copy_Stuff)
def copy_Stuff(self):
self.text_Box.selectAll()
self.text_Box.copy()
def doIt(self):
self.text_Box.clear()
self.text_Box.setText('')
self._thread.start()
def main():
app = QtGui.QApplication(sys.argv)
gui = GUI()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
This code example shows a simple working thread with signal that returns a value to the main, displays the value in a QTextEdit widget and how to copy all of the contents of a QTextEdit widget with a single button click.

How to call back the same window!? PYQT5

I spent all day debugging and stripping my project to fix this issue.
I have a help window(Help_ui class) which should open if the text.txt is not found and the main window(Main class)which has a QTextEdit box which should print "Hello".
The problem is that when I call the Main window from the Help_ui class it doesn't print "Hello", but it does if I call it from the logic.
Why is doing this, does it open another instance of that windows and not the proper window?
from PyQt5 import QtWidgets
import sys
from pathlib import Path
from ui_files import mainWindow
from ui_files import help_ui
text = "Hello"
class Main(QtWidgets.QMainWindow, mainWindow.Ui_mainWindow):
def __init__(self, text):
super().__init__()
self.setupUi(self)
self.mainTextEdit.setText(text)
class Help_ui(QtWidgets.QDialog, help_ui.Ui_help):
def __init__(self):
super().__init__()
self.setupUi(self)
self.close_btn.clicked.connect(self.close)
self.form = Main(None)
self.form.show()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
form = Main(text)
my_file = Path("file.txt")
if my_file.is_file():
form.show()
else:
help_window = Help_ui()
help_window.show()
app.exec_()
What happens is that the instance form is different from the instance self.form, in the first you pass as a parameter text, instead in the second None.
Must be change self.form = Main(None) to self.form = Main(text)

PyQt4 signals and slots - QToolButton

In PyQt4 I have a main window which when the settings button is clicked opens the settings dialog
from PyQt4 import QtCore, QtGui
import ui_Design, ui_Settings_Design
class MainDialog(QtGui.QMainWindow, ui_Design.Ui_arbCrunchUI):
def __init__(self, parent=None):
super(MainDialog, self).__init__(parent)
self.setupUi(self)
self.settingsBtn.clicked.connect(lambda: self.showSettings())
def showSettings(self):
dialog = QtGui.QDialog()
dialog.ui = SettingsDialog()
dialog.ui.setupUi(dialog)
dialog.exec_()
The above works and my SettingsDialog is displayed but I cant get the setPageIndex to work
class SettingsDialog(QtGui.QDialog, ui_Settings_Design.Ui_SettingsDialog):
def __init__(self, parent=None):
super(SettingsDialog, self).__init__(parent)
self.setupUi(self)
self.bookSettingsBtn.clicked.connect(self.setPageIndex)
#QtCore.pyqtSlot()
def setPageIndex(self):
print 'selected'
self.settingsStackedWidget.setCurrentIndex(0)
The bookSettingsBtn is a QToolButton
self.bookSettingsBtn = QtGui.QToolButton(self.navigationFrame)
And the settingsStackedWidget is a QStackedWidget
self.settingsStackedWidget = QtGui.QStackedWidget(SettingsDialog)
At this point I am pretty confused on signals and slots and nothing I have read clears this up - if anyone can point out what I am doing wrong above and also potentially direct me to a good (beginners) guide / tutorial on signals and slots it would be greatly appreciated
I would also like to know how to make setPageIndex work as follows:
def setPageIndex(self, selection):
self.settingsStackedWidget.setCurrentIndex(selection)
I'm not sure why you're doing the following, but that's the issue:
def showSettings(self):
dialog = QtGui.QDialog()
dialog.ui = SettingsDialog()
dialog.ui.setupUi(dialog)
dialog.exec_()
SettingsDialog itself is a proper QDialog. You don't need to instantiate another QDialog.
Right now, you're creating an empty QDialog and then populate it with the same ui as SettingsDialog (i.e. setupUi(dialog)), then you show this dialog. But... The signal connection is for SettingsDialog, and the dialog you're showing doesn't have that.
Basically, you don't need that extra QDialog at all. The following should be enough:
def showSettings(self):
dialog = SettingsDialog()
dialog.exec_()
Ok. So here is an example how you pass an argument to a slot
from functools import partial
# here you have a button bookSettingsBtn:
self.bookSettingsBtn = QtGui.QPushButton("settings")
self.bookSettingsBtn.clicked.connect(partial(self.setPageIndex, self.bookSettingsBtn.text()))
#pyqtSlot(str) # this means the function expects 1 string parameter (str, str) 2 string parameters etc.
def setPageIndex(self, selection):
print "you pressed button " + selection
In your case the argument would be an int. Of course you have to get the value from somewhere
and then put it in the partial part as the argument (here I just used the text of the button),
but you can use int, bool etc. Just watch the slot signature.
Here is a tutorial that helped me:
http://zetcode.com/gui/pyqt4/
I hope this helps.
Hey here I have a fully running example (just copy paste it in a python file and run it):
Maybe this helps you. It's a small example but here you see how it works.
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from functools import partial
class MyForm(QMainWindow):
def __init__(self, parent=None):
super(MyForm, self).__init__(parent)
button1 = QPushButton('Button 1')
button2 = QPushButton('Button 2')
button1.clicked.connect(partial(self.on_button, button1.text()))
button2.clicked.connect(partial(self.on_button, button1.text()))
layout = QHBoxLayout()
layout.addWidget(button1)
layout.addWidget(button2)
main_frame = QWidget()
main_frame.setLayout(layout)
self.setCentralWidget(main_frame)
#pyqtSlot(str)
def on_button(self, n):
print "Text of button is: " + str(n)
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
form = MyForm()
form.show()
app.exec_()
So I dont really understand why but changing the way the settingsDialog is called from the MainWindow has fixed my problem. I guess the parent window needed to be specified??:
class MainDialog(QtGui.QMainWindow, ui_Design.Ui_arbCrunchUI):
....
def showSettings(self):
self.settingsDialog = QtGui.QDialog(self)
self.settingsDialog.ui = SettingsDialog(self)
self.settingsDialog.ui.show()
class SettingsDialog(QtGui.QDialog, ui_Settings_Design.Ui_SettingsDialog):
def __init__(self, parent=None):
super(SettingsDialog, self).__init__(parent)
self.setupUi(self)
self.bookSettingsBtn.clicked.connect(partial(self.setPageIndex, 1))
#QtCore.pyqtSlot(int)
def setPageIndex(self, selection):
self.settingsStackedWidget.setCurrentIndex(selection)

Quiting the print dialog-pyqt

I defined a print function using QPrinter and QDialog. However, when I launch the printer dialog and then press cancel, the entire mainwindow goes into not responding mode. I have tried to do QtGui.QPrintDialog.close() but does not work.
Code:
import sys
from PyQt4 import QtCore
from PyQt4 import QtGui
class QButton(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.button = QtGui.QPushButton('Button', self)
self.name='me'
self.button.clicked.connect(self.calluser)
def calluser(self):
Appli=QtGui.QApplication(sys.argv)
printer= QtGui.QPrinter()
doc=QtGui.QTextDocument("Set local variables in this printing slot." )
dialog = QtGui.QPrintDialog(printer)
dialog.setModal(True)
dialog.setWindowTitle("Print Document" )
if dialog.exec_() == True:
doc.print_(printer)
# dialog.addEnabledOption(QAbstractPrintDialog.PrintSelection)
def demo_QButton():
app = QtGui.QApplication(sys.argv)
tb = QButton()
tb.show()
app.exec_()
if __name__=='__main__':
demo_QButton()
You created a new application in the calluser method. Delete or comment the line:
Appli=QtGui.QApplication(sys.argv)
and try again. I think this time your main window will remain responsive.

Open a second window in PyQt

I'm trying to use pyqt to show a custom QDialog window when a button on a QMainWindow is clicked. I keep getting the following error:
$ python main.py
DEBUG: Launch edit window
Traceback (most recent call last):
File "/home/james/Dropbox/Database/qt/ui_med.py", line 23, in launchEditWindow
dialog = Ui_Dialog(c)
File "/home/james/Dropbox/Database/qt/ui_edit.py", line 15, in __init__
QtGui.QDialog.__init__(self)
TypeError: descriptor '__init__' requires a 'sip.simplewrapper' object but received a 'Ui_Dialog'
I've gone over several online tutorials, but most of them stop just short of showing how to use a non built-in dialog window. I generated the code for both the main window and the dialog using pyuic4. What I think should be the relevant code is below. What am I missing here?
class Ui_Dialog(object):
def __init__(self, dbConnection):
QtGui.QDialog.__init__(self)
global c
c = dbConnection
class Ui_MainWindow(object):
def __init__(self, dbConnection):
global c
c = dbConnection
def launchEditWindow(self):
print "DEBUG: Launch edit window"
dialog = QtGui.QDialog()
dialogui = Ui_Dialog(c)
dialogui = setupUi(dialog)
dialogui.show()
class StartQT4(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
conn = sqlite3.connect('meds.sqlite')
c = conn.cursor()
self.ui = Ui_MainWindow(c)
self.ui.setupUi(self)
def main():
app = QtGui.QApplication(sys.argv)
program = StartQT4()
program.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Bonus question: since it looks like you can't pass arguments in pyqt function callbacks, is setting something which would otherwise be passed as an argument (the poorly named "c") to be global the best way to get information into those functions?
I've done like this in the past, and i can tell it works.
assuming your button is called "Button"
class Main(QtGui.QMainWindow):
''' some stuff '''
def on_Button_clicked(self, checked=None):
if checked==None: return
dialog = QDialog()
dialog.ui = Ui_MyDialog()
dialog.ui.setupUi(dialog)
dialog.setAttribute(QtCore.Qt.WA_DeleteOnClose)
dialog.exec_()
This works for my application, and I believe it should work with yours as well. hope it'll help, it should be pretty straight forward to do the few changes needed to apply it to your case.
have a good day everybody.
Ui_Dialog should inherent from QtGui.QDialog, not object.
class Ui_Dialog(QtGui.QDialog):
def __init__(self, dbConnection):
QtGui.QDialog.__init__(self)
global c
c = dbConnection
class StartQT4(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
Why QtGui.QWidget.__init___ ???
Use insted:
class StartQT4(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
You must call __init__ methon from base class (name in parenthesis '()')
QDialog have two useful routins:
exec_()
show()
First wait for closing dialog and then you can access any field form dialog. Second show dialog but don't wait, so to work properly you must set some slot/signals connections to respond for dialog actions.
eg. for exec_():
class Dialog(QDialog):
def __init__(self, parent):
QDialog.__init__(parent)
line_edit = QLineEdit()
...
dialog = Dialog()
if dialog.exec_(): # here dialog will be shown and main script will wait for its closing (with no errors)
data = dialog.line_edit.text()
Small tip: can you change your ui classes into widgets (with layouts). And perhaps problem is that your __init__ should be __init__(self, parent=None, dbConnection)
Because when you create new widget in existing one PyQt may try to set it as children of existing one. (So change all init to have additional parent param (must be on second position)).

Categories