I have a minimum example here of a QTableView widget that displays a long string that I want word wrapped when I start the app.
from PyQt6.QtWidgets import (
QMainWindow,
QTableView,
QHeaderView,
QApplication,
)
from PyQt6.QtCore import (
Qt,
QEvent,
QAbstractTableModel,
QSize,
QEvent
)
import sys
text = """A long string which needs word wrapping to fully display. A long string which needs word wrapping to fully display. A long string which needs word wrapping to fully display."""
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.table = QTableView()
header = self.table.horizontalHeader()
header.setSectionResizeMode(QHeaderView.ResizeMode.Stretch)
self.table.horizontalHeader().sectionResized.connect(self.table.resizeRowsToContents)
self.model = TableModel([[text] for i in range(50)])
self.table.setModel(self.model)
self.setCentralWidget(self.table)
self.table.resizeRowsToContents()
def changeEvent(self, event):
if event.type() == QEvent.Type.WindowStateChange:
self.table.resizeRowsToContents()
return super(MainWindow, self).changeEvent(event)
class TableModel(QAbstractTableModel):
def __init__(self, data):
super().__init__()
self._data = data
def data(self, index, role):
if role == Qt.ItemDataRole.DisplayRole:
return self._data[index.row()][index.column()]
def rowCount(self, index):
return len(self._data)
def columnCount(self, index):
return len(self._data[0])
app = QApplication(sys.argv)
app.lastWindowClosed.connect(app.quit)
w = MainWindow()
w.show()
app.exec()
When I run the above I get this
but when I resize the window manually just slightly, I get what I'm expecting
How would I get the second image as the state when the app is started? I thought calling self.table.resizeRowsToContents() in the __init__ method would do it. Another question is, why does self.table.horizontalHeader().sectionResized.connect(self.table.resizeRowsToContents) work upon resizing when resizeRowsToContents() does not work in the __init__ method?
why does self.table.horizontalHeader().sectionResized.connect(self.table.resizeRowsToContents) work upon resizing when resizeRowsToContents() does not work in the init method?
Because the window isn't rendered yet, that's why the QTableView doesn't know yet how big the text is in order to resize the rows.
How would I get the second image as the state when the app is started? I thought calling self.table.resizeRowsToContents() in the init method would do it.
You could separate the population of the table from the init method, or delay it, until Your widget is rendered, preferably inside the class itself, but you can do something like this:
# ...
app = QApplication(sys.argv)
app.lastWindowClosed.connect(app.quit)
w = MainWindow()
w.show()
w.table.resizeRowsToContents() # I just added this line
app.exec()
Related
I'm new to pyqt6 and even to python. As the title indicates, I got stuck with handling mouse position variables. I was expecting to show coodinates of mouse pointer in the QLabel correspond to the mouse movement. I was able to fetch coordinates from mouseMoveEvent in the QGraphicsScene class to getPosition in the Window class. But, that coodinates couldn't be passed to the other function in Window class.
Here is my code so far.
import sys
from PyQt6 import QtWidgets
from PyQt6.QtWidgets import QVBoxLayout, QWidget, QLabel
class GraphicsScene(QtWidgets.QGraphicsScene):
def __init__(self, parent=None):
super().__init__(parent)
def mouseMoveEvent(self, event):
self.posX = event.scenePos().x()
Window.getPosition(Window, event.scenePos().x())
class GraphicsView(QtWidgets.QGraphicsView):
def __init__(self, parent=None):
super(GraphicsView, self).__init__(parent)
self.setMouseTracking(True)
scene = GraphicsScene(self)
self.setScene(scene)
class Window(QWidget):
def __init__(self):
super().__init__()
self.Layout = QVBoxLayout()
self.gw = GraphicsView() # an image is meant to be set here.
self.Layout.addWidget(self.gw)
self.label = QLabel("Coordinate: x") # wanna show coorinates here correspond to the mouse movement.
self.Layout.addWidget(self.label)
self.setLayout(self.Layout)
def getPosition(self, posX):
self.label.setText("Coordinate: x" + str(self.posX))
self.repaint()
print(posX)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = Window()
w.show()
sys.exit(app.exec())
and got an ERROR like this:
AttributeError: type object 'Window' has no attribute 'label'
It seemas the self in the getPosition function is set to GraphicsScene class after being called (unexpectedly for me). And I have no idea this approach works or not after reading several web documents and asking help for chatGPT. Possibly, I took wrong approach to layout of Widgets.
Any suggestion would be helpful because I'm stuck whole this week with dipression.
Thanks.
Using class Window as parameter to setPosition was wrong, one needs to use an instance of this class. I did this by climbing up the parent() methods and there may be prettier ways to achieve the same. However, it works for now and I did not want to throw in too many changes.
I marked notable changes with comments.
#!/usr/bin/env python3
import sys
from PyQt6 import QtWidgets
class GraphicsScene(QtWidgets.QGraphicsScene):
def __init__(self, parent=None):
super().__init__(parent)
def mouseMoveEvent(self, event):
self.posX = event.scenePos().x()
self.parent().parent().setPosition(event.scenePos().x()) # <-- crawl up the ancestry
class GraphicsView(QtWidgets.QGraphicsView):
def __init__(self, parent=None):
super(GraphicsView, self).__init__(parent)
self.setMouseTracking(True)
scene = GraphicsScene(self)
self.setScene(scene)
class Window(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.Layout = QtWidgets.QVBoxLayout()
self.gw = GraphicsView(self) # <-- pass self here
self.Layout.addWidget(self.gw)
self.label = QtWidgets.QLabel("Coordinate: x") # wanna show coorinates here correspond to the mouse movement.
self.Layout.addWidget(self.label)
self.setLayout(self.Layout)
def setPosition(self, posX): # <-- this is a setter, not a getter
self.label.setText("Coordinate: x" + str(posX)) # <-- use argument posX
self.repaint()
print(posX)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = Window()
w.show()
sys.exit(app.exec())
I'm trying to add custom animation to QPushbutton without making a custom QPushbutton and overriding its enterEvent() and leaveEvent().
So far I've tried this,
#staticmethod
def addButtonHoverAnimation(button:QPushButton,currentPos:QPoint):
'''
Method to:
=> Add hover animation for provided button
'''
enterShift = QPropertyAnimation(button,b'pos',button)
exitShift = QPropertyAnimation(button,b'pos',button)
def enterEvent(e):
pos=button.pos()
enterShift.setStartValue(pos)
enterShift.setEndValue(QPoint(pos.x()+3,pos.y()+3))
enterShift.setDuration(100)
enterShift.start()
Effects.dropShadow(button,1,2)
def leaveEvent(e):
pos=button.pos()
exitShift.setStartValue(pos)
exitShift.setEndValue(QPoint(pos.x()-3,pos.y()-3))
exitShift.setDuration(100)
exitShift.start()
Effects.dropShadow(button)
button.enterEvent=enterEvent
button.leaveEvent=leaveEvent
But when I move the mouse very quickly in and out of the button before the animation finishes, The button starts to move wierdly towards the North-West direction.
Button Animation Using Dynamic Positions
I figured out this was due to the leaveEvent() being triggered before enterEvent() even finishes and also because the start and end values are dynamic. So, I tried providing currentPos as a static position and using it instead,
#staticmethod
def addButtonHoverAnimation(button:QPushButton,currentPos:QPoint):
'''
Method to:
=> Add hover animation for provided button
'''
enterShift = QPropertyAnimation(button,b'pos',button)
enterShift.setStartValue(currentPos)
enterShift.setEndValue(QPoint(currentPos.x()+3,currentPos.y()+3))
enterShift.setDuration(100)
exitShift = QPropertyAnimation(button,b'pos',button)
exitShift.setStartValue(QPoint(currentPos.x()-3,currentPos.y()-3))
exitShift.setEndValue(currentPos)
exitShift.setDuration(100)
def enterEvent(e):
button.setProperty(b'pos',exitShift.endValue())
enterShift.start()
Effects.dropShadow(button,1,2)
def leaveEvent(e):
exitShift.start()
Effects.dropShadow(button)
button.enterEvent=enterEvent
button.leaveEvent=leaveEvent
On running, as soon as the mouse enters the QPushbutton, it moves to the top-left of its parent widget and the animation starts working fine. I can't figure out why this is happening. But I was able to get that, it only happened when I used any static value in the animation.
Button Animation with Static Position:
Here is an example:
import sys
from PyQt5.QtCore import QEvent, QPoint, QObject, QPropertyAnimation
from PyQt5.QtWidgets import QApplication, QPushButton, QVBoxLayout, QWidget
# This is the same method mentioned above
from styling import addButtonHoverAnimation
class Widget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
layout=QVBoxLayout()
button1 = QPushButton("Proceed1", self)
layout.addWidget(button1)
button2 = QPushButton("Proceed2", self)
layout.addWidget(button2)
self.setLayout(layout)
self.resize(640, 480)
addButtonHoverAnimation(button1)
addButtonHoverAnimation(button2)
def main():
app = QApplication(sys.argv)
view = Widget()
view.show()
ret = app.exec_()
sys.exit(ret)
if __name__ == "__main__":
main()
The problem is that probably when the state is changed from enter to leave (or vice versa) the previous animation still does not end so the position of the widget is not the initial or final position, so when starting the new animation there is a deviation that accumulates. One possible solution is to initialize the position and keep it as a reference.
On the other hand you should not do x.fooMethod = foo_callable since many can fail, in this case it is better to use an eventfilter.
import sys
from dataclasses import dataclass
from functools import cached_property
from PyQt5.QtCore import QEvent, QPoint, QObject, QPropertyAnimation
from PyQt5.QtWidgets import QApplication, QPushButton, QWidget
#dataclass
class AnimationManager(QObject):
widget: QWidget
delta: QPoint = QPoint(3, 3)
duration: int = 100
def __post_init__(self):
super().__init__(self.widget)
self._start_value = QPoint()
self._end_value = QPoint()
self.widget.installEventFilter(self)
self.animation.setTargetObject(self.widget)
self.animation.setPropertyName(b"pos")
self.reset()
def reset(self):
self._start_value = self.widget.pos()
self._end_value = self._start_value + self.delta
self.animation.setDuration(self.duration)
#cached_property
def animation(self):
return QPropertyAnimation(self)
def eventFilter(self, obj, event):
if obj is self.widget:
if event.type() == QEvent.Enter:
self.start_enter_animation()
elif event.type() == QEvent.Leave:
self.start_leave_animation()
return super().eventFilter(obj, event)
def start_enter_animation(self):
self.animation.stop()
self.animation.setStartValue(self.widget.pos())
self.animation.setEndValue(self._end_value)
self.animation.start()
def start_leave_animation(self):
self.animation.stop()
self.animation.setStartValue(self.widget.pos())
self.animation.setEndValue(self._start_value)
self.animation.start()
class Widget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
button1 = QPushButton("Proceed1", self)
button1.move(100, 100)
button2 = QPushButton("Proceed2", self)
button2.move(200, 200)
self.resize(640, 480)
animation_manager1 = AnimationManager(widget=button1)
animation_manager2 = AnimationManager(widget=button2)
def main():
app = QApplication(sys.argv)
view = Widget()
view.show()
ret = app.exec_()
sys.exit(ret)
if __name__ == "__main__":
main()
184 / 5000
Resultados de traducción
If you are using a layout then you must reset the position since the layout does not apply the position change immediately but only when the parent widget applies the changes.
class Widget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
button1 = QPushButton("Proceed1")
button2 = QPushButton("Proceed2")
lay = QVBoxLayout(self)
lay.addWidget(button1)
lay.addWidget(button2)
self.resize(640, 480)
self.animation_manager1 = AnimationManager(widget=button1)
self.animation_manager2 = AnimationManager(widget=button2)
def resizeEvent(self, event):
super().resizeEvent(event)
self.animation_manager1.reset()
self.animation_manager2.reset()
I've got a QTreeView populated by a QStandardItemModel with the TreeView set up so it only allows internal Drag and Drop (InternalMove).
I am trying to detect whenever the user makes such an internal move and would like to extract the item being dragged as well as the start and end location.
QStandardItemModel provides the "rowsMoved" signal which is supposed to emit precisely what I am looking for: parent, start, end, destination, row.
The problem: This signal never gets called when moving around items. Why is this?
Other signals like rowsInserted() or rowsRemoved() work just fine, but rowsMoved() does not.
In the following minimal example, the print() in onMove() should be called when the user moves around items, but it doesn't.
import random
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
model = QtGui.QStandardItemModel(self)
view = QtWidgets.QTreeView()
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(view)
view.setModel(model)
root_item = QtGui.QStandardItem("Root")
model.appendRow(root_item)
self.populate(root_item, 3)
view.expandAll()
view.setDragEnabled(True)
view.setDragDropMode(QtWidgets.QAbstractItemView.InternalMove)
view.setDefaultDropAction(QtCore.Qt.MoveAction)
view.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
view.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectItems)
model.rowsMoved.connect(self.onMove)
def onMove(self, parent, start, end, destination, row):
print("parent",parent,"start",start,"end",end,"destination",destination,"row",row)
def populate(self, root_item, level):
for i in range(random.randint(2, 4)):
it = QtGui.QStandardItem("item {}".format(i))
it.setCheckable(False)
root_item.appendRow(it)
next_level = level - 1
if next_level > 0:
self.populate(it, next_level)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
The documentation states:
Components connected to this signal use it to adapt to changes
in the model's dimensions. It can only be emitted by the QAbstractItemModel
implementation, and cannot be explicitly emitted in subclass code.
Considering that this signal is not defined by the QStandardItemModel class, any instance of this class won't emit such signal.
The only signals you can connect to, as you mentioned, are rowsInserted() are rowsRemoved() because they are redefined in this class. Note that they are marked as internal in the source file.
If you need information about the item being dragged, I suggest that you create a custom class which inherit from QtWidgets.QTreeView and override the dragEnterEvent and dropEvent methods.
Here is an example on how to retrieve the item with its whole hierarchy being dragged and dropped:
import random
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
def getHierarchy(index, hierarchy=None):
hierarchy = hierarchy or []
if not index.isValid():
return hierarchy
hierarchy.insert(0, (index.row(), index.column()))
return getHierarchy(index.parent(), hierarchy)
class MyTreeView(QtWidgets.QTreeView):
def dropEvent(self, e):
super().dropEvent(e)
currentIndex = e.source().currentIndex()
print('dropEvent.source current index:', getHierarchy(currentIndex))
def dragEnterEvent(self, e):
super().dragEnterEvent(e)
currentIndex = e.source().currentIndex()
print('dragEnterEvent.source current index:', getHierarchy(currentIndex))
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
model = QtGui.QStandardItemModel(self)
view = MyTreeView()
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(view)
view.setModel(model)
root_item = QtGui.QStandardItem("Root")
model.appendRow(root_item)
self.populate(root_item, 3)
view.expandAll()
view.setDragEnabled(True)
view.setDragDropMode(QtWidgets.QAbstractItemView.InternalMove)
view.setDefaultDropAction(QtCore.Qt.MoveAction)
view.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
view.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectItems)
def populate(self, root_item, level):
for i in range(random.randint(2, 4)):
it = QtGui.QStandardItem("item {}".format(i))
it.setCheckable(False)
root_item.appendRow(it)
next_level = level - 1
if next_level > 0:
self.populate(it, next_level)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
I suggest to look at this repository which deals with a similar problem as yours: https://github.com/d1vanov/PyQt5-reorderable-list-model
I am using PyQt5 and quite new to it. I would like to drag and drop a QListWidgetItem from one QListWidget to the other, such that the resulting QListWidgetItem on one side will contain additional data. I tried sub-classing QListWidgetItem, but the type does not carry through drag and drop as it seems to create a new instance of QListWidgetItem.
Here is the code:
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QHBoxLayout, QListWidget, QListWidgetItem, QAction, QVBoxLayout
from PyQt5 import QtCore, QtGui
import sys
class GUI(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.central_widget = MyCentralWidget(self)
self.setCentralWidget(self.central_widget)
class MyCustomItem(QListWidgetItem):
def __init__(self, data, *args, **kwargs):
super().__init__(*args, **kwargs)
self.extra_data = data
class MyCentralWidget(QWidget):
def __init__(self, parent):
super(MyCentralWidget, self).__init__(parent)
self.h_layout = QHBoxLayout(self)
self.setLayout(self.h_layout)
self.list_left = DragAndDropList()
self.list_left.setDragEnabled(True)
self.list_left.setAcceptDrops(False)
self.list_right = DragAndDropList()
self.h_layout.addWidget(self.list_left)
self.h_layout.addWidget(self.list_right)
item = MyCustomItem(69, 'custom_item')
self.list_left.insertItem(1, item)
class DragAndDropList(QListWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setIconSize(QtCore.QSize(124, 124))
self.setDragDropMode(self.DragDrop)
self.setSelectionMode(self.ExtendedSelection)
self.setAcceptDrops(True)
def dragEnterEvent(self, event):
if event.mimeData().hasUrls():
event.accept()
else:
super().dragEnterEvent(event)
def dragMoveEvent(self, event):
if event.mimeData().hasUrls():
event.setDropAction(QtCore.Qt.CopyAction)
event.accept()
else:
super().dragMoveEvent(event)
def dropEvent(self, event):
if event.mimeData().hasUrls():
event.setDropAction(QtCore.Qt.CopyAction)
event.accept()
links = []
for url in event.mimeData().urls():
links.append(str(url.toLocalFile()))
self.emit(QtCore.SIGNAL("dropped"), links)
else:
event.setDropAction(QtCore.Qt.LinkAction)
super().dropEvent(event)
list_items = [self.item(i) for i in range(self.count())]
for l in list_items:
print(l.extra_data)
def main():
app = QApplication([])
win = GUI()
win.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Here I get the error: "AttributeError: 'QListWidgetItem' object has no attribute 'extra_data'", when I try to drag and drop the custom_item.
I did have look at this thread [1], but it is out of date and there were no clear solutions.
Subclassing QListWidgetItem won't help you, as the drag and drop data is always serialized, which means that no instance reference is ever exchanged.
If your data is serializable (strings, obviously, but usually any QVariant type is fine, such as QColor or QPixmap), you can just use QListWidgetItem.setData() with a custom role specific for every data field you want to store, and then use QListWidgetItem.data() to get that data back.
In this case I created a custom function, but that's obviously not necessary, as you can just manually set the data for each item before or after inserting it, as long as you have the right row index.
MySpecialRole = QtCore.Qt.UserRole + 1
class DragAndDropList(QtWidgets.QListWidget):
def addCustomItem(self, name, data):
item = QtWidgets.QListWidgetItem(name)
item.setData(MySpecialRole, data)
self.addItem(item)
def dropEvent(self, event):
super().dropEvent(event)
# let's see the data for each item, including our custom role
for row in range(self.count()):
item = self.item(row)
print('Data for item {}: {}'.format(
row + 1, item.data(MySpecialRole)))
class MyCentralWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(MyCentralWidget, self).__init__(parent)
self.h_layout = QtWidgets.QHBoxLayout(self)
self.setLayout(self.h_layout)
self.list_left = DragAndDropList()
self.list_left.setDragEnabled(True)
self.list_right = DragAndDropList()
self.list_right.setAcceptDrops(True)
self.h_layout.addWidget(self.list_left)
self.h_layout.addWidget(self.list_right)
self.list_left.addCustomItem('item (using addCustomItem)', 'some data')
self.list_left.addItem('item without custom data')
self.list_left.addItem('this item will have data')
self.list_left.item(2).setData(MySpecialRole, 'some custom data')
Note that the following line will give you an error:
self.emit(QtCore.SIGNAL("dropped"), links)
Not only the list widget doesn't have an emit attribute (like any other subclass of QObject doesn't), but also custom signals have to be declared in the class definition and then emitted directly.
class DragAndDropList(QtWidgets.QListWidget):
dropped = QtCore.pyqtSignal(object)
def dropEvent(self, event):
# ...
self.dropped.emit(links)
I'm putting together a UI - users provide some information, and code executes. I've got some checkboxes. I want to enable/disable some of the checkboxes based on the status of other checkboxes. As an example, my UI has a checkbox which lets a user specify if they wanted a file to print, and a checkbox that let a user specify if they want it to print in colour. If the 'print' checkbox isn't ticked, I want to clear and disable the 'colour' checkbox: it doesn't make any sense to let someone say they want to print in colour if they aren't printing.
I can see how to do this with signals/slots, but I'm pretty new to Qt, so I'm wondering if there's a cleaner way to do this. Looking at ButtonGroups was my first port of call, but I couldn't see any way to make it work.
What I have looks something like this. I want to emphasize - this does exactly what I want it to do - I'm just not sure that it's the best way to do it, and I'd like not to hate myself if I come back to the code in a few months with more knowledge. I'd be entirely unsurprised if there were built-in functionality that accomplished my goals.
self.first_checkbox = QtWidgets.QCheckBox()
self.second_checkbox = QtWidgets.QCheckBox()
self.first_checkbox.stateChanged.connect(self._handleCheckboxStateChanged)
#QtCore.Slot()
def _handleCheckboxStateChange(self):
if self.first_checkbox.isChecked():
self.second_checkbox.setEnabled(True)
else:
self.second_checkbox.setEnabled(False)
self.second_checkbox.setChecked(False)
Your method is correct, my answer just tries to show other equivalent methods:
1.
from PySide2 import QtCore, QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self.first_checkbox = QtWidgets.QCheckBox("Print")
self.second_checkbox = QtWidgets.QCheckBox("color")
self.first_checkbox.stateChanged.connect(
lambda state: self.second_checkbox.setDisabled(
state != QtCore.Qt.Checked
)
)
self.first_checkbox.stateChanged.connect(
lambda state: self.second_checkbox.setCheckState(
QtCore.Qt.Unchecked
)
if not state
else None
)
self.second_checkbox.setDisabled(True)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(self.first_checkbox)
lay.addWidget(self.second_checkbox)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
2.
from PySide2 import QtCore, QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self.first_checkbox = QtWidgets.QCheckBox("Print")
self.second_checkbox = QtWidgets.QCheckBox("color")
self.first_checkbox.stateChanged.connect(
self._handleCheckboxStateChange
)
self.second_checkbox.setDisabled(True)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(self.first_checkbox)
lay.addWidget(self.second_checkbox)
#QtCore.Slot(QtCore.Qt.CheckState)
def _handleCheckboxStateChange(self, state):
self.second_checkbox.setEnabled(state == QtCore.Qt.Checked)
if state != QtCore.Qt.Checked:
self.second_checkbox.setCheckState(QtCore.Qt.Unchecked)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())