Get state from QCheckBox inside QTableWidget cell - python

I want to get a state from QCheckBox inside QTableWidget cell.
I've made example code for this issue.
import sys
from PyQt5.QtCore import Qt, QSettings
from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QVBoxLayout
from PyQt5.QtWidgets import QPushButton, QTableWidget, QCheckBox, QTextEdit
class TestUI(QWidget):
def __init__(self):
super().__init__()
self.btn = QPushButton("Get Data")
self.tbl = QTableWidget()
self.log = QTextEdit()
self.init_ui()
def init_ui(self):
self.btn.clicked.connect(self.get_data)
self.tbl.setFocusPolicy(Qt.NoFocus)
self.tbl.setMinimumHeight(255)
self.tbl.setMaximumHeight(255)
self.tbl.setRowCount(20)
self.tbl.setColumnCount(3)
self.tbl.horizontalHeader().setStretchLastSection(True)
self.tbl.setHorizontalHeaderLabels(["", "Option", "Value"])
self.tbl.resizeRowsToContents()
self.tbl.resizeColumnsToContents()
for row in range(20):
chk_box = QCheckBox()
chk_box.setCheckState(Qt.Unchecked)
cell = QWidget()
hlayout = QHBoxLayout()
hlayout.addWidget(chk_box)
hlayout.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)
hlayout.setContentsMargins(0, 0, 0, 0)
cell.setLayout(hlayout)
self.tbl.setCellWidget(row, 0, cell)
vlayout = QVBoxLayout()
vlayout.addWidget(self.btn)
vlayout.addWidget(self.tbl)
vlayout.addWidget(self.log)
self.setLayout(vlayout)
self.show()
def get_data(self):
self.log.clear()
self.log.append(self.tbl.cellWidget(0, 0).isChecked())
self.log.append(self.tbl.cellWidget(0, 1).text())
self.log.append(self.tbl.cellWidget(0, 2).text())
if __name__ == "__main__":
APP = QApplication(sys.argv)
ex = TestUI()
sys.exit(APP.exec_())
How can I do this? I can't get the state through this code.
I think the code should be self.log.append(self.tbl.cellWidget(0, 0).????.isChecked()).
But I do not know exactly how to do it.
Please help me.

If the code that places the widget in column 0 is analyzed:
chk_box = QCheckBox()
chk_box.setCheckState(Qt.Unchecked)
cell = QWidget()
hlayout = QHBoxLayout()
hlayout.addWidget(chk_box)
hlayout.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)
hlayout.setContentsMargins(0, 0, 0, 0)
cell.setLayout(hlayout)
self.tbl.setCellWidget(row, 0, cell)
It is noted that the widget set is not the QCheckBox but a QWidget, and the QCheckBox is the son of the QWidget so that information can be used to obtain it using the findChild() method. On the other hand, the item method may return None, so you should check if it is not, since it could throw an exception:
def get_data(self):
self.log.clear()
widget = self.tbl.cellWidget(0, 0)
if widget is not None:
chk_box = widget.findChild(QCheckBox)
if chk_box is not None:
self.log.append(str(chk_box.isChecked()))
it1 = self.tbl.item(0, 1)
self.log.append(it1.text() if it1 is not None else "")
it2 = self.tbl.item(0, 2)
self.log.append(it2.text() if it2 is not None else "")
A more elegant version of the above is to make the "cell" a custom widget that exposes the isChecked() method of the QCheckBox:
class Widget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.chk_box = QCheckBox()
self.chk_box.setCheckState(Qt.Unchecked)
hlayout = QHBoxLayout(self)
hlayout.addWidget(self.chk_box)
hlayout.setAlignment(Qt.AlignCenter)
hlayout.setContentsMargins(0, 0, 0, 0)
def isChecked(self):
return self.chk_box.isChecked()
class TestUI(QWidget):
def __init__(self):
super().__init__()
self.btn = QPushButton("Get Data")
self.tbl = QTableWidget()
self.log = QTextEdit()
self.init_ui()
def init_ui(self):
self.btn.clicked.connect(self.get_data)
self.tbl.setFocusPolicy(Qt.NoFocus)
self.tbl.setMinimumHeight(255)
self.tbl.setMaximumHeight(255)
self.tbl.setRowCount(20)
self.tbl.setColumnCount(3)
self.tbl.horizontalHeader().setStretchLastSection(True)
self.tbl.setHorizontalHeaderLabels(["", "Option", "Value"])
self.tbl.resizeRowsToContents()
self.tbl.resizeColumnsToContents()
for row in range(20):
cell = Widget()
self.tbl.setCellWidget(row, 0, cell)
vlayout = QVBoxLayout(self)
vlayout.addWidget(self.btn)
vlayout.addWidget(self.tbl)
vlayout.addWidget(self.log)
self.show()
def get_data(self):
self.log.clear()
widget = self.tbl.cellWidget(0, 0)
if widget is not None:
self.log.append(str(widget.isChecked()))
it1 = self.tbl.item(0, 1)
self.log.append(it1.text() if it1 is not None else "")
it2 = self.tbl.item(0, 2)
self.log.append(it2.text() if it2 is not None else "")
It can be deduced that you use the QWidget to center the QCheckBox inside the cell but I think it can be optimized to avoid creating widgets using a QProxyStyle, and then access the information through the checkState() method of the QTableWidgetItem:
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (
QApplication,
QWidget,
QHBoxLayout,
QVBoxLayout,
QPushButton,
QTableWidget,
QTextEdit,
QTableWidgetItem,
QProxyStyle,
QStyle,
)
class ProxyStyle(QProxyStyle):
def subElementRect(self, element, option, widget):
r = super().subElementRect(element, option, widget)
if element == QStyle.SE_ItemViewItemCheckIndicator:
r.moveCenter(option.rect.center())
return r
class TestUI(QWidget):
def __init__(self):
super().__init__()
self.btn = QPushButton("Get Data")
self.tbl = QTableWidget()
self.log = QTextEdit()
self.init_ui()
def init_ui(self):
self.btn.clicked.connect(self.get_data)
proxy = ProxyStyle()
self.tbl.setStyle(proxy)
self.tbl.setFocusPolicy(Qt.NoFocus)
self.tbl.setFixedHeight(255)
self.tbl.setRowCount(20)
self.tbl.setColumnCount(3)
self.tbl.horizontalHeader().setStretchLastSection(True)
self.tbl.setHorizontalHeaderLabels(["", "Option", "Value"])
self.tbl.resizeRowsToContents()
self.tbl.resizeColumnsToContents()
for row in range(20):
it = QTableWidgetItem()
it.setCheckState(Qt.Checked)
self.tbl.setItem(row, 0, it)
vlayout = QVBoxLayout(self)
vlayout.addWidget(self.btn)
vlayout.addWidget(self.tbl)
vlayout.addWidget(self.log)
self.show()
def get_data(self):
self.log.clear()
it0 = self.tbl.item(0, 0)
self.log.append(str(it0.checkState() == Qt.Checked))
it1 = self.tbl.item(0, 1)
self.log.append(it1.text() if it1 is not None else "")
it2 = self.tbl.item(0, 2)
self.log.append(it2.text() if it2 is not None else "")
if __name__ == "__main__":
APP = QApplication(sys.argv)
ex = TestUI()
sys.exit(APP.exec_())

Related

How do I programmatically change the parent of a layout

I want to be able to move a layout to another layout based on a user input. I have the following code which does not appear to work for me. If I switch lines 31 and 34 so that they operate on the widget rather than the layout then I get the expected behaviour but I am hoping to operate on all widgets within a layout by just moving the layout.
import sys
from PyQt5.QtWidgets import QPushButton, QWidget, QHBoxLayout, QLabel, QApplication, QVBoxLayout
class b(QWidget):
def __init__(self, name):
super(b, self).__init__()
self.layout = QVBoxLayout(self)
lbl_1 = QLabel(name)
self.layout.addWidget(lbl_1)
class a(QWidget):
def __init__(self):
super(a, self).__init__()
self.layout = QHBoxLayout(self)
self.widget_1 = b('widget 1')
self.widget_2 = b('widget 2')
self.layout.addWidget(self.widget_1)
self.layout.addWidget(self.widget_2)
self.button_layout = QHBoxLayout()
self.move_layout = QPushButton('Move to other layout')
self.move_layout.clicked.connect(lambda: self.move_button())
self.button_layout.addWidget(self.move_layout)
self.widget = 'widget_2'
self.widget_2.layout.addLayout(self.button_layout)
def move_button(self):
if self.widget == 'widget_2':
self.widget_1.layout.addLayout(self.button_layout)
self.widget = 'widget_1'
else:
self.widget_2.layout.addLayout(self.button_layout)
self.widget = 'widget_2'
print('moved widget to {}'.format(self.widget))
if __name__ == '__main__':
app = QApplication(sys.argv)
window = a()
window.show()
sys.exit(app.exec_())
Edit: to clarify, In the example above, the layout I want to move (self.button_layout) is a child layout of self.widget_2.layout. When I click the pushbutton, I want the self.button_layout to be set as a child layout of self.widget_1.layout. Essentially it will do what the code below does but using addLayout instead of addWidget.
import sys
from PyQt5.QtWidgets import QPushButton, QWidget, QHBoxLayout, QLabel, QApplication, QVBoxLayout
class b(QWidget):
def __init__(self, name):
super(b, self).__init__()
self.layout = QVBoxLayout(self)
lbl_1 = QLabel(name)
self.layout.addWidget(lbl_1)
class a(QWidget):
def __init__(self):
super(a, self).__init__()
self.layout = QHBoxLayout(self)
self.widget_1 = b('widget 1')
self.widget_2 = b('widget 2')
self.layout.addWidget(self.widget_1)
self.layout.addWidget(self.widget_2)
self.button_layout = QHBoxLayout()
self.move_layout = QPushButton('Move to other layout')
self.move_layout.clicked.connect(lambda: self.move_button())
self.button_layout.addWidget(self.move_layout)
self.widget = 'widget_2'
self.widget_2.layout.addLayout(self.button_layout)
def move_button(self):
if self.widget == 'widget_2':
self.widget_1.layout.addWidget(self.move_layout)
self.widget = 'widget_1'
else:
self.widget_2.layout.addWidget(self.move_layout)
self.widget = 'widget_2'
print('moved widget to {}'.format(self.widget))
if __name__ == '__main__':
app = QApplication(sys.argv)
window = a()
window.show()
sys.exit(app.exec_())
The problem is that if a layout has a parent then it cannot be changed as the error message indicates:
QLayout::addChildLayout: layout "" already has a parent
One possible solution is to remove the parent:
def move_button(self):
self.button_layout.setParent(None)
if self.widget == "widget_2":
self.widget_1.layout.addLayout(self.button_layout)
self.widget = "widget_1"
else:
self.widget_2.layout.addLayout(self.button_layout)
self.widget = "widget_2"
print("moved widget to {}".format(self.widget))
Another alternative is to place the layout in a QWidget that is the container and that place it in the required layout:
class a(QWidget):
def __init__(self):
super(a, self).__init__()
layout = QHBoxLayout(self)
self.widget_1 = b("widget 1")
self.widget_2 = b("widget 2")
layout.addWidget(self.widget_1)
layout.addWidget(self.widget_2)
self.container = QWidget()
container_layout = QHBoxLayout(self.container)
button = QPushButton("Move to other layout")
button.clicked.connect(self.move_button)
container_layout.addWidget(button)
self.widget = "widget_1"
self.move_button()
def move_button(self):
if self.widget == "widget_2":
self.widget_1.layout.addWidget(self.container)
self.widget = "widget_1"
else:
self.widget_2.layout.addWidget(self.container)
self.widget = "widget_2"
print("moved widget to {}".format(self.widget))

How can I generate the buttons and connect them to different functions? [duplicate]

This question already has answers here:
How do I assert the identity of a PyQt5 signal?
(2 answers)
Closed 2 years ago.
I've created a search engine in PyQt5, using the code below:
import sys
from PyQt5.QtWidgets import (
QWidget, QLineEdit, QLabel, QScrollArea, QMainWindow,
QApplication, QHBoxLayout, QVBoxLayout, QSpacerItem, QSizePolicy, QCompleter, QPushButton
)
from PyQt5 import QtCore
from PyQt5.QtCore import Qt
tlist = ['thing1', 'thing2', 'thing3', 'thing4']
class Label(QWidget):
def __init__(self, name):
super(Label, self).__init__()
self.name = name
self.lbl = QLabel(self.name)
self.lbl.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse)
self.btn = QPushButton("Preview")
self.btn.setMaximumSize(QtCore.QSize(100,100))
self.btn.clicked.connect(self.printsignal)
self.hbox = QHBoxLayout()
self.hbox.addWidget(self.lbl)
self.hbox.addWidget(self.btn)
self.setLayout(self.hbox)
def show(self):
for labels in [self, self.lbl]:
labels.setVisible(True)
def hide(self):
for labels in [self, self.lbl]:
labels.setVisible(False)
def printsignal(self):
print("clicked")
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super().__init__()
self.controls = QWidget()
self.controlsLayout = QVBoxLayout()
self.widgets = []
for name in tlist:
item = Label(name)
self.controlsLayout.addWidget(item)
self.widgets.append(item)
spacer = QSpacerItem(1, 1, QSizePolicy.Minimum, QSizePolicy.Expanding)
self.controlsLayout.addItem(spacer)
self.controls.setLayout(self.controlsLayout)
self.scroll = QScrollArea()
self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
self.scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.scroll.setWidgetResizable(True)
self.scroll.setWidget(self.controls)
self.searchbar = QLineEdit()
self.searchbar.textChanged.connect(self.update_display)
self.completer = QCompleter(tlist)
self.completer.setCaseSensitivity(Qt.CaseInsensitive)
self.searchbar.setCompleter(self.completer)
container = QWidget()
containerLayout = QVBoxLayout()
containerLayout.addWidget(self.searchbar)
containerLayout.addWidget(self.scroll)
container.setLayout(containerLayout)
self.setCentralWidget(container)
self.setGeometry(600, 100, 800, 600)
self.setWindowTitle('Search Engine')
def update_display(self, text):
for widget in self.widgets:
if text.lower() in widget.name.lower():
widget.show()
else:
widget.hide()
app = QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
The problem I have is, all the buttons share the same function and I don't know how to make them have different signals, as they are generated automatically. Basically, if I run the code it will show up like
this:
and when I press any of the buttons, it will print "clicked" (as in printsignal function). What I want is a different function for each button. Is there a way to do that?
Normally you can use self.sender().text() to get text from QButton which generated signal.
But because you create own widget Label with QButton and QLabel and you want text from label so you can get directly self.name
def printsignal(self):
print("clicked", self.name)
eventually self.lbl.text()
def printsignal(self):
print("clicked", self.lbl.text())
Working code.
I removed show(), hide() because you don't need it
import sys
from PyQt5.QtWidgets import (
QWidget, QLineEdit, QLabel, QScrollArea, QMainWindow,
QApplication, QHBoxLayout, QVBoxLayout, QSpacerItem, QSizePolicy, QCompleter, QPushButton
)
from PyQt5 import QtCore
from PyQt5.QtCore import Qt
tlist = ['thing1', 'thing2', 'thing3', 'thing4']
class Label(QWidget):
def __init__(self, name):
super().__init__()
self.name = name
self.lbl = QLabel(self.name)
self.lbl.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse)
self.btn = QPushButton("Preview")
self.btn.setMaximumSize(QtCore.QSize(100,100))
self.btn.clicked.connect(self.printsignal)
self.hbox = QHBoxLayout()
self.hbox.addWidget(self.lbl)
self.hbox.addWidget(self.btn)
self.setLayout(self.hbox)
def printsignal(self):
print("clicked", self.name)
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super().__init__()
self.controls = QWidget()
self.controlsLayout = QVBoxLayout()
self.widgets = []
for name in tlist:
item = Label(name)
self.controlsLayout.addWidget(item)
self.widgets.append(item)
spacer = QSpacerItem(1, 1, QSizePolicy.Minimum, QSizePolicy.Expanding)
self.controlsLayout.addItem(spacer)
self.controls.setLayout(self.controlsLayout)
self.scroll = QScrollArea()
self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
self.scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.scroll.setWidgetResizable(True)
self.scroll.setWidget(self.controls)
self.searchbar = QLineEdit()
self.searchbar.textChanged.connect(self.update_display)
self.completer = QCompleter(tlist)
self.completer.setCaseSensitivity(Qt.CaseInsensitive)
self.searchbar.setCompleter(self.completer)
container = QWidget()
containerLayout = QVBoxLayout()
containerLayout.addWidget(self.searchbar)
containerLayout.addWidget(self.scroll)
container.setLayout(containerLayout)
self.setCentralWidget(container)
self.setGeometry(600, 100, 800, 600)
self.setWindowTitle('Search Engine')
def update_display(self, text):
for widget in self.widgets:
if text.lower() in widget.name.lower():
widget.show()
else:
widget.hide()
app = QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())

PyQt5 Custom Title Bar Doesn't Show

I am trying to make my first program. I'm hoping for custom dark mode design, and that requires me to make a custom title bar.
I copied the code for the title bar from someone else, it worked perfectly - custom movable window.
I have carefully merged it with my previous code, though title bar doesn't appear.
Now my guess is I have to call it at the end of my code, but it ends up with errors, as I'm not sure how to properly call it.
Note: removing the QtCore.Qt.FramelessWindowHint part is NOT the answer, as it just brings back the stock Win title bar, that's supposed to be hidden and replaced by dark title bar.
Part of code copied from: https://stackoverflow.com/a/44249552/12221725
Image:
import sys
from PyQt5 import QtGui, QtCore
from PyQt5.QtGui import QFont
from PyQt5.QtCore import Qt, QPoint
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout, QVBoxLayout, QTextEdit
#fCol = "#e0e0e0"
#bCol = "#212121"
class MainWindow(QWidget):
def __init__(self):
super(MainWindow, self).__init__()
self.layout = QHBoxLayout()
self.textArea = QTextEdit("Lorem ipsum...")
self.layout.addWidget(self.textArea)
self.textArea.setStyleSheet("QTextEdit {color:white;background-color:#212121;border-radius:+16px;}")
self.sans = QFont("Segoe UI",20)
self.textArea.setFont(self.sans)
self.btnLayout = QVBoxLayout()
self.btnLayout.addWidget(QPushButton("Open"))
self.btnLayout.addWidget(QPushButton("Setup"))
self.btnLayout.addWidget(QPushButton("Find"))
self.setStyleSheet("QPushButton {max-width:200px;color:#4fc3f7;background-color:#424242;border:2px solid #4fc3f7;border-radius:16px;font-size:35px;font-weight:bold;}" + "QPushButton:hover {color:#212121;background-color:#4fc3f7;}" + "QPushButton:pressed {color:white;background-color:#212121;border-color:white;}")
self.status = QTextEdit()
self.status.insertPlainText("Successfully loaded" + "\nOpen a file...")
self.status.setReadOnly(1)
self.status.setStyleSheet("QTextEdit {color:white;background-color:#212121;border-radius:+16px;font-size:14px;max-width:200px;}")
self.btnLayout.addWidget(self.status)
self.layout.addLayout(self.btnLayout)
self.setLayout(self.layout)
#self.setFixedSize(650, 320)
self.setFixedSize(800, 400)
self.setWindowTitle("Py Program")
self.setWindowFlags(QtCore.Qt.FramelessWindowHint)# | QtCore.Qt.WindowStaysOnTopHint)
#self.layout.setContentsMargins(0,0,0,0)
#self.layout.addStretch(-1)
#self.pressing = False
print("MainWindow Loaded")
#self.show()
class MyBar(QWidget):
def __init__(self, parent):
super(MyBar, self).__init__()
self.parent = parent
print(self.parent.width())
self.layout = QHBoxLayout()
self.layout.setContentsMargins(0,0,0,0)
self.title = QLabel("My Own Bar")
btn_size = 35
self.btn_close = QPushButton("x")
self.btn_close.clicked.connect(self.btn_close_clicked)
self.btn_close.setFixedSize(btn_size,btn_size)
self.btn_close.setStyleSheet("background-color: red;")
self.btn_min = QPushButton("-")
self.btn_min.clicked.connect(self.btn_min_clicked)
self.btn_min.setFixedSize(btn_size, btn_size)
self.btn_min.setStyleSheet("background-color: gray;")
self.btn_max = QPushButton("+")
self.btn_max.clicked.connect(self.btn_max_clicked)
self.btn_max.setFixedSize(btn_size, btn_size)
self.btn_max.setStyleSheet("background-color: gray;")
self.title.setFixedHeight(35)
self.title.setAlignment(Qt.AlignCenter)
self.layout.addWidget(self.title)
self.layout.addWidget(self.btn_min)
self.layout.addWidget(self.btn_max)
self.layout.addWidget(self.btn_close)
self.title.setStyleSheet("background-color: black;color: white;")
self.setLayout(self.layout)
self.start = QPoint(0, 0)
self.pressing = False
print("MyBar Loaded")
def resizeEvent(self, QResizeEvent):
super(MyBar, self).resizeEvent(QResizeEvent)
self.title.setFixedWidth(self.parent.width())
def mousePressEvent(self, event):
self.start = self.mapToGlobal(event.pos())
self.pressing = True
def mouseMoveEvent(self, event):
if self.pressing:
self.end = self.mapToGlobal(event.pos())
self.movement = self.end-self.start
self.parent.setGeometry(self.mapToGlobal(self.movement).x(),
self.mapToGlobal(self.movement).y(),
self.parent.width(),
self.parent.height())
self.start = self.end
def mouseReleaseEvent(self, QMouseEvent):
self.pressing = False
def btn_close_clicked(self):
self.parent.close()
def btn_max_clicked(self):
self.parent.showMaximized()
def btn_min_clicked(self):
self.parent.showMinimized()
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setWindowIcon(QtGui.QIcon("icon.png"))
app.setStyleSheet("QWidget {background-color:#424242;border-radius:12px;}")
app.setFont(QFont("Consolas"))
mw = MainWindow()
mw.show()
sys.exit(app.exec_())
The problem is that you have not created or placed a Bar() inside the window. You must also restructure your layout so that the titlebar is displayed at the top and your content at the bottom using a QVBoxLayout.
On the other hand I have improved the original titleBar so that it is not necessary to set the parent directly but instead use the window():
import sys
from PyQt5.QtGui import QFont, QIcon
from PyQt5.QtCore import Qt, QPoint
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout, QVBoxLayout, QTextEdit, QLabel
class MainWindow(QWidget):
def __init__(self):
super(MainWindow, self).__init__()
self.setWindowFlags(Qt.FramelessWindowHint)
hlayout = QHBoxLayout()
self.textArea = QTextEdit("Lorem ipsum...")
hlayout.addWidget(self.textArea)
self.textArea.setStyleSheet("QTextEdit {color:white;background-color:#212121;border-radius:+16px;}")
self.sans = QFont("Segoe UI",20)
self.textArea.setFont(self.sans)
self.btnLayout = QVBoxLayout()
self.btnLayout.addWidget(QPushButton("Open"))
self.btnLayout.addWidget(QPushButton("Setup"))
self.btnLayout.addWidget(QPushButton("Find"))
self.setStyleSheet("QPushButton {max-width:200px;color:#4fc3f7;background-color:#424242;border:2px solid #4fc3f7;border-radius:16px;font-size:35px;font-weight:bold;}" + "QPushButton:hover {color:#212121;background-color:#4fc3f7;}" + "QPushButton:pressed {color:white;background-color:#212121;border-color:white;}")
self.status = QTextEdit()
self.status.insertPlainText("Successfully loaded" + "\nOpen a file...")
self.status.setReadOnly(1)
self.status.setStyleSheet("QTextEdit {color:white;background-color:#212121;border-radius:+16px;font-size:14px;max-width:200px;}")
self.btnLayout.addWidget(self.status)
self.setFixedSize(800, 400)
self.setWindowTitle("Py app")
hlayout.addLayout(self.btnLayout)
custom_titlebar = TitleBar()
lay = QVBoxLayout(self)
lay.addWidget(custom_titlebar)
lay.addLayout(hlayout)
class TitleBar(QWidget):
def __init__(self, parent=None):
super(TitleBar, self).__init__(parent)
self.title = QLabel("My Own Bar")
btn_size = 35
self.btn_close = QPushButton("x")
self.btn_close.clicked.connect(self.btn_close_clicked)
self.btn_close.setFixedSize(btn_size,btn_size)
self.btn_close.setStyleSheet("background-color: red;")
self.btn_min = QPushButton("-")
self.btn_min.clicked.connect(self.btn_min_clicked)
self.btn_min.setFixedSize(btn_size, btn_size)
self.btn_min.setStyleSheet("background-color: gray;")
self.btn_max = QPushButton("+")
self.btn_max.clicked.connect(self.btn_max_clicked)
self.btn_max.setFixedSize(btn_size, btn_size)
self.btn_max.setStyleSheet("background-color: gray;")
self.title.setFixedHeight(35)
self.title.setAlignment(Qt.AlignCenter)
self.title.setStyleSheet("background-color: black;color: white;")
lay = QHBoxLayout(self)
lay.setContentsMargins(0,0,0,0)
lay.addWidget(self.title)
lay.addWidget(self.btn_min)
lay.addWidget(self.btn_max)
lay.addWidget(self.btn_close)
self.pressing = False
self.dragPosition = QPoint()
def resizeEvent(self, QResizeEvent):
super(TitleBar, self).resizeEvent(QResizeEvent)
self.title.setFixedWidth(self.window().width())
def mousePressEvent(self, event):
self.start = event.globalPos()
self.pressing = True
def mouseMoveEvent(self, event):
if self.pressing:
self.end = event.globalPos()
delta = self.end - self.start
self.window().move(self.window().pos() + delta)
self.start = self.end
def mouseReleaseEvent(self, QMouseEvent):
self.pressing = False
def btn_close_clicked(self):
self.window().close()
def btn_max_clicked(self):
self.window().showMaximized()
def btn_min_clicked(self):
self.window().showMinimized()
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setWindowIcon(QIcon("icon.png"))
app.setStyleSheet("QWidget {background-color:#424242;border-radius:12px;}")
app.setFont(QFont("Consolas"))
mw = MainWindow()
mw.show()
sys.exit(app.exec_())

Can a checkable Qstandard item be centered within a QStandardItemModel column?

I have a table class with a column of check boxes. I'd like to center these within the column but using item.setTextAlignment(Qt.AlignCenter) doesn't work.
from PyQt5.QtWidgets import *
from PyQt5.QtCore import (QDate, QDateTime, QRegExp, QSortFilterProxyModel, Qt,
QTime, QModelIndex, QSize, pyqtSignal, QObject)
from PyQt5.QtGui import QStandardItemModel, QIcon, QStandardItem
class Table(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.initUI()
self.show()
def initUI(self):
mainLayout = QVBoxLayout()
self.proxyModel = QSortFilterProxyModel()
self.proxyModel.setDynamicSortFilter(True)
self.sourceModel = QStandardItemModel(0, 2, self)
self.sourceModel.setHeaderData(0, Qt.Horizontal, '')
self.sourceModel.setHeaderData(1, Qt.Horizontal, 'Value')
self.proxyModel.setSourceModel(self.sourceModel)
self.proxyGroupBox = QGroupBox('data')
self.proxyView = QTreeView()
self.proxyView.setRootIsDecorated(False)
self.proxyView.setAlternatingRowColors(True)
self.proxyView.setModel(self.proxyModel)
self.proxyView.setEditTriggers(QAbstractItemView.NoEditTriggers)
proxyLayout = QGridLayout()
proxyLayout.addWidget(self.proxyView, 0, 0, 1, 3)
self.proxyGroupBox.setLayout(proxyLayout)
mainLayout.addWidget(self.proxyGroupBox)
self.setLayout(mainLayout)
for i in range(5):
self.proxyView.resizeColumnToContents(0)
item = QStandardItem(True)
item.setCheckable(True)
item.setCheckState(False)
#item.setTextAlignment(Qt.AlignCenter)
self.sourceModel.setItem(i, 0, item)
self.sourceModel.setData(self.sourceModel.index(i, 1), i+1)
def setSourceModel(self, model):
self.proxyModel.setSourceModel(model)
if __name__=='__main__':
import sys
app = QApplication(sys.argv)
window = Table()
sys.exit(app.exec_())
Is there anyway to center each item of the first column?
If you want to change the alignment of the checkbox then you must use a QProxyStyle:
class CheckBoxProxyStyle(QProxyStyle):
def subElementRect(self, element, option, widget):
rect = super().subElementRect(element, option, widget)
if element == QStyle.SE_ItemViewItemCheckIndicator:
rect.moveCenter(option.rect.center())
return rect
self.proxyView = QTreeView()
self.proxyView.setStyle(CheckBoxProxyStyle(self.proxyView.style()))

PySide - Group radioButton in a loop

I have a problem when trying to group, radioButton generated in a loop, together so that each line has its one buttonGroup and can be checked separetly.
Here is a stripped version of my code:
def ui_layout(self):
self.main_layout = QVBoxLayout()
self.setLayout(self.main_layout)
attrs = ['a', 'b']
for attr in attrs:
buttonGroup = QButtonGroup()
self.attr_layout = QHBoxLayout()
self.main_layout.addLayout(self.attr_layout)
self.rb1 = QRadioButton('{}_rb1'.format(attr))
self.attr_layout.addWidget(self.rb1)
buttonGroup.addButton(self.rb1)
self.rb2 = QRadioButton('{}_rb2'.format(attr))
self.attr_layout.addWidget(self.rb2)
buttonGroup.addButton(self.rb2)
All I get is this :
Here's the full code if you wanna try stuff : https://pastebin.com/3vJ4DXER
Try it:
import sys
from PyQt5.QtWidgets import (QRadioButton, QVBoxLayout, QHBoxLayout,
QButtonGroup, QApplication, QWidget)
class Window(QWidget):
def __init__(self):
super().__init__()
self.init_ui()
def init_ui(self):
self.main_layout = QVBoxLayout()
self.setLayout(self.main_layout)
attrs = ['a', 'b']
self.buttonGroup = ['a', 'b']
for i, attr in enumerate(attrs):
self.buttonGroup[i] = QButtonGroup()
self.attr_layout = QHBoxLayout()
self.main_layout.addLayout(self.attr_layout)
self.rb1 = QRadioButton('{}_rb1'.format(attr))
self.attr_layout.addWidget(self.rb1)
self.buttonGroup[i].addButton(self.rb1)
self.rb2 = QRadioButton('{}_rb2'.format(attr))
self.attr_layout.addWidget(self.rb2)
self.buttonGroup[i].addButton(self.rb2)
self.buttonGroup[i].buttonClicked.connect(self.check_button)
def check_button(self, radioButton):
print("radioButton-> `{}`".format(radioButton.text()))
app = QApplication(sys.argv)
a_window = Window()
a_window.show()
sys.exit(app.exec_())

Categories