Make QGroupBox selectable and clickable - python

I have the following toy interface:
from PyQt5 import QtWidgets, QtGui, QtCore
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
w = QtWidgets.QWidget()
layout = QtWidgets.QVBoxLayout()
w.setLayout(layout)
self.setCentralWidget(w)
my_tree = QtWidgets.QTreeWidget()
layout.addWidget(my_tree)
alpha = QtWidgets.QTreeWidgetItem(my_tree, ['Alpha'])
beta = QtWidgets.QTreeWidgetItem(my_tree, ['Beta'])
alpha.addChild(QtWidgets.QTreeWidgetItem(['one']))
alpha.addChild(QtWidgets.QTreeWidgetItem(['two']))
beta.addChild(QtWidgets.QTreeWidgetItem(['first']))
beta.addChild(QtWidgets.QTreeWidgetItem(['second']))
my_tree.expandAll()
alpha.child(0).setSelected(True)
scroll = QtWidgets.QScrollArea()
layout.addWidget(scroll)
scrollLayout = QtWidgets.QVBoxLayout()
scrollW = QtWidgets.QWidget()
scroll.setWidget(scrollW)
scrollW.setLayout(scrollLayout)
scrollLayout.setAlignment(QtCore.Qt.AlignTop)
scroll.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
scroll.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
scroll.setWidgetResizable(True)
for _ in range(5):
fooGroup = QtWidgets.QGroupBox()
fooLayout = QtWidgets.QVBoxLayout()
fooGroup.setLayout(fooLayout)
fooItem1 = QtWidgets.QLabel("fooItem1")
fooItem2 = QtWidgets.QLabel("fooItem2")
fooItem3 = QtWidgets.QLabel("fooItem3")
fooLayout.addWidget(fooItem1)
fooLayout.addWidget(fooItem2)
fooLayout.addWidget(fooItem3)
scrollLayout.addWidget(fooGroup)
self.show()
app = QtWidgets.QApplication([])
window = MainWindow()
app.exec_()
How can I make each group in the scroll area selectable and clickable by the user?
I have so far tried to add the following code in the loop:
def onFooGroupClick():
print("Group")
fooGroup.clicked.connect(onFooGroupClick)
and (as per this post):
def onFooGroupClick():
print("Group")
def f():
return onFooGroupClick()
fooGroup.mousePressEvent = f()
However, all my efforts have been unsuccessful and I cannot seem to be able to make it work.

Create a class that inherits from QGroupBox.
Define the clicked signal in it and override the mousePressEvent method.
from PyQt5 import QtWidgets, QtGui, QtCore
class GroupBox(QtWidgets.QGroupBox): # +++ !!!
clicked = QtCore.pyqtSignal(str, object) # +++
def __init__(self, title):
super(GroupBox, self).__init__()
self.title = title
self.setTitle(self.title)
def mousePressEvent(self, event):
child = self.childAt(event.pos())
if not child:
child = self
self.clicked.emit(self.title, child) # +++
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
w = QtWidgets.QWidget()
layout = QtWidgets.QVBoxLayout()
w.setLayout(layout)
self.setCentralWidget(w)
my_tree = QtWidgets.QTreeWidget()
layout.addWidget(my_tree)
alpha = QtWidgets.QTreeWidgetItem(my_tree, ['Alpha'])
beta = QtWidgets.QTreeWidgetItem(my_tree, ['Beta'])
alpha.addChild(QtWidgets.QTreeWidgetItem(['one']))
alpha.addChild(QtWidgets.QTreeWidgetItem(['two']))
beta.addChild(QtWidgets.QTreeWidgetItem(['first']))
beta.addChild(QtWidgets.QTreeWidgetItem(['second']))
my_tree.expandAll()
alpha.child(0).setSelected(True)
scroll = QtWidgets.QScrollArea()
layout.addWidget(scroll)
scrollLayout = QtWidgets.QVBoxLayout()
scrollW = QtWidgets.QWidget()
scroll.setWidget(scrollW)
scrollW.setLayout(scrollLayout)
scrollLayout.setAlignment(QtCore.Qt.AlignTop)
scroll.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
scroll.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
scroll.setWidgetResizable(True)
for _ in range(5):
fooGroup = GroupBox(f'GroupBox_{_}') # - QtWidgets.QGroupBox()
fooGroup.setObjectName(f'fooGroup {_}')
fooGroup.clicked.connect(self.onFooGroupClick) # +++
fooLayout = QtWidgets.QVBoxLayout()
fooGroup.setLayout(fooLayout)
fooItem1 = QtWidgets.QLabel("fooItem1", objectName="fooItem1")
fooItem1.setStyleSheet('background: #44ffff')
fooItem2 = QtWidgets.QLabel("fooItem2", objectName="fooItem2")
fooItem2.setStyleSheet('background: #ffff56;')
fooItem3 = QtWidgets.QLabel("fooItem3", objectName="fooItem3")
fooItem3.setStyleSheet('background: #ff42ff;')
fooLayout.addWidget(fooItem1)
fooLayout.addWidget(fooItem2)
fooLayout.addWidget(fooItem3)
scrollLayout.addWidget(fooGroup)
def onFooGroupClick(self, title, obj): # +++
print(f"Group: {title}; objectName=`{obj.objectName()}`")
if __name__ == '__main__':
app = QtWidgets.QApplication([])
window = MainWindow()
window.show()
app.exec_()

Related

Change QLabelText as QLineEdit text changes

There is this QLineEdit with setText is set to a predefined value and there is a QDialog with QLabel in it which is supposed to show whatever is in the QLineEdit. The code below shows the situation.
import sys
import os
import datetime
from PySide2.QtWidgets import *
from PySide2 import *
now = datetime.datetime.now()
now_str = now.strftime("%H.%M.%S,%d/%m/%y")
default_text = (str("Sugar_" + now_str))
class MainWindow(QWidget):
def __init__(self):
super(MainWindow, self).__init__()
self.resize(600, 500)
btn = QPushButton("show dialog")
mw_layout = QVBoxLayout()
mw_layout.addWidget(btn)
self.setLayout(mw_layout)
btn.clicked.connect(show_d)
class dialog(QDialog):
def __init__(self):
super(dialog, self).__init__()
self.resize(400, 350)
title = QLineEdit()
title.setText(default_text)
show_title = QPushButton("Show title")
cancel = QPushButton("Cancel")
d_layout = QVBoxLayout()
d_layout.addWidget(title)
d_layout.addWidget(show_title)
d_layout.addWidget(cancel)
self.setLayout(d_layout)
t = title.text()
title_dialog = QDialog()
label = QLabel()
label.setText("The title is " + title.text())
ok = QPushButton("OK!")
t_layout = QVBoxLayout()
t_layout.addWidget(label)
t_layout.addWidget(ok)
title_dialog.setLayout(t_layout)
def show_t():
title_dialog.exec_()
title_dialog.setModal(True)
def close_t():
title_dialog.accept()
show_title.clicked.connect(show_t)
ok.clicked.connect(close_t)
cancel.clicked.connect(self.close_d)
def close_d(self):
self.reject()
def show_d():
d = dialog()
d.exec_()
d.setModal(True)
if __name__ == '__main__':
app = QApplication(sys.argv)
MainWindow = MainWindow()
MainWindow.show()
sys.exit(app.exec_())
But this doesn't work like I expected it to. The QLabel text just show the default text even when the text in QLineEdit is changed.
The console also shows the following error;
qt.xkb.compose: failed to create compose table.
I think there is something's obviously wrong but I can't seem to find what.
Any help appreciated.
You must update the text before a certain event, for example an instant before displaying the dialog:
class dialog(QDialog):
def __init__(self):
super(dialog, self).__init__()
self.resize(400, 350)
self.title_lineedit = QLineEdit(default_text)
show_title = QPushButton("Show title")
cancel = QPushButton("Cancel")
d_layout = QVBoxLayout(self)
d_layout.addWidget(self.title_lineedit)
d_layout.addWidget(show_title)
d_layout.addWidget(cancel)
self.title_dialog = QDialog()
self._title_label = QLabel()
ok = QPushButton("OK!")
t_layout = QVBoxLayout(self.title_dialog)
t_layout.addWidget(self._title_label)
t_layout.addWidget(ok)
show_title.clicked.connect(self.on_clicked)
ok.clicked.connect(self.title_dialog.reject)
cancel.clicked.connect(self.reject)
self.update_label()
def update_label(self):
self._title_label.setText("The title is " + self.title_lineedit.text())
def on_clicked(self):
self.update_label()
self.title_dialog.exec_()

Display a dialog within the main window

The code below creates an empty dialog when Hello! is pressed:
from PyQt5 import QtWidgets, QtCore
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
w = QtWidgets.QWidget()
layout = QtWidgets.QVBoxLayout()
w.setLayout(layout)
self.setCentralWidget(w)
toyButton = QtWidgets.QPushButton("Hello!")
layout.addWidget(toyButton)
toyButton.clicked.connect(self.showdialog)
def showdialog(self):
d = QtWidgets.QDialog()
d.setWindowTitle("Dialog")
d.setWindowModality(QtCore.Qt.WindowModal)
d.exec_()
if __name__ == '__main__':
app = QtWidgets.QApplication([])
window = MainWindow()
window.show()
app.exec_()
How can I force the dialog to appear within the main window instead of having it floating around as an independent window?
You simply need to give the dialog a parent widget: d = QtWidgets.QDialog(self.centralWidget()). self is also a valid parent; pick your favorite!
You could also add d to the layout: self.centralWidget().layout().addWidget(d);
although this second one does not respect your modality+exec.
Here's the full code comparing both methods:
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
w = QtWidgets.QWidget()
layout = QtWidgets.QVBoxLayout()
w.setLayout(layout)
self.setCentralWidget(w)
toyButton = QtWidgets.QPushButton("Hello!")
layout.addWidget(toyButton)
toyButton.clicked.connect(self.showdialog)
toyButton2 = QtWidgets.QPushButton("Hello2!")
layout.addWidget(toyButton2)
toyButton2.clicked.connect(self.showdialog2)
def showdialog(self):
d = QtWidgets.QDialog(self.centralWidget())
d.setWindowTitle("Dialog")
d.setWindowModality(QtCore.Qt.WindowModal)
d.exec_()
def showdialog2(self):
d = QtWidgets.QDialog()
d.setWindowTitle("Dialog2") # window title won't be seen...
d.setWindowModality(QtCore.Qt.WindowModal)
QtWidgets.QPushButton('Dialog2', parent=d) # ... so we add a little something
self.centralWidget().layout().addWidget(d)
d.exec_()

How can i add push button to each and every item of the list view

Here is my sample code,i want to add a push button to each and every row of the list view.I am not found any method to set the widget to model.Can any one please help me how to add widget for each and every row of the list view.Thank you in advance.
Given below is my code:
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class MyCustomWidget(QWidget):
def __init__(self,parent=None):
super(MyCustomWidget, self).__init__(parent)
self.row = QHBoxLayout()
self.row.addWidget(QPushButton("add"))
self.setLayout(self.row)
class Dialog(QtGui.QDialog):
def __init__(self, parent=None):
super(Dialog, self).__init__(parent=parent)
vLayout = QtGui.QVBoxLayout(self)
hLayout = QtGui.QHBoxLayout()
self.lineEdit = QtGui.QLineEdit()
hLayout.addWidget(self.lineEdit)
self.filter = QtGui.QPushButton("filter", self)
hLayout.addWidget(self.filter)
self.list = QtGui.QListView(self)
vLayout.addLayout(hLayout)
vLayout.addWidget(self.list)
self.model = QtGui.QStandardItemModel(self.list)
codes = [
'windows',
'windows xp',
'windows7',
'hai',
'habit',
'hack',
'good'
]
self.list.setModel(self.model)
for code in codes:
item = QtGui.QStandardItem(code)
self.model.appendRow(item)
self.list.setIndexWidget(item.index(), QtGui.QPushButton("button"))
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
w = Dialog()
w.show()
sys.exit(app.exec_())
You have to create a custom widget where you must set the button on the right side with a layout.
import sys
from PyQt4 import QtCore, QtGui
class CustomWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(CustomWidget, self).__init__(parent)
self.button = QtGui.QPushButton("button")
lay = QtGui.QHBoxLayout(self)
lay.addWidget(self.button, alignment=QtCore.Qt.AlignRight)
lay.setContentsMargins(0, 0, 0, 0)
class Dialog(QtGui.QDialog):
def __init__(self, parent=None):
super(Dialog, self).__init__(parent=parent)
vLayout = QtGui.QVBoxLayout(self)
hLayout = QtGui.QHBoxLayout()
self.lineEdit = QtGui.QLineEdit()
hLayout.addWidget(self.lineEdit)
self.filter = QtGui.QPushButton("filter", self)
hLayout.addWidget(self.filter)
self.list = QtGui.QListView(self)
vLayout.addLayout(hLayout)
vLayout.addWidget(self.list)
self.model = QtGui.QStandardItemModel(self.list)
codes = [
'windows',
'windows xp',
'windows7',
'hai',
'habit',
'hack',
'good'
]
self.list.setModel(self.model)
for code in codes:
item = QtGui.QStandardItem(code)
self.model.appendRow(item)
self.list.setIndexWidget(item.index(), CustomWidget())
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
w = Dialog()
w.show()
sys.exit(app.exec_())

show groupbox inside window (not in new window) PyQt5

My code show GroupBox in new window. how to return it to inside main windoow?
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class Window(QtWidgets.QMainWindow, QtWidgets.QDialog):
def __init__(self):
super(Window, self).__init__()
V = app.desktop().screenGeometry()
h = V.height()
w = V.width()
x = 1000
y = 600
self.setGeometry(h/4, w/20, x, y)
self.setFixedSize(x, y)
self.setWindowTitle('Main Window')
self.home()
def home(self):
Window.tools_in_home(self)
self.show()
def tools_in_home(self):
self.groupBox = QtWidgets.QGroupBox('GroupBox')
self.groupBox.move(150, 50)
self.groupBox.resize(800, 400)
hBoxLayout = QtWidgets.QHBoxLayout()
button1 = QtWidgets.QPushButton('Test', self)
hBoxLayout.addWidget(button1)
self.groupBox.setLayout(hBoxLayout)
vBox = QtWidgets.QVBoxLayout()
vBox.addWidget(self.groupBox)
self.setLayout(vBox)
self.groupBox.show()
def run():
global app
app = QtWidgets.QApplication(sys.argv)
GUI = Window()
sys.exit(app.exec_())
run()
Try it:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class Window(QtWidgets.QMainWindow): #, QtWidgets.QDialog):
def __init__(self):
super(Window, self).__init__()
# +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
centralWidget = QtWidgets.QWidget()
self.setCentralWidget(centralWidget)
self.grid = QtWidgets.QGridLayout(centralWidget)
# +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
V = QtWidgets.QApplication.desktop().screenGeometry()
h = V.height()
w = V.width()
x = 1000
y = 600
self.setGeometry(h/4, w/20, x, y)
self.setFixedSize(x, y)
self.setWindowTitle('Main Window')
self.home()
def home(self):
# Window.tools_in_home(self)
self.tools_in_home()
self.show()
def tools_in_home(self):
self.groupBox = QtWidgets.QGroupBox('GroupBox')
self.groupBox.move(150, 50)
self.groupBox.resize(800, 400)
hBoxLayout = QtWidgets.QHBoxLayout()
button1 = QtWidgets.QPushButton('Test', self)
hBoxLayout.addWidget(button1)
self.groupBox.setLayout(hBoxLayout)
# vBox = QtWidgets.QVBoxLayout()
# vBox.addWidget(self.groupBox)
self.grid.addWidget(self.groupBox) # +++
# self.setLayout(vBox)
# self.groupBox.show()
def run():
# global app
app = QtWidgets.QApplication(sys.argv)
GUI = Window()
sys.exit(app.exec_())
run()

QListWidget items disappear in icon view mode when resizing window

Why do my listwidget items disappear sometimes when i resize the dialog?
Before:
After:
import os, sys, json
sys.path.append('Z:\\pipeline\\site-packages')
from PySide import QtGui, QtCore, QtSvg
################################################################################
# Custom Widgets
################################################################################
class LayerWidget(QtGui.QWidget):
def __init__(self):
super(LayerWidget, self).__init__()
# controls
self.ui_thumbnail = QtGui.QToolButton()
self.ui_thumbnail.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)
self.ui_thumbnail.setFixedSize(128,128)
self.ui_thumbnail.setIconSize(QtCore.QSize(80,80))
self.ui_thumbnail.setText('TITLE HERE')
self.ui_profiles = QtGui.QComboBox()
self.ui_profiles.addItems(['Item 1','Item 2','Item 3'])
# layout
main_layout = QtGui.QVBoxLayout()
main_layout.setContentsMargins(0,0,0,0)
main_layout.setSpacing(0)
main_layout.addWidget(self.ui_thumbnail)
main_layout.addWidget(self.ui_profiles)
main_layout.addStretch()
self.setLayout(main_layout)
class LayerManager(QtGui.QWidget):
def __init__(self):
super(LayerManager, self).__init__()
self.resize(400, 500)
self.ui_layers = QtGui.QListWidget()
self.ui_layers.setViewMode(QtGui.QListWidget.IconMode)
self.ui_layers.setResizeMode(QtGui.QListWidget.Adjust)
self.ui_layers.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
self.ui_layers.setMovement(QtGui.QListView.Static)
self.ui_layers.setIconSize(QtCore.QSize(96,96))
self.ui_layers.setSpacing(10)
main_layout = QtGui.QVBoxLayout(self)
main_layout.addWidget(self.ui_layers)
def add_new_layers(self):
for x in range(4):
widget = LayerWidget()
item = QtGui.QListWidgetItem()
self.ui_layers.insertItem(self.ui_layers.count(), item)
self.ui_layers.setItemWidget(item, widget)
item.setSizeHint(widget.sizeHint())
################################################################################
# Main Window
################################################################################
class MainWindow(QtGui.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setWindowTitle('Hyv')
self.resize(500, 500)
self.ui_layerManager = LayerManager()
self.setCentralWidget(self.ui_layerManager)
self.ui_layerManager.add_new_layers()
################################################################################
# Launch Methods
################################################################################
def main():
app = QtGui.QApplication(sys.argv)
ex = MainWindow()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()

Categories