Is it possible to run a custom method on clicking the ClearButton in a QLineEdit?
For instance i have a ClearButton inside a QCombobox and i want to set a default-index on clicking the ClearButton in this ComboBox.
I have already tried to subclass the 'clear()' slot of the QLineEdit, but without success.
qtawesome
import sys
from PyQt5.QtWidgets import (QLineEdit, QApplication, QWidget, QVBoxLayout)
import qtawesome as qt
class Widget(QWidget):
def __init__(self, parent=None):
super(QWidget, self).__init__(parent)
self.flag = 0
self.layout = QVBoxLayout()
self.line_edit = QLineEdit()
self.line_edit.setClearButtonEnabled(False)
self.line_edit.textChanged.connect(self._on_line_edit_text_changed)
self.clear_icon = qt.icon('mdi.delete-circle-outline', color='gray', color_active='black')
self.clear_action = None
self.layout.addWidget(self.line_edit)
self.setLayout(self.layout)
def _on_line_edit_text_changed(self):
if self.line_edit and self.line_edit.text():
if not self.clear_action:
self.clear_action = self.line_edit.addAction(self.clear_icon, QLineEdit.TrailingPosition)
self.clear_action.triggered.connect(self._on_clear_clicked)
elif self.clear_action and self.line_edit and not self.line_edit.text():
self.line_edit.removeAction(self.clear_action)
self.clear_action = None
def _on_clear_clicked(self):
self.line_edit.clear()
if __name__ == "__main__":
app = QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
Related
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()
I have the following test script.
from PyQt5.QtWidgets import *
import sys
class MW(QMainWindow):
def __init__(self):
super(MW, self).__init__()
widget = QWidget()
widget.setStyleSheet('QWidget {background-color:#000000; color:#FFFFFF}'
"QPushButton:hover {background-color:#202020}")
self.setCentralWidget(widget)
box = QVBoxLayout(widget)
but1_box = QHBoxLayout()
but1 = QPushButton("Button 1")
lab1 = QLabel("Label 1")
but1_box.addWidget(but1)
but1_box.addWidget(lab1)
box.addLayout(but1_box)
but2_box = QHBoxLayout()
but2 = QPushButton("Button 2")
lab2 = QLabel("Label 2")
but2_box.addWidget(but2)
but2_box.addWidget(lab2)
box.addLayout(but2_box)
self.show()
app = QApplication(sys.argv)
mw = MW()
sys.exit(app.exec_())
If I hover over the PushButton it changes its color to a gray and I want that the associated Label changes its color while hovering over the button.
It is not possible to implement directly using the pseudo-states of the Qt Style Sheet but you will have to use an eventFilter that detects the changes of the hover (enter and leave) and that modifies the stylesheet of the other elements
from PyQt5.QtCore import pyqtSignal, QEvent, QObject
from PyQt5.QtWidgets import (
QApplication,
QHBoxLayout,
QLabel,
QMainWindow,
QPushButton,
QVBoxLayout,
QWidget,
)
import sys
class HoverListener(QObject):
entered = pyqtSignal()
leaved = pyqtSignal()
def __init__(self, widget):
super(HoverListener, self).__init__(widget)
self._widget = widget
self.widget.installEventFilter(self)
#property
def widget(self):
return self._widget
def eventFilter(self, obj, event):
if obj == self.widget:
if event.type() == QEvent.Enter:
self.entered.emit()
elif event.type() == QEvent.Leave:
self.leaved.emit()
return super(HoverListener, self).eventFilter(obj, event)
class MW(QMainWindow):
def __init__(self):
super(MW, self).__init__()
widget = QWidget()
widget.setStyleSheet(
"QWidget {background-color:#000000; color:#FFFFFF}"
"QPushButton:hover {background-color:#202020}"
)
self.setCentralWidget(widget)
but1 = QPushButton("Button 1")
lab1 = QLabel("Label 1")
hover_listener1 = HoverListener(but1)
hover_listener1.entered.connect(
lambda label=lab1: label.setStyleSheet("background-color:#202020")
)
hover_listener1.leaved.connect(lambda label=lab1: label.setStyleSheet(""))
but2 = QPushButton("Button 2")
lab2 = QLabel("Label 2")
hover_listener2 = HoverListener(but2)
hover_listener2.entered.connect(
lambda label=lab2: label.setStyleSheet("background-color:#202020")
)
hover_listener2.leaved.connect(lambda label=lab2: label.setStyleSheet(""))
box = QVBoxLayout(widget)
but1_box = QHBoxLayout()
but1_box.addWidget(but1)
but1_box.addWidget(lab1)
box.addLayout(but1_box)
but2_box = QHBoxLayout()
but2_box.addWidget(but2)
but2_box.addWidget(lab2)
box.addLayout(but2_box)
self.show()
app = QApplication(sys.argv)
mw = MW()
sys.exit(app.exec_())
I've seen a number of replies on SO regarding this matter but not specifically to QMenu and QToolButton. Would appreciate some pointers on aligning the popup widget to the right side of the button. Here's a basic code I'm working off..
import sys
from PyQt5.QtWidgets import *
class test(QWidget):
def __init__(self):
super().__init__()
self.resize(200, 100)
layout = QHBoxLayout(self)
label = QLabel('Testing QToolButton Popup')
toolbutton = QToolButton()
toolbutton.setPopupMode(QToolButton.InstantPopup)
widget = QWidget()
widgetLayout = QHBoxLayout(widget)
widgetLabel = QLabel('Popup Text')
widgetSpinbox = QSpinBox()
widgetLayout.addWidget(widgetLabel)
widgetLayout.addWidget(widgetSpinbox)
widgetAction = QWidgetAction(toolbutton)
widgetAction.setDefaultWidget(widget)
widgetMenu = QMenu(toolbutton)
widgetMenu.addAction(widgetAction)
toolbutton.setMenu(widgetMenu)
layout.addWidget(label)
layout.addWidget(toolbutton)
if __name__ == '__main__':
app = QApplication(sys.argv)
win = test()
win.show()
sys.exit(app.exec_())
The outcome looks like this:
The Qt developer thought the default position was correct, so if you want to modify the alignment you must move the QMenu as I show below:
import sys
from PyQt5.QtCore import QPoint
from PyQt5.QtWidgets import (
QApplication,
QHBoxLayout,
QLabel,
QMenu,
QSpinBox,
QToolButton,
QWidgetAction,
QWidget,
)
class Menu(QMenu):
def showEvent(self, event):
if self.isVisible():
button = self.parentWidget()
if button is not None:
pos = button.mapToGlobal(button.rect().bottomRight())
self.move(pos - self.rect().topRight())
super().showEvent(event)
class Test(QWidget):
def __init__(self):
super().__init__()
self.resize(200, 100)
layout = QHBoxLayout(self)
label = QLabel("Testing QToolButton Popup")
toolbutton = QToolButton(popupMode=QToolButton.InstantPopup)
widgetLabel = QLabel("Popup Text")
widgetSpinbox = QSpinBox()
widget = QWidget()
widgetLayout = QHBoxLayout(widget)
widgetLayout.addWidget(widgetLabel)
widgetLayout.addWidget(widgetSpinbox)
widgetAction = QWidgetAction(toolbutton)
widgetAction.setDefaultWidget(widget)
widgetMenu = Menu(toolbutton)
widgetMenu.addAction(widgetAction)
toolbutton.setMenu(widgetMenu)
layout.addWidget(label)
layout.addWidget(toolbutton)
if __name__ == "__main__":
app = QApplication(sys.argv)
win = Test()
win.show()
sys.exit(app.exec_())
This question already has an answer here:
How to open a window with a click of a button from another window using PyQt?
(1 answer)
Closed 3 years ago.
I want to create a new window when a button is clicked. I will later have windows be created dynamically depending on inputted data. But I want to start simple first.
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QPushButton, QGridLayout, QWidget
class MyWindow(QtWidgets.QMainWindow, QPushButton):
def __init__(self):
super(MyWindow, self).__init__()
centralWidget = QWidget()
self.setCentralWidget(centralWidget)
self.setWindowTitle("ASSET")
self.Button = QPushButton('Action',self)
self.Button.clicked.connect(self.Action)
self.layout = QGridLayout(centralWidget)
self.layout.addWidget(self.Button)
def Action(self):
pass
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec_())
You can create another QMainWindow() and when the button is clicked, activate the show() method
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QPushButton, QGridLayout, QWidget, QLabel
class NewWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(NewWindow, self).__init__(parent)
self.label = QLabel('New Window!')
centralWidget = QWidget()
self.setCentralWidget(centralWidget)
self.layout = QGridLayout(centralWidget)
self.layout.addWidget(self.label)
class MyWindow(QtWidgets.QMainWindow, QPushButton):
def __init__(self):
super(MyWindow, self).__init__()
centralWidget = QWidget()
self.setCentralWidget(centralWidget)
self.setWindowTitle("ASSET")
self.Button = QPushButton('Action',self)
self.Button.clicked.connect(self.Action)
self.layout = QGridLayout(centralWidget)
self.layout.addWidget(self.Button)
self.new_window = NewWindow(self)
def Action(self):
self.new_window.show()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec_())
I just need to know if I can make a slot or signal between a pushbutton and specific page in tabwidget or no !?
If yes then how?
I divide a tab widget into 4 pages. My ask is about if I can make a slot or signal between pushbutton in first page and second page or not.
Try it:
from PyQt5.QtWidgets import (QWidget, QApplication, QTabWidget, QLabel, QPushButton,
QVBoxLayout, QMenuBar, QAction)
class MainWidget(QWidget):
def __init__(self, textLabel, *args, **kwargs):
super(MainWidget, self).__init__(*args, **kwargs)
layout = QVBoxLayout(self)
self.label = QLabel(textLabel, self)
self.btn = QPushButton('Next', self)
layout.addWidget(self.label)
layout.addWidget(self.btn)
class Window(QWidget):
def __init__(self):
super().__init__()
bar = QMenuBar(self)
menu = bar.addMenu('File')
action = QAction('Close activ tab', self)
menu.addAction(action)
action.triggered.connect(self.closeActivTab)
self.tabwdg = QTabWidget()
self.tabwdg.setTabsClosable(True)
self.tabWidget = MainWidget('this is the first page')
self.tabwdg.addTab(self.tabWidget, 'first')
self.tabWidget.btn.clicked.connect(self.numTab)
self.tabWidget = MainWidget('this is the second page')
self.tabwdg.addTab(self.tabWidget, 'second')
self.tabWidget.btn.clicked.connect(self.numTab)
self.tabWidget = MainWidget('this is the third page')
self.tabwdg.addTab(self.tabWidget, 'third')
self.tabWidget.btn.clicked.connect(self.numTab)
self.tabWidget = MainWidget('this is the fourth page')
self.tabwdg.addTab(self.tabWidget, 'fourth')
self.tabWidget.btn.clicked.connect(self.numTab)
self.tabwdg.tabCloseRequested.connect(self.closeTab)
box = QVBoxLayout()
box.addWidget(bar)
box.addWidget(self.tabwdg)
self.setLayout(box)
def numTab(self):
nextTab = self.tabwdg.currentIndex()+1
if nextTab == self.tabwdg.count():
nextTab = 0
self.tabwdg.setCurrentIndex(nextTab)
self.tabwdg.setCurrentWidget(self.tabwdg.currentWidget())
def closeActivTab(self):
activ_tab_ind = self.tabwdg.currentIndex()
self.closeTab(activ_tab_ind)
def closeTab(self, ind):
self.tabwdg.removeTab(ind)
if __name__ == '__main__':
import sys
app = QApplication([''])
w = Window()
w.resize(400, 300)
w.show()
sys.exit(app.exec_())