how can I oveload paste on a QtextEdit - python

I want to paste in a QTextEdit an text with an certain font size, ex. 14
I made an app that replace a paraghaph sign with a blank space, like in
PyQt QLineEdit and 'paste' event?
On def __init__(self) I code:
self.textEdit.textChanged.connect(self.valueChanged)
then
def valueChanged(self, text):
if QtGui.QApplication.clipboard().text() == text:
self.pasteEvent(text)
and then
def pasteEvent(self, text):
text.toUpper()
TypeError: valueChanged() takes exactly 2 arguments (1 given)

In the previous question that links you use a QLineEdit that has the void QLineEdit::textChanged(const QString &text) signal that carries the text, but in the case of QTextEdit there is a signal with the same name void textChanged() but it does not carry the text so that is the cause of the error. The solution for that case is to obtain the text using the object and not through the signal.
def valueChanged(self):
if QtGui.QApplication.clipboard().text() == self.textEdit.text():
self.pasteEvent(text)
Although if your goal is to change the size of the font then your previous logic does not work since you are detecting the event after the text is pasted, if you want to modify something during the paste then you must override the insertFromMimeData() method:
from PyQt4 import QtCore, QtGui
class TextEdit(QtGui.QTextEdit):
def insertFromMimeData(self, source):
last_font = self.currentFont()
new_font = QtGui.QFont(last_font)
new_font.setPointSize(14)
self.setCurrentFont(new_font)
super(TextEdit, self).insertFromMimeData(source)
self.setCurrentFont(last_font)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
w = TextEdit()
w.show()
sys.exit(app.exec_())

Related

Printing some text in a Label, depending on textbox input - PyQT5

I need help figuring out how to use the value written in a textbox in PyQT5, and use that value to build an IF statement. Any suggestions on how to do it? I have tried to declare the text in the textbox as a variable and use it in the IF statement but I can't seem to figure it out how to do it properly, and every time i run the code, some exit code shows (-1073741819 (0xC0000005) ).
Summing up, can't use pass the value of the textbox to the variable in order to do an IF statement.
I had this code down below:
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QTextEdit
def window():
app = QApplication(sys.argv)
win = QMainWindow()
win.setGeometry(200, 200, 400, 400)
win.setWindowTitle("Register Program")
label = QtWidgets.QLabel(win)
label.setText("Random Text")
label.move(169, 15)
label2 = QtWidgets.QLabel(win)
label2.resize(300, 100)
label2.setText("1- Register new person\n2- See all regestries\n3- See last regestry\n\nPress ESC to exit\n")
label2.move(70, 50)
textbox = QtWidgets.QLineEdit(win)
textbox.setText("")
textbox.resize(250, 25)
textbox.move(70, 250)
button1 = QtWidgets.QPushButton(win)
button1.move(150, 300)
button1.setText("Submit")
button1.clicked.connect(clicked)
button2 = QtWidgets.QPushButton(win)
button2.move(150, 335)
button2.setText("Close")
button2.clicked.connect(close)
win.show()
sys.exit(app.exec_())
def clicked():
inpt = int(window().textbox.text)
if inpt == 1:
print("Hello")
def close():
sys.exit()
window()```
If you're just looking to get user input, there's a builtin static method you can call for requesting input of a particular type: https://doc.qt.io/qt-5/qinputdialog.html#getText
If you want to make your own widget however, you need to use the signals and slots to trigger a python method to store the value. This is easiest to do in a class. You can trigger the method whenever the text changes with the textChanged signal and do whatever you need to do with it.
(Note, I haven't run this as I don't have PyQt5 currently installed, but it should work)
from PyQt5 import QtCore, QtGui, QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
# type: (QtWidgets.QWidget) -> None
super(Widget, self).__init__(parent)
self.line_edit = QtWidgets.QLineEdit()
main_layout = QtWidgets.QVBoxLayout()
main_layout.addWidget(self.line_edit)
self.setLayout(main_layout)
self.line_edit.textChanged.connect(self.on_text_changed)
def get_text(self):
return self.line_edit.text()
def on_text_changed(self, text):
print("The text was changed to:", text)
if __name__ == '__main__':
app = QtWidgets.QApplication([])
widget = Widget()
widget.show()
app.exec_()
Edit: Also, to clarify why you're getting an error, QApplication is a singleton. This means there can only ever be one created. If you try to create a second, you'll get an error. The best way to access the current QApplication is to call QApplication.instance(). You also only call app.exec_() once, as once the application is running it will continue to run in the background. You should use signal/slots to interact with the UI and trigger the code you want to run.

Connecting in PyQt4 QMessageBox fails to call the slot method

I was trying to analyse the sample code cited here: PyQt - QMessageBox
Here's the snippet:
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class Window(QMainWindow):
def __init__(self):
super().__init__()
w = QWidget()
b = QPushButton(self)
b.setText("Show message!")
b.clicked.connect(self.showdialog)
w.setWindowTitle("PyQt Dialog demo")
def showdialog(self):
msg = QMessageBox()
msg.setIcon(QMessageBox.Question)
# self.connect(msg, SIGNAL('clicked()'), self.msgbtn)
msg.buttonClicked.connect(self.msgbtn)
msg.exec_()
def msgbtn(self, i):
print("Button pressed is:", i.text())
if __name__ == '__main__':
app = QApplication([])
w = Window()
w.show()
app.exec_()
There are two ways of connecting signals to slots in PyQt. For buttons, it's:
QtCore.QObject.connect(button, QtCore.SIGNAL(“clicked()”), slot_function)
or
widget.clicked.connect(slot_function)
Using it the second way works fine: the msgbtn slot method is called as intended. However, if I try to change it to the more usual, 'PyQt-onic' way of connecting (i.e. the first one - I commented it out in the snippet), the slot method is never called. Could anyone please help me out with this?
the signal you pass to SIGNAL is incorrect, the QMessageBox does not have the clicked signal but the signal is buttonClicked (QAbstractButton *) so the correct thing is:
self.connect(msg, SIGNAL("buttonClicked(QAbstractButton *)"), self.msgbtn)
On the other hand that is not the PyQt-onic style, but the old style which is not recommended to use, but we recommend using the new style.
Old style:
self.connect(msg, SIGNAL("buttonClicked(QAbstractButton *)"), self.msgbtn)
New style:
msg.buttonClicked.connect(self.msgbtn)
For more detail read the docs.

Qt - keep reference of widget in Python

In reference to a previous question, I need some help with keeping references in my application.
First a snippet from my code.
from PyQt4 import QtGui
import os, os.path
import sys
class mainWindowHandler():
equationEditor = []
_listview = None
_window = None
def __init__(self):
return
def showAddEquation(self):
"""Creates a new instance of the dynamic editor for adding an equation"""
#create a horizontal split layout
window = QtGui.QWidget()
layout = QtGui.QHBoxLayout()
current = len(self.equationEditor) - 1
de = QtGui.QPushButton(str(current))
self.equationEditor.append(de)
de.clicked.connect(self.clicked)
#fill list view with items from equation collection
listview = QtGui.QListWidget()
for equation in self.equationEditor:
item = QtGui.QListWidgetItem()
item.setText(equation.text())
listview.addItem(item)
layout.addWidget(listview)
layout.addWidget(de)
window.setWindowTitle("Equation {}".format(str(current))
window.setLayout(layout)
self._window = window
self._listview = listview
window.show()
return window
def clicked(self):
"""Method for handling the button events in the solver settings\n
signal = the button hit\n"""
return self.showAddEquation()
if __name__ == "__main__":
path = os.path.dirname(os.path.abspath(__file__))
app = QtGui.QApplication(sys.argv)
ewh = mainWindowHandler()
window = ewh.showAddEquation()
sys.exit(app.exec_())
The application will (later) create a window that allows the manipulation of certain settings - in my code example represented by the QPushButton. These settings are later written to a txt-file, but until then I save them in form of there widget. I simply add the widget to a collection and recall them from there. That works well on the Python-level.
Now, I have a button that creates a new instance of the window from inside of the window itself. That works too. But only until the third instance. At that point I loose the reference to my QPushButton on the Qt-level. I get the
wrapped C/C++ object of type `QPushButton` has been deleted
error when trying to retrieve the buttons from my collection (equationEditor). In Python they are still there, but obviously the corresponding Qt-objects where destroyed because I somewhere mishandled the references.
Can someone point out a better solution or how I can keep the references?
Thanks...
Edit:
As there seem to be some confusions I will try to explain the functionality a bit more in detail.
The program starts and creates a window "Equation 1" with a QListViewand a QPushButton "1". In the list view all available QPushButton are listed (at start only 1 item). In my actual program the QPushButton is QWidget with some text fields and the QPushButton.
If the user clicks "1" then the button "1" should disappear and a new instance of QPushButton named "2" should appear at the position of "1". Additionally, the listview should now hold two items "1" and "2" and the window should have the title "Equation 2". If it is a new window or the same as before with new contents is not relevant. Both variants would be okay. The former is the way it is implemented at the moment. Visible should by only one window at a time.
All instances of QPushButton should by collected in a small list (called equationEditor) to keep them in the memory. In my actual program this is used for saving all changes made in the widgets without writing the changes to a temp file.
Later, if the user selects item "1" in the QListView then the current visible QPushButton should be replaced by the QPushButton "1" (from the collection equationEditor) or if he selects the second item the QPushButton "2" should be shown.
Why?
The widget that will be used later contains a lot of editable data. As the user could edit that at any time it is easier to keep the widgets in memory without showing them instead of repopulating all the data again. As soon as the user selects one in the QListView the corresponding widget should be shown in the window so that he can edited the data in the widget again.
It's quite hard to understand what exactly you're trying to do. Looking at your code I wonder why it is even working twice before failing.
Btw. I just saw, that there is a quite accurate description of why it's failing in the previous post, given by Schollii
Anyways, I think you should make a new class for the equation window. The main class can then keep track of all opened windows in the equationEditor list. It can also add the values of the other opened windows to a new one, once created.
Here is how it would look like
from PyQt4 import QtGui
import os, os.path
import sys
class ShowAddEquation(QtGui.QWidget):
"""Creates a new instance of the dynamic editor for adding an equation"""
def __init__(self,parent=None):
super(ShowAddEquation, self).__init__(parent=parent)
#create a horizontal split layout
layout = QtGui.QHBoxLayout()
self.current = 0
self.de = QtGui.QPushButton(str(self.current))
self.listview = QtGui.QListWidget()
layout.addWidget(self.listview)
layout.addWidget(self.de)
self.setWindowTitle("Equation Editor")
self.setLayout(layout)
self.show()
def setCurrent(self, current):
self.current=current
self.de.setText(str(self.current))
class mainWindowHandler():
equationEditor = []
def __init__(self):
return
def clicked(self):
se = ShowAddEquation()
self.equationEditor.append(se)
se.de.clicked.connect(self.clicked)
current = len(self.equationEditor) - 1
se.setCurrent(current)
for equation in self.equationEditor:
item = QtGui.QListWidgetItem()
item.setText(str(equation.current))
se.listview.addItem(item)
if __name__ == "__main__":
path = os.path.dirname(os.path.abspath(__file__))
app = QtGui.QApplication(sys.argv)
ewh = mainWindowHandler()
ewh.clicked()
sys.exit(app.exec_())
So, after understanding the approach given in the first answer I have solved my problem. Here is the working code
# -*- coding: utf-8 -*-
"""
Created on Sat Sep 3 14:31:15 2016
"""
from PyQt4 import QtGui
from PyQt4 import QtCore
import os, os.path
import sys
class mainWindowHandler():
equationEditor = []
_listview = None
_window = None
def __init__(self):
return
def showAddEquation(self):
"""Creates a new instance of the dynamic editor for adding an equation"""
#create a horizontal split layout
self._window = QtGui.QWidget()
layout = QtGui.QHBoxLayout()
self._listview = QtGui.QListWidget()
layout.addWidget(self._listview)
self._listview.clicked[QtCore.QModelIndex].connect(self.changed)
self._window.setLayout(layout)
#populate the right side of the layout with a button
self.clicked()
self._window.show()
return self._window
def clicked(self):
"""Make a new button instance and add it to the window and the collection"""
window = self._window
layout = window.layout()
current = len(self.equationEditor) - 1
de = QtGui.QPushButton(str(current))
self.equationEditor.append(de)
de.clicked.connect(self.clicked)
#close the currently shown button
item = layout.takeAt(1)
if item is not None:
item.widget().close()
layout.addWidget(de)
#fill list view with items from material collection
item = QtGui.QListWidgetItem()
item.setText(de.text())
self._listview.addItem(item)
self._window.setWindowTitle("Equation Editor {}".format(str(current)))
def changed(self, index):
"""hide the object on the right side of the layout and show the button at position index in the collection"""
layout = self._window.layout()
item = layout.takeAt(1)
item.widget().close()
# insert the selected button from the collection
de = self.equationEditor[index.row()]
layout.insertWidget(1, de)
self._window.setWindowTitle("Equation Editor {}".format(str(index.row() - 1)))
de.show()
if __name__ == "__main__":
path = os.path.dirname(os.path.abspath(__file__))
app = QtGui.QApplication(sys.argv)
ewh = mainWindowHandler()
window = ewh.showAddEquation()
sys.exit(app.exec_())

Make an action when the QLineEdit text is changed (programmatically)

I have written the following code snippet with an QLineEdit that can be edited by pushing the button "Add Text".
import sys
import os
from PyQt4 import QtGui
from PyQt4 import *
class SmallGUI(QtGui.QMainWindow):
def __init__(self):
super(SmallGUI,self).__init__()
self.initUI()
def initUI(self):
self.setGeometry(300,300,300,300)
self.setWindowTitle('Sample')
#One input
self.MyInput = QtGui.QLineEdit(self)
self.MyInput.setGeometry(88,25,110,20)
###############
QtCore.QObject.connect(self.MyInput,QtCore.SIGNAL("textChanged(bool)"),self.doSomething)
#Add Text
self.MyButton = QtGui.QPushButton(self)
self.MyButton.setGeometry(QtCore.QRect(88,65,110,20))
self.MyButton.setText('Add Text')
###############
QtCore.QObject.connect(self.MyButton,QtCore.SIGNAL("clicked(bool)"),self.addText)
self.show()
def addText(self):
self.MyInput.setText('write something')
def doSomething(self):
print "I'm doing something"
def main():
app = QtGui.QApplication(sys.argv)
sampleForm = SmallGUI()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
What I would like to do is to execute an action when the text of the QLineEdit is changed programmatically, i.e. by clicking the button 'Add Text', doing the following:
QtCore.QObject.connect(self.MyInput,QtCore.SIGNAL("textChanged(bool)"),self.doSomething)
The reason why I have used the signal "textChanged" is related to what the class documentation says, that is "this signal is also emitted when the text is changed programmatically, for example, by calling setText()."
However this does not work cause the print statement is not executed. Can anyone help me out with that?
The problem is that the signal is not textChanged(bool) because it takes a string argument, so it should probably be: textChanged(str).
To avoid this kind of errors you should use the new-style syntax for connecting signals:
self.MyInput.textChanged.connect(self.doSomething)
# or:
self.MyInput.textChanged[str].connect(self.doSomething)
This syntax has several advantages:
It is clearer
It's less verbose and more readable
It provides more error checking because if the signal doesn't exist it raises an error. With the old syntax no error is raised, but the signal isn't connected either and the result is the behaviour you have seen.

PyQt4 connect to signal "textValueChanged()"

I have a app that uses PyQt4 for GUI. But having some issues with connecting to signals.
I made a button like this
self.button=QtGui.QPushButton("Load File")
QObject.connect( self.button, SIGNAL('clicked ()'), self.clicked )
And it perfectly fires the following function:
def clicked(self):
So in the same manner i made a input element. However the input element signal does not fire when i change the text.
self.filter=QtGui.QInputDialog() #Create the Input Dialog
self.filter.setInputMode (self.filter.InputMode.TextInput ) #Change the input type to text
self.filter.setOption(self.filter.InputDialogOption.NoButtons,True) #I don't need the buttons so i have removed them
self.filter.setLabelText("Filter") #I change the label to "filter"
self.connect( self.filter, QtCore.SIGNAL("textValueChanged()"), self.filterUpdate ) #I connect to the signal textValueChanged() that should be fired when the text is changed and make it fire the filterUpdate() function
The following is never fired:
def filterUpdate(self):
print "Hello"
This works here:
from PyQt4 import QtCore, QtGui
import sys
app = QtGui.QApplication(sys.argv)
def filterUpdate():
print('!')
filter = QtGui.QInputDialog()
filter.setInputMode (filter.TextInput)
filter.setOption(filter.NoButtons, True)
filter.setLabelText("Filter")
filter.textValueChanged.connect(filterUpdate)
filter.show()
sys.exit(app.exec_())

Categories