PyQt: how do I replace a widget using a button? - python

I'm trying to write a simple code which will change existing text widget to another one when user clicks a button.
So I have
title1=QtGui.QLabel('Hello')
title2=QtGui.QLabel('bye')
abutton=QtGui.QPushButton('Click me')
grid.addWidget(title1,1,5)
grid.addWidget(abutton,3,5)
and I have a function:
def myfunc(self):
self.grid.removeWidget(self.title1)
self.grid.addWidget(title2,1,5)
which I expect to change my "hello" to "bye" after I do this:
abutton.clicked.connect(self.myfunc)
but apparently that doesn't work. And I've checked: removeWidged works perfectly outside the function (my first thought was, maybe, i was doing something wrong in the function), and also the function does work itself(i checked it by making in print stuff and it did once I clicked the button, but the widget was still there)
what might I be doing wrong? thanks.

You had typo and you trying local vars like so many issues in your code. Here is a working example
from PyQt4 import QtGui, QtCore
import sys
class BASEGUICLS(QtGui.QDialog):
def __init__(self,parent=None):
super(BASEGUICLS, self).__init__(parent)
self.gridLayout = QtGui.QGridLayout()
self.title1=QtGui.QLabel('Hello')
self.title2=QtGui.QLabel('bye')
abutton=QtGui.QPushButton('Click me')
self.gridLayout.addWidget(self.title1,1,5)
self.gridLayout.addWidget(abutton,3,5)
self.setLayout(self.gridLayout)
abutton.clicked.connect(self.myfunc)
def myfunc(self):
self.gridLayout.removeWidget(self.title1)
self.title1.deleteLater()
self.gridLayout.addWidget(self.title2,1,5)
def main():
app = QtGui.QApplication(sys.argv)
ex = BASEGUICLS(None)
ex.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()

Related

QPushButton.clicked.connect doesn't seem to work

I am trying to decouple entirely my GUI from my controller class, and for some reason I can't seem to manage to connect my buttons from outside of my GUI class itself.
Here's a small example of what I mean :
import sys
from PySide6 import QtWidgets
class Gui(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Gui, self).__init__(parent)
layout = QtWidgets.QHBoxLayout(self)
self.button = QtWidgets.QPushButton("Do stuff")
layout.addWidget(self.button)
class Controller(object):
def do_stuff(self):
print("something")
def startup(parent):
ctrl = Controller()
gui = Gui(parent)
gui.button.clicked.connect(ctrl.do_stuff)
return gui
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
dialog = QtWidgets.QDialog()
gui = startup(dialog)
dialog.show()
sys.exit(app.exec_())
I would expect this code, when run, to display a GUI with one push button (which it does), and when pressing the push button, I'd expect the word "something" to get printed. However this doesn't seem to be the case.
I might just be too tired, but I can't find the solution.
What am I missing?
Thanks a lot in advance!
ctrl = None
gui = None
def startup(parent):
global ctrl
global gui
ctrl = Controller()
gui = Gui(parent)
gui.button.clicked.connect(ctrl.do_stuff)
return gui
try this, and it does work. when the variable is in the function, it will be destroyed before the function is finished. the global variable is not a good coding style but is a simple way to figure out your confusion.

Detect Ctrl+S ion QTextedit?

So, I'm making a QTextEdit that edits a text file. I got the loading and saving working fine with buttons. But I got the habit of pressing Ctrl+S to save every time I paste something into the textedit because I used that in Notepad before. So I've been trying to implement it. But I can't wrap my head around how to detect and execute my save function. Lets call it savetext.
I've been going around trying to get keyPressEvent to work, but I just don't understand how it works. So I've been pretty helpless in trying to learn it.
My heavily simplified code looks like this:
class GUI(QProcess):
def init etc...
"Button creations and connect to save/load function"
self.textedit=QTextEdit()
def savetext(self):
code
def loadtext(self):
code
Now, how do I detect a key combination being detected in the QTextEdit, or anywhere in my program for that matter, and cause it to do savetext? In my case, Ctrl+S, though I'd just love a general explanation so I could apply it to any combo.
Use QShortcut and QKeySequence
from PyQt5.QtWidgets import QApplication, QTextEdit, QShortcut
from PyQt5.QtGui import QKeySequence
import sys
def slot():
print("Ctrl+S")
app = QApplication(sys.argv)
textedit=QTextEdit()
shortcut = QShortcut(QKeySequence("Ctrl+S"), textedit)
shortcut.activated.connect(slot)
textedit.show()
sys.exit(app.exec_())
You can probably use QShortcut, and right now it will activate only when textedit in focus. If you want to change the behavior please take a look here
Here is a example
import sys
from PyQt4 import QtGui, QtCore
class Window(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
layout = QtGui.QVBoxLayout(self)
self.edit = QtGui.QTextEdit()
layout.addWidget(self.edit)
self.button = QtGui.QPushButton('Test')
layout.addWidget(self.button)
foo = QtGui.QShortcut(QtGui.QKeySequence("Ctrl+S"), self.edit, self.saveCall, context=QtCore.Qt.WidgetShortcut)
def saveCall(self):
self.edit.append('Please save me')
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec_())

QPlainTextEdit thinks it's modified if it has an empty text

I'm using PyQt to build a simple IDE and getting weird errors if you load an empty file. A small example script is posted below:
#!/usr/bin/env python
import sys
from PyQt4 import QtGui
class TestApp(QtGui.QMainWindow):
def __init__(self, filename=None):
super(TestApp, self).__init__()
self._editor = QtGui.QPlainTextEdit()
self._editor.modificationChanged.connect(self._change_modified)
self.setCentralWidget(self._editor)
self._editor.setPlainText('a')
def _change_modified(self, have_change):
print(have_change)
if __name__ == '__main__':
a = QtGui.QApplication([])
app = TestApp()
app.show()
sys.exit(a.exec_())
As expected, this shows a window with a plain text editor. As soon as the setPlainText method is called, the editor emits two events: One modificationChanged event with changes=True, a second with changes=False.
A bit weird, but fine.
However, if you change setPlainText('a') to setPlainText(''), only a single event is emitted, this time with changes=True. Even worse, after telling the editor it's not modified with setModified(False), it insists it's been changed somehow.
Does anyone know what's causing this and how I can work around this issue?
Update: It seems to be a bug & also affects QPlainTextEdit.clear().
The workaround below places a wrapper around the QPlainTextEdit to fix clear() and setPlainText('').
#!/usr/bin/env python
import sys
from PyQt4 import QtGui
class TestApp(QtGui.QMainWindow):
def __init__(self, filename=None):
super(TestApp, self).__init__()
self._editor = PlainTextEdit()
self._editor.modificationChanged.connect(self._change_modified)
self.setCentralWidget(self._editor)
self._editor.setPlainText('')
def _change_modified(self, have_change):
print(have_change)
class PlainTextEdit(QtGui.QPlainTextEdit):
def clear(self):
self.selectAll()
cursor = self.textCursor()
cursor.removeSelectedText()
doc = self.document()
doc.clearUndoRedoStacks()
doc.setModified(False)
self.modificationChanged.emit(False)
def setPlainText(self, text):
if text:
super(PlainTextEdit, self).setPlainText(text)
else:
self.clear()
if __name__ == '__main__':
a = QtGui.QApplication([])
app = TestApp()
app.show()
sys.exit(a.exec_())
It's a Qt bug, and the straightforward workaround is to check for empty contents if modifications are indicated.

Can't get custom slot working in PyQT4 with QT4 designer

I am new to PyQT4.
After some tuts I decided to make a simple GUI in which I will enter text in first line and on clicking of Reverse button ,it will show reversed string on second line.
I made a custom slot for this,by defining the function in my class.But when I click reverse nothing happens. I have used in-bilt slots for Clear button and Exit button in my GUI and they are working perfectly.
If someone can just clarify this custom slot problem it would help me advance further.
Thanks in advance.
Here's a photo of my GUI
http://img196.imageshack.us/img196/7131/diall.png
Stringreverse.py Final File
import sys
from PyQt4 import QtCore, QtGui
from stringreverse_ui import Ui_Dialog
class MyForm(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui=Ui_Dialog()
self.ui.setupUi(self)
QtCore.QObject.connect(self.ui.pushButton_3,QtCore.SIGNAL("Click()"), self.reverse)
def reverse(self):
s=self.ui.lineEdit_2.text()
self.ui.lineEdit.setText(s[::-1])
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = MyForm()
myapp.show()
sys.exit(app.exec_())enter code here
Try using QtCore.SIGNAL("clicked()") instead of QtCore.SIGNAL("Click()").

PyQt: Trouble with asterisk on modification in QPlainTextEdit

I'm having a problem with a QPlainTextEdit. I want the "contents have been modified" asterisk to appear in the title bar whenever the contents have been modified.
In the example below, type a few letters. The asterisk appears as it should. Hit Ctrl+S, the asterisk disappears as it should. But then if you type a few more letters... why doesn't the asterisk appear again?
import os, sys
from PyQt4 import QtGui, QtCore
class MyTextEdit(QtGui.QPlainTextEdit):
def __init__(self):
QtGui.QPlainTextEdit.__init__(self)
save_seq = QtGui.QKeySequence.Save
self.save_shortcut = QtGui.QShortcut(save_seq, self, self.save)
QtCore.QObject.connect(self,
QtCore.SIGNAL("modificationChanged(bool)"),
self.on_change)
def on_change(self, is_modified):
print "on_change"
window.setWindowModified(is_modified)
def save(self):
window.setWindowModified(False)
#
app = QtGui.QApplication(sys.argv)
window = QtGui.QMainWindow()
edit = MyTextEdit()
window.setCentralWidget(edit)
window.setWindowTitle("None [*]")
window.show()
app.exec_()
Never mind, figured it out. The problem was that in the save method I should've been calling self.document().setModified(False) instead of window.setWindowModified(False)

Categories

Resources