I have a QLineEdit widget and I want to use the double click event on it. How can I do that?
def __init__(self):
#... other codes
self.title = QLineEdit()
self.title.returnPressed.connect(self.lockTitle)
#like this -> 'self.title.doubleClicked.connect(self.unlockTitle)'
#... other codes
def lockTitle(self):
self.title.setDisabled(True)
def unlockTitle(self):
self.title.setDisabled(False)
A possible solution is to create a custom QLineEdit by creating a new signal that is emitted in the mouseDoubleClickEvent method, but the problem in your case is that the QLineEdit is disabled and that method is not invoked so instead of using that method you should use the event method:
class LineEdit(QLineEdit):
doubleClicked = pyqtSignal()
def event(self, event):
if event.type() == QEvent.Type.MouseButtonDblClick:
self.doubleClicked.emit()
return super().event(event)
self.title = LineEdit()
self.title.returnPressed.connect(self.lockTitle)
self.title.doubleClicked.connect(self.unlockTitle)
Related
why overriding keyPressEvent() in QPlainTextEdit,
self.clientDataEdit.keyPressEvent = self.clientKeyPressEvent
stops the signal textChanged() in QPlainTextEdit from triggering
The clientKeyPressEvent() method triggers when keys are pressed but QPlainTextEdit stopped updating and textChanged() signal stopped triggering.
If required, I can try posting code but maybe this is something 'simple'
Short Answer:
Because they are removing the default behavior, and one of them was to emit that signal.
Long Answer:
Do not modify the methods by doing foo.bar = baz especially in the Qt bindings since they keep a cache of the used methods that can cause you these problems.
If you want to modify the behavior of a method without losing the default behavior then create a class that inherits and calls super from the method:
class PlainTextEdit(QPlainTextEdit):
def keyPressEvent(self, event):
super().keyPressEvent(event)
# TODO
In addition, Qt allows you to listen to the events without the need to override the methods using an event filter:
class Helper(QObject):
def __init__(self, widget):
super().__init__(widget)
self._widget = widget
self.widget.installEventFilter(self)
#property
def widget(self):
return self._widget
def eventFilter(self, obj, event):
if self.widget is obj and event.type() == QEvent.KeyPress:
print(event.key(), event.text())
return super().eventFilter(obj, event)
helper = Helper(self.clientDataEdit)
I'm writing a custom TableModel in PyQt5, inheriting from QtCore.QAbstractTableModel. I want my Table to have one column with CheckBoxes only, no text, and one column with a PushButton in each row.
I tried to return a QPushButton object in the data method for the Qt.Display role, but apparently this is not possible.
So my question is: Can I implement in the Model itself that it returns certain widgets for certain cells? In my opinion, that is the job of the model, but how do I achieve this?
My second question would be how I have to assign the slots so that I know from which of the buttons (from which row) the action occurred?
Explanation:
Can I implement in the Model itself that it returns certain widgets for certain cells? In my opinion, that is the job of the model, but how do I achieve this?
It could be that the model provides the widgets but it is not common. In general, the model provides the information that will be displayed through a delegate, and is the delegate that can provide widgets. There is also the alternative of setting widgets on the unlinked view of the model using the setIndexWidget method.
Considering the first case, the solution is to implement a delegate.
how I have to assign the slots so that I know from which of the buttons (from which row) the action occurred?
In general the widgets that are used as editors so you must update the model, and then the model can notify other elements through the dataChanged signal as for example if the user wrote a text or changed the status of a checkbox, but in the case of the clicked not notify a permanent change but temporary. Considering this, the delegate could present a signal.
Solution:
from PyQt5 import QtCore, QtGui, QtWidgets
class PushButtonDelegate(QtWidgets.QStyledItemDelegate):
clicked = QtCore.pyqtSignal(QtCore.QModelIndex)
def paint(self, painter, option, index):
if (
isinstance(self.parent(), QtWidgets.QAbstractItemView)
and self.parent().model() is index.model()
):
self.parent().openPersistentEditor(index)
def createEditor(self, parent, option, index):
button = QtWidgets.QPushButton(parent)
button.clicked.connect(lambda *args, ix=index: self.clicked.emit(ix))
return button
def setEditorData(self, editor, index):
editor.setText(index.data(QtCore.Qt.DisplayRole))
def setModelData(self, editor, model, index):
pass
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = QtWidgets.QTableView()
model = QtGui.QStandardItemModel(0, 2)
for i in range(10):
it1 = QtGui.QStandardItem()
it1.setData(QtCore.Qt.Checked, QtCore.Qt.CheckStateRole)
it1.setFlags(it1.flags() | QtCore.Qt.ItemIsUserCheckable)
it2 = QtGui.QStandardItem()
it2.setData("text-{}".format(i), QtCore.Qt.DisplayRole)
model.appendRow([it1, it2])
# pass the view as parent
delegate = PushButtonDelegate(w)
w.setItemDelegateForColumn(1, delegate)
def on_clicked(index):
print(index.data())
delegate.clicked.connect(on_clicked)
w.setModel(model)
w.show()
sys.exit(app.exec_())
I am looking for a way to create a popup box with a filebrowser inside of it by clicking a button from the main app screen. The below snippet is the class that is called when the upload button is clicked from the main app. It will render the popup with the file browser, but the on_* kwargs do not run the respective methods.
class UploadPopup:
def __init__(self, short_text='heading'):
browser = FileBrowser(select_string='Select', cancel_state='down')
browser.bind(on_success=self._fbrowser_success,
on_canceled=self._fbrowser_canceled,
on_submit=self._fbrowser_submit)
self.popup = Popup(
title=short_text,
content=browser, size_hint=(0.9, 0.9),
auto_dismiss=False
)
self.popup.open()
def _fbrowser_canceled(self, instance):
print('cancelled, Close self.')
self.popup.dismiss()
def _fbrowser_success(self, instance):
print(instance.selection)
self.popup.dismiss()
def _fbrowser_submit(self, instance):
print(instance.selection)
self.popup.open()
Any ideas??
Where ever you are calling UploadPopup(), you need to save a reference to it, so that it does not get garbage collected. For example, you might want to do self.pop = UploadPopup() in your main app.
Also, in your event handling methods, you probably want to replace self.popup.open() with self.popup.dismiss().
I have already accepted an answer, but would like to expand on that a bit. #john-anderson was correct in that garbage collection was collecting the instantiation. I was originally doing this...
class MainScreen(Screen):
...
#staticmethod
def upload(self):
this = UploadPopup()
...
class UploadPopup():
....
see original post
....
In order to resolve this issue I had to instantiate in the init method of my MainScreen class add an open method to the UpdatePopup class and call that method when the button was clicked.
class MainScreen(Screen):
def __init__(self):
self.upload_popup = UploadPopup()
...
#staticmethod
def upload(self):
self.upload_popup.start()
...
class UploadPopup:
def __init__(self, short_text='heading'):
browser = FileBrowser(select_string='Select', cancel_state='down')
browser.bind(on_success=self._fbrowser_success,
on_canceled=self._fbrowser_canceled,
on_submit=self._fbrowser_submit)
self.popup = Popup(
title=short_text,
content=browser, size_hint=(0.9, 0.9),
auto_dismiss=False
)
def start(self):
self.popup.open()
....
I'm tired about looking for the methods to deal with widgets within python class (Python 2.7 & PyQt4) who load file.ui (GUI QTDesigner)
CODE
form_class = uic.loadUiType("MyPythonProgram.ui")[0]
class MyWindowClass(QtGui.QMainWindow, form_class):
def __init__(self, parent = None):
QtGui.QMainWindow.__init__(self, parent)
self.setupUi(self)
self.btn_buscar.clicked.connect(self.buscar)
def addingResultsToQListView(self):
for item in SomeList:
self.listView.addItem(item) ###It's not correct, but cannot find the right one
def onListItemClicked():
getItem = listView.currentItem().text() ###It's not correct, but cannot find the right one
def buscar(self):
getEditText = self.textEdit.toPlainText()
### Don't know how to do this function. I want to get the edittext to search on some website and retrieve the results into a list. then the list will be added to QlistView (just found C++ methods, not for python)
#Finally
getEditText = '' ###After click on 'btn_buscar', want to clear this field
app = QtGui.QApplication(sys.argv)
MyWindow = MyWindowClass(None)
MyWindow.show()
app.exec_()
It could be helper to get some DOC, or some help about making python apps hybrid (Android if its possible), keeping .ui and .py layers separately as I'm trying to show you.
This is my .ui for more information:
QUESTION'
How could I bind python functions with elements on .ui? I was trying too much methods but didn't find the right one. Need to know how to deal with QlistView and Qedittext... Thanks
This is the way I do it: separate the classes between construction (loading) of the UI and changing its content.
form_class = uic.loadUiType("MyPythonProgram.ui")[0]
class MyWindowClass(QtGui.QMainWindow, form_class):
def __init__(self, parent = None):
QtGui.QMainWindow.__init__(self, parent)
self.setupUi(self)
class myGui:
def __init__(self):
self.gui = MyWindowClass() # that's the trick!
# self.addindResultsToQListView() # doesn't work, because I don't have your list items
self.gui.btn_buscar.clicked.connect(self.buscar)
self.editText = None
def show(self):
self.gui.show()
def addingResultsToQListView(self):
for item in SomeList: # you need to specify this `list` before this works!
self.gui.listView.addItems(item)
def buscar(self):
self.editText = self.gui.textEdit.text()
self.gui.textEdit.setText("")
app = QtGui.QApplication(sys.argv)
MyWindow = MyGui()
MyWindow.show()
app.exec_()
The trick is to reference the MyWindowClass, which is the constructor of your gui and hence the GUI itself, as an object within the class that controls the content of your GUI (myGui).
You call myGui on toplevel which then calls MyWindowClass as the object self.gui. From then on, whenever you want to address something in your GUI you name it self.gui. and add the QObject.
I also tried to understand what you want to do for the pushBotton. The content of your TextEdit (in PyQt they are called lineEdit btw) is stored in the variable self.editText which is initialized as None. Afterwards, the lineEdit is cleared from the user content.
Using PyQt4 + QT4.8.4, I'd like to drop (external) textual content to a widget defined as a PyQt4 plugin in QtDesigner
I use two python classes :
widgetlabelplugin.py inherited from QPyDesignerCustomWidgetPlugin
widgetlabel.py inherited from QLabel
Overriding the dropEvent in (widgetlabel.py), I'm able to retrieve "external textual content" and to set _model property.
I do the following steps :
Launch designer by previously setting PYQTDESIGNERPATH to the
.py path
Create a dialog without button
Drop a PyGMT/ WiddgetLabel on the dialog
Drop a "textual content" (from notepad) to the widgetlabel label
-> at this step, the label is updated on the dialog but not on the properties browser on the right
Save Dialog from Qt designer tool bar
-> ui file doesn't contain any "textual content" neither for QLabel/text, nor WidgetLabel/model
In Qt designer, If I select dialog background and reselect WidgetLabel, properties are updated in the browser, they are still not saved if I save the ui !
python class : widgetlabelplugin.py
# A demonstration custom widget plugin for PROJECT Qt Designer.
from PyQt4 import QtGui, QtDesigner
from widgetlabel import WidgetLabel
# This class implements the interface expected by Qt Designer to access the
# custom widget. See the description of the QDesignerCustomWidgetInterface
# class for full details.
class WidgetLabelPlugin(QtDesigner.QPyDesignerCustomWidgetPlugin):
# Initialise the instance.
def __init__(self, parent=None):
super(WidgetLabelPlugin, self).__init__(parent)
self._initialized = False
# Initialise the custom widget for use with the specified formEditor
# interface.
def initialize(self, formEditor):
if self._initialized:
return
self._initialized = True
# Return True if the custom widget has been intialised.
def isInitialized(self):
return self._initialized
# Return a new instance of the custom widget with the given parent.
def createWidget(self, parent):
return WidgetLabel(parent)
# Return the name of the class that implements the custom widget.
def name(self):
return "WidgetLabel"
# Return the name of the group to which the custom widget belongs. A new
# group will be created if it doesn't already exist.
def group(self):
return "PyGMT"
# Return the icon used to represent the custom widget in Designer's widget
# box.
def icon(self):
return QtGui.QIcon(":/designer/frame.png")
# Return a short description of the custom widget used by Designer in a
# tool tip.
def toolTip(self):
return "Satis demonstration widget"
# Return a full description of the custom widget used by Designer in
# "What's This?" help for the widget.
def whatsThis(self):
return "WidgetLabel is a demonstration custom widget written in Python " \
"using PyQt."
# Return True if the custom widget acts as a container for other widgets.
def isContainer(self):
return False
# Return the name of the module containing the class that implements the
# custom widget. It may include a module path.
def includeFile(self):
return "WidgetLabel"
python class : widgetlabel.py
#############################################################################
##
## This file is part of the examples of PROJECT Qt Designer.
##
#############################################################################
from PyQt4 import QtCore, QtGui
# This is the class that implements the custom widget for PROJECT.
class WidgetLabel(QtGui.QLabel):
#model changed signal
modelChanged = QtCore.pyqtSignal(QtCore.QString)
# Initialise the instance.
def __init__(self, parent=None):
super(WidgetLabel, self).__init__(parent)
self.setAcceptDrops(True)
self.setText("Label")
# Initialise the model property.
self._model = None
###########################################################################
# DRAG & DROP PART #
###########################################################################
def dragEnterEvent(self, e):
if e.mimeData().hasFormat("text/plain"):
e.setDropAction(QtCore.Qt.CopyAction)
e.accept()
else:
e.ignore()
def dragMoveEvent(self, event):
if event.mimeData().hasFormat("text/plain"):
event.setDropAction(QtCore.Qt.CopyAction)
event.accept()
else:
event.ignore
def dropEvent(self, e):
e.acceptProposedAction()
bStream = e.mimeData().retrieveData("text/plain",
QtCore.QVariant.ByteArray)
self.setModel(QtCore.QString(str(bStream.toByteArray())))
# The getter for the zoom property.
def getModel(self):
return self._model
# The setter for the model property. We also make define this as a Qt slot
# which can be connected to Qt signals in Qt Designer.
#QtCore.pyqtSlot(QtCore.QString)
def setModel(self, model):
# print "new model", model
# Set QLabel text
self.setText(model)
# Don't do anything if nothing has changed.
if self._model == model:
return
# Remember the new model level.
self._model = model
# Emit the Qt signal to say that the model level has changed.
self.modelChanged.emit(model)
# The resetter for the model property.
def resetModel(self):
self.setModel(None)
# Define the model property. Changing the value of this in Qt Designer's
# property editor causes the model to change dynamically.
model = QtCore.pyqtProperty(QtCore.QString, getModel, setModel, resetModel)
# Display the custom widget if the script is being run directly from the
# command line.
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
demo = WidgetLabel()
demo.show()
sys.exit(app.exec_())