PyQt5 call function when click on QListWidgetItem - python

How can I make sure that the do_something() function is called only when QListWidgetItem "Item 1" is clicked, but not QListWidgetItem "Item 2"?
In the implementation below, do_something() function is called each time I click on either of the items.
from PyQt5.QtWidgets import QApplication, QWidget, QListWidget, QHBoxLayout, QListWidgetItem
import sys
class Window(QWidget):
def __init__(self):
super().__init__()
self.list_widget = QListWidget()
self.layout = QHBoxLayout()
self.layout.addWidget(self.list_widget)
self.list_widget.insertItem(1, QListWidgetItem("Item 1"))
self.list_widget.insertItem(2, QListWidgetItem("Item 2"))
self.list_widget.itemClicked.connect(self.do_something)
self.setLayout(self.layout)
self.show()
def do_something(self):
print("It was clicked on item 1")
App = QApplication(sys.argv)
window = Window()
sys.exit(App.exec())

The solution is to obtain the row of the pressed item and verify that it is 0:
from PyQt5.QtCore import pyqtSlot
# ...
#pyqtSlot("QListWidgetItem*")
def do_something(self, item):
if self.list_widget.row(item) == 0:
print("It was clicked on item 1")

Related

select and highlight the next word from QTextEdit on button click and show in QLabel

The aim is to select and highlight the next word on each click of QPushButton and shown that selected/highlighted word in the QLabel as well.
The minimum working code of my Python pyqt5 gui application is given below along with its output
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow, QTextEdit,QVBoxLayout,QPushButton,QLabel
import lorem
s=lorem.sentence()
p=lorem.paragraph()
t=lorem.text()
class myWindow(QMainWindow):
def __init__(self):
super(myWindow,self).__init__()
self.setWindowTitle('application')
self.setGeometry(200,200,800,600)
self.initUI()
def initUI(self):
# Cannot set QxxLayout directly on the QMainWindow
# Need to create a QWidget and set it as the central widget
widget = QWidget()
layout=QVBoxLayout()
#self.setLayout(layout)
self.textbox=QTextEdit(self)
#self.textbox.setGeometry(20,20,750,520)
self.textbox.setText(t)
layout.addWidget(self.textbox)
self.l1=QLabel(self)
#self.l1.setGeometry(260,560,20,20)
self.l1.setText('highlited word')
self.l1.adjustSize()
layout.addWidget(self.l1)
self.b1=QPushButton('next word',self)
#self.b1.move(460,550)
layout.addWidget(self.b1)
widget.setLayout(layout)
self.setCentralWidget(widget)
def mymain():
app=QApplication(sys.argv)
win=myWindow()
win.show()
sys.exit(app.exec_())
if __name__=='__main__':
mymain()
and the output is
What I would like is: When the QPushButton is clicked, the first word of the text in QTextEdit box is selected and highlited and is also shown on the QLabel, and when the QPushButton is pressed again, the second word is selected/highlighted in QTextEdit box and is shown on the QLabel box, and the process continues.
Note: This is different from 'Find' as I have to go though all words in the text with each click.
Try QTextCursor.movePosition(QTextCursor.NextWord, QTextCursor.KeepAnchor).
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow, QTextEdit,QVBoxLayout,QPushButton,QLabel
import lorem
s=lorem.sentence()
p=lorem.paragraph()
t=lorem.text()
class myWindow(QMainWindow):
def __init__(self):
super(myWindow,self).__init__()
self.setWindowTitle('application')
self.setGeometry(200,200,800,600)
self.initUI()
def initUI(self):
# Cannot set QxxLayout directly on the QMainWindow
# Need to create a QWidget and set it as the central widget
widget = QWidget()
layout=QVBoxLayout()
#self.setLayout(layout)
self.textbox=QTextEdit(self)
#self.textbox.setGeometry(20,20,750,520)
self.textbox.setText(t)
# Move Cursor to Start of the document.
cursor = self.textbox.textCursor()
cursor.movePosition(cursor.Start)
layout.addWidget(self.textbox)
self.l1=QLabel(self)
#self.l1.setGeometry(260,560,20,20)
self.l1.setText('highlited word')
self.l1.adjustSize()
layout.addWidget(self.l1)
self.b1=QPushButton('next word',self)
self.b1.clicked.connect(self.next_word)
#self.b1.move(460,550)
layout.addWidget(self.b1)
widget.setLayout(layout)
self.setCentralWidget(widget)
def next_word(self):
word = self.get_next_word()
while(word in [".", ""]): #Filter
word = self.get_next_word()
self.l1.setText(word)
def get_next_word(self):
cursor = self.textbox.textCursor()
if(cursor.atEnd()):
return "End Of document!"
cursor.clearSelection()
cursor.movePosition(cursor.NextWord, cursor.KeepAnchor)
self.textbox.setTextCursor(cursor)
return cursor.selectedText()
def mymain():
app=QApplication(sys.argv)
win=myWindow()
win.show()
sys.exit(app.exec_())
if __name__=='__main__':
mymain()

Problem integrating QFontComboBox in Qmenu

I'm trying to integrate QFontComboBox within Qmenu.
I try to make two things happen when selecting a particular font from the menu:
The Qmenu will close.
print the selected font.
from PyQt5.QtCore import QObject
from PyQt5.QtGui import QIcon, QFont, QCursor
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QFontComboBox, QWidgetAction, QMenu, QPushButton
class Window(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Pyside2 FontCombo Box")
self.setGeometry(300,200,300,250)
self.setFontBox()
self.setIcon()
self.show()
def setIcon(self):
appIcon = QIcon("icon.png")
self.setWindowIcon(appIcon)
def setFontBox(self):
self.font_button = QPushButton(self)
self.font_button.setFixedWidth(300)
self.font_button.clicked.connect(lambda: self.setFontmenu())
vbox = QVBoxLayout()
vbox.addWidget(self.font_button)
self.setLayout(vbox)
def setFontmenu(self):
font_menu = QMenu()
font_submenu = QFontComboBox()
font_submenu.setCurrentFont(QFont("Arial"))
objectTest = QObject()
widget = QWidgetAction(objectTest)
widget.setDefaultWidget(font_submenu)
font_menu.addAction(widget)
font_menu.exec_(QCursor.pos())
menu = font_menu
menu.addSeparator()
font_submenu.showPopup()
font_submenu.setFocus()
font_submenu.currentFontChanged.connect(self._changed)
def _changed(self):
font = self.currentFont().family()
print(font)
return
myapp = QApplication(sys.argv)
window = Window()
myapp.exec_()
sys.exit()

How to transfer items from QListWidget based in one window to another QListWidget based in another window?

That being said, I would like to be able to transfer my items from QListWidget based in one window to another.
The code below allows me to transfer one item at a time,
but I am struggling to think of a way to transfer multiple items
at one time.
(Code below is from an example I found and have altered.)
from PyQt5.QtWidgets import (
QApplication,
QMainWindow,
QDialog,
QWidget,
QVBoxLayout,
QLineEdit,
QLabel,
QPushButton,
QListWidget,
QAbstractItemView
)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.user_input = QListWidget()
self.user_input.addItem("2")
self.user_input.addItem("3")
self.populate()
self.show()
self.user_input.setSelectionMode(QAbstractItemView.ExtendedSelection)
def populate(self):
widgets = [QLabel("Insert a number"), self.user_input]
centralWidget = self.group_widgets(widgets)
self.setCentralWidget(centralWidget)
def group_widgets(self, widgets):
parentWidget = QWidget()
layout = QVBoxLayout()
for widget in widgets: layout.addWidget(widget)
parentWidget.setLayout(layout)
return parentWidget
def when_input(self, function):
#self.user_input.textChanged.connect(function)
self.user_input.itemClicked.connect(self.printItemText)
self.user_input.itemClicked.connect(function)
def printItemText(self):
items = self.user_input.selectedItems()
x = []
for i in range(len(items)):
x.append(str(self.user_input.selectedItems()[i].text()))
print (x)
class Dialog(QDialog):
def __init__(self):
super().__init__()
self.user_input = QListWidget()
self.relay_sum = None # function to relay result of addition
self.populate()
self.show()
def populate(self):
widgets = self.get_widgets()
layout = self.get_layout(widgets)
self.setLayout(layout)
def get_widgets(self):
widgets = [
QLabel("Inserted number"),
self.user_input,
]
return widgets
def get_layout(self, widgets):
layout = QVBoxLayout()
for widget in widgets: layout.addWidget(widget)
return layout
def main():
app = QApplication([])
mainWindow = MainWindow()
dialog = Dialog()
mainWindow.when_input(lambda text: dialog.user_input.addItem(str(text.text())))
app.exec_()
if __name__ == "__main__":
main()
When an item is clicked it is also selected so just use the last feature.
One possible solution is to create a new token that transports the cloned items from the selected items, and then add it to the other QListWidget.
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import (
QAbstractItemView,
QApplication,
QDialog,
QLabel,
QListWidget,
QMainWindow,
QVBoxLayout,
QWidget,
)
class MainWindow(QMainWindow):
custom_signal = pyqtSignal(list)
def __init__(self):
super().__init__()
self.user_input = QListWidget(selectionMode=QAbstractItemView.ExtendedSelection)
self.user_input.addItem("2")
self.user_input.addItem("3")
self.populate()
self.user_input.itemSelectionChanged.connect(self.handle_selection_changed)
def populate(self):
widgets = [QLabel("Insert a number"), self.user_input]
centralWidget = self.group_widgets(widgets)
self.setCentralWidget(centralWidget)
def group_widgets(self, widgets):
parentWidget = QWidget()
layout = QVBoxLayout(parentWidget)
for widget in widgets:
layout.addWidget(widget)
return parentWidget
def handle_selection_changed(self):
items = []
for item in self.user_input.selectedItems():
items.append(item.clone())
self.custom_signal.emit(items)
class Dialog(QDialog):
def __init__(self):
super().__init__()
self.user_input = QListWidget()
self.populate()
def populate(self):
widgets = self.get_widgets()
layout = self.get_layout(widgets)
self.setLayout(layout)
def get_widgets(self):
widgets = [
QLabel("Inserted number"),
self.user_input,
]
return widgets
def get_layout(self, widgets):
layout = QVBoxLayout()
for widget in widgets:
layout.addWidget(widget)
return layout
def add_items(self, items):
for item in items:
self.user_input.addItem(item)
def main():
app = QApplication([])
mainWindow = MainWindow()
mainWindow.show()
dialog = Dialog()
dialog.show()
mainWindow.custom_signal.connect(dialog.add_items)
app.exec_()
if __name__ == "__main__":
main()

What is the signal for user clicks the down arrow on the QComboBox?

I need to execute a method whenever the user clicks the down arrow on the combo box. I've tried the signals listed in the documentations but none of the worked.
from PyQt5.QtWidgets import *
import sys
class Window(QWidget):
def __init__(self):
super().__init__()
self.combo = QComboBox(self)
self.combo.signal.connect(self.mymethod)
self.show()
def mymethod(self):
print('hello world')
app = QApplication(sys.argv)
win = Window()
sys.exit(app.exec_())
There is no signal that is emitted when the down arrow is pressed but you can create override the mousePressEvent method and verify that this element was pressed:
import sys
from PyQt5.QtCore import pyqtSignal, Qt
from PyQt5.QtWidgets import (
QApplication,
QComboBox,
QStyle,
QStyleOptionComboBox,
QVBoxLayout,
QWidget,
)
class ComboBox(QComboBox):
arrowClicked = pyqtSignal()
def mousePressEvent(self, event):
super().mousePressEvent(event)
opt = QStyleOptionComboBox()
self.initStyleOption(opt)
sc = self.style().hitTestComplexControl(
QStyle.CC_ComboBox, opt, event.pos(), self
)
if sc == QStyle.SC_ComboBoxArrow:
self.arrowClicked.emit()
class Window(QWidget):
def __init__(self):
super().__init__()
self.combo = ComboBox()
self.combo.arrowClicked.connect(self.mymethod)
lay = QVBoxLayout(self)
lay.addWidget(self.combo)
lay.setAlignment(Qt.AlignTop)
def mymethod(self):
print("hello world")
if __name__ == "__main__":
app = QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec_())

How to use key press events in PyQt5

I want the "Add" function to run when I input a number into "LE1" and press the "Enter" key on the keyboard. I also want the line edit to clear its text when I select it for editing.
from PyQt5 import QtWidgets, QtCore
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QLineEdit, QLabel, QGridLayout, QWidget, QDialog
class MyWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MyWindow, self).__init__()
centralWidget = QWidget()
self.setCentralWidget(centralWidget)
self.Glayout = QGridLayout(centralWidget)
self.LE1 = QLineEdit('Input Number',self)
self.LE1.keyPressEvent(self.KPE)
Label1 = QLabel('+ 1 =',self)
self.LE2 = QLineEdit(self)
self.Glayout.addWidget(self.LE1)
self.Glayout.addWidget(Label1)
self.Glayout.addWidget(self.LE2)
def Add(self):
Num = float(self.LE1.text())
math = Num + 1
ans = str(math)
self.LE2.setText(ans)
def KPE(self):
if event.key() == Qt.Key_Enter:
self.Add()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec_())
keyPressEvent is a method that if you override it that way you are losing the default behavior, besides it is unnecessary since QLineEdit has the returnPressed signal that notifies if Enter is pressed.
On the other hand, converting a string to floating can throw an exception so you should prevent that case, another better option is to use a widget that allows only numerical values with QSpinBox or QDoubleSpinBox, or at least restrict the values that are entered into the QLineEdit with a QValidator appropriate.
And finally do not use the word math as a variable name since that is the name of a library that could cause you problems in the future.
Considering the above, the solution is:
from PyQt5.QtWidgets import (
QApplication,
QGridLayout,
QLineEdit,
QLabel,
QMainWindow,
QWidget,
)
class MyWindow(QMainWindow):
def __init__(self, parent=None):
super(MyWindow, self).__init__(parent)
self.LE1 = QLineEdit("Input Number")
self.LE1.returnPressed.connect(self.add)
Label1 = QLabel("+ 1 =")
self.LE2 = QLineEdit()
centralWidget = QWidget()
self.setCentralWidget(centralWidget)
layout = QGridLayout(centralWidget)
layout.addWidget(self.LE1)
layout.addWidget(Label1)
layout.addWidget(self.LE2)
def add(self):
try:
num = float(self.LE1.text())
num += 1
self.LE2.setText(str(num))
except ValueError:
pass
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec_())

Categories

Resources