Grouping about 100 Radio Buttons - python

I'm trying to create a multiple-choice test with approximately 100 questions in it. In this example, I give you a group of radio buttons. I solved creating multiple radio buttons with this code. However, I want to group these selections.
I found a soultion in this link : https://www.delftstack.com/tutorial/pyqt5/pyqt5-radiobutton/#:~:text=setChecked(True)-,PyQt5%20QRadiobutton%20Group,are%20connected%20to%20different%20functions.
However, they didn't create radio buttons with 'for' loop. What should I do about this?
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5 import QtCore, QtGui, QtWidgets
class Ornek(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.toggles = []
self.lay = QVBoxLayout()
self.h_box = QGridLayout()
for i in range (4):
self.btngroup = QButtonGroup()
for j in range (4):
if j % 4 == 0:
self.btn = QRadioButton("A", self)
elif j % 4 == 1:
self.btn = QRadioButton("B", self)
elif j % 4 == 2:
self.btn = QRadioButton("C", self)
else:
self.btn = QRadioButton("D", self)
text = self.btn.text()
self.btn.clicked.connect(lambda ch, text=text: print("\nclicked--> {}".format(text)))
self.h_box.addWidget(self.btn,i,j,1,1)
self.lay.addLayout(self.h_box)
self.setLayout(self.lay)
self.setGeometry(300,300,250,250)
self.setWindowTitle("Çıkış Projesi")
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
pencere = Ornek()
sys.exit(app.exec_())

You have created a QButtonGroup but you don't use it, your code can be rewritten as:
def initUI(self):
self.toggles = []
lay = QVBoxLayout(self)
h_box = QGridLayout()
lay.addLayout(h_box)
for i in range(4):
btngroup = QButtonGroup(self)
btngroup.buttonClicked.connect(lambda btn: print(btn.text()))
for j in range(4):
btn = QRadioButton()
btngroup.addButton(btn)
h_box.addWidget(btn, i, j, 1, 1)
if j % 4 == 0:
btn.setText("A")
elif j % 4 == 1:
btn.setText("B")
elif j % 4 == 2:
btn.setText("C")
else:
btn.setText("D")
self.setGeometry(300, 300, 250, 250)
self.setWindowTitle("Çıkış Projesi")
self.show()

Related

Pyside/Pyqt5 dynamically adding and sorting items

I have a simple user interface where I want to dynamically add frames and labels in a widget (as I will use these labels to transmit a video feed from my webcams).
In the following code I set a function where the user selects an integer which represents the number of labels(webcams) they want to see and then dynamically adds these labels& frames to the widget:
def loopCamFeed(self,n):
if (n % 2) == 0:
dividnd = n / 2
for i in range(2):
self.frame_12 = QFrame(self.ui.webcamWidget)
self.frame_12.setObjectName(u"frame_12")
self.frame_12.setFrameShape(QFrame.StyledPanel)
self.frame_12.setFrameShadow(QFrame.Raised)
self.horizontalLayout_14 = QHBoxLayout(self.frame_12)
self.horizontalLayout_14.setObjectName(u"horizontalLayout_14")
for i in range(int(dividnd)):
self.label_5 = QLabel("hello",self.frame_12)
self.label_5.setObjectName(u"label_5")
self.horizontalLayout_14.addWidget(self.label_5, 0, Qt.AlignHCenter)
self.ui.verticalLayout_15.addWidget(self.frame_12)
Which displays the labels as in the image below:
--By adding a value of 2:
--By adding a value of 4):
By adding a value of 8:
The challenge that I am facing is how to handle an odd number selection. For example, if a user selects 3 or 7 webcams/labels.
If a user selects 3 labels/webcams, I'd want to show one on the top frame and two at the bottom.
MAIN.PY (Where this piece of code was written):
from ui_interface import *
import sys
from Custom_Widgets.Widgets import *
import cv2
import numpy as np
from PyQt5.QtCore import pyqtSignal, QObject, QThread
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
loadJsonStyle(self, self.ui)
self.show()
#Expand Center Menu Widget
self.ui.settingsBtn.clicked.connect(lambda: self.ui.centerMenuContainer.expandMenu())
self.ui.infoBtn.clicked.connect(lambda: self.ui.centerMenuContainer.expandMenu())
self.ui.helpBtn.clicked.connect(lambda: self.ui.centerMenuContainer.expandMenu())
#Close Center Menu Widget
self.ui.closeCenterMenuButton.clicked.connect(lambda: self.ui.centerMenuContainer.collapseMenu())
#Close Notification Menu Widget
self.ui.closeNotificationBtn.clicked.connect(lambda: self.ui.popUpNotificationContainer.collapseMenu())
self.loopCamFeed(4)
def ImageUpdateSlot(self, Image):
self.ui.label_5.setPixmap(QPixmap.fromImage(Image))
def CancelFeed(self):
self.worker1.stop()
def startVideo(self):
self.worker1 = Worker1()
self.worker1.start()
self.worker1.ImageUpdate.connect(self.ImageUpdateSlot)
def loopCamFeed(self,n):
if (n % 2) == 0:
dividnd = n / 2
for i in range(2):
self.frame_12 = QFrame(self.ui.webcamWidget)
self.frame_12.setObjectName(u"frame_12")
self.frame_12.setFrameShape(QFrame.StyledPanel)
self.frame_12.setFrameShadow(QFrame.Raised)
self.horizontalLayout_14 = QHBoxLayout(self.frame_12)
self.horizontalLayout_14.setObjectName(u"horizontalLayout_14")
for i in range(int(dividnd)):
self.label_5 = QLabel("hello",self.frame_12)
self.label_5.setObjectName(u"label_5")
self.horizontalLayout_14.addWidget(self.label_5, 0, Qt.AlignHCenter)
self.ui.verticalLayout_15.addWidget(self.frame_12)
class Worker1(QThread):
ImageUpdate = pyqtSignal(QImage)
def __init__(self):
super().__init__()
def run(self):
self.ThreadActive = True
Capture = cv2.VideoCapture(0)
while self.ThreadActive:
ret, frame = Capture.read()
if ret:
Image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
FlippedImage = cv2.flip(Image, 1)
ConvertToQtFormat = QImage(FlippedImage.data, FlippedImage.shape[1], FlippedImage.shape[0], QImage.Format_RGB888)
Pic = ConvertToQtFormat.scaled(1200, 900, Qt.KeepAspectRatio)
self.ImageUpdate.emit(Pic)
def stop(self):
self.ThreadActive = False
self.quit()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
Use a grid layout instead of a horizontal layout:
def loopCamFeed(self,n):
self.frame_12 = QFrame(self.ui.webcamWidget)
self.frame_12.setObjectName(u"frame_12")
self.frame_12.setFrameShape(QFrame.StyledPanel)
self.frame_12.setFrameShadow(QFrame.Raised)
self.grid_layout = QGridLayout(self.frame_12)
self.grid_layout.setObjectName(u"grid_layout")
for i in range(int(n)):
self.label_5 = QLabel("hello",self.frame_12)
self.label_5.setObjectName(u"label_5")
self.grid_layout.addWidget(self.label_5, 0, Qt.AlignHCenter)
self.ui.verticalLayout_15.addWidget(self.frame_12)
As Medhat mentioned, applying the GridLayout was the best solution.
I applied the following code:
def loopCamFeed(self,n):
w = 0
if n > 0:
# if ( n % 2) == 0:
for i in range(int(n)):
if (i%2) == 0:
w +=1
print(int(w / 2), (i%2))
self.label = QtWidgets.QLabel()
self.label.setText("Screen " +str(i))
self.label.setStyleSheet("background-color: black5;")
self.label.setObjectName(u"label")
self.gridLayout.addWidget(self.label, (i%2) ,int(w),Qt.AlignHCenter )
This works perfectly! Thanks #Medhat

Clearing Grid Layout in scroll area

I have a grid layout that's inside a scroll area. I want to have 5 columns and 200 rows maximum at a time. When a grid item is clicked I want to remove all items in the grid and add new ones.
However, when I start with around 50 items(10x5) and add 1000(200x5) items after clearing the first 50 nothing shows up on the screen. I assume it is because they are too small.
If I do 750(150x5) they show up very small.
The issue is that if I start with 1000 items everything looks how they should be.
Below is my reproducible example to my problem.
import sys
from PySide2.QtWidgets import *
from PySide2.QtGui import *
from PySide2.QtCore import *
class GridButton(QPushButton):
def __init__(self, parent, tab, grid) -> None:
super().__init__(parent)
self.tab = tab
self.grid = grid
self.grid_wid = parent
def onclick(self):
self.tab.clear()
for i in range(150):
for j in range(5):
btn = GridButton(self.grid_wid, self.tab, self.grid)
btn.setText(f"nButton: {i}")
btn.clicked.connect(btn.onclick)
self.grid.addWidget(btn, i, j)
class Test(QWidget):
def __init__(self, parent) -> None:
super().__init__(parent)
self.sc = QScrollArea(self)
self.sc.setGeometry(0, 0, 1024, 600)
self.grid_wid = QWidget()
self.grid = QGridLayout(self.grid_wid)
for i in range(10):
for j in range(5):
btn = GridButton(self.grid_wid, self, self.grid)
btn.setText(f"Button: {i}")
btn.clicked.connect(btn.onclick)
self.grid.addWidget(btn, i, j)
self.sc.setWidget(self.grid_wid)
def clear(self):
for i in reversed(range(self.grid.count())):
widgetToRemove = self.grid.itemAt(i).widget()
widgetToRemove.setParent(None)
widgetToRemove.deleteLater()
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.tabs = Test(self)
self.setWindowTitle("GUI")
self.setFixedSize(QSize(1024, 600))
self.setCentralWidget(self.tabs)
self.show()
def main():
app = QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
From #CarlHR's answer:
self.sc.setWidgetResizable(True)

How can I add pyqt5 buttons on top of each other?

I am trying to create a basic 25 key keyboard in pyqt, I have laid out the 15 white keys but am struggling with how to add the 10 remaining black keys,
This is how I made my keys
from PyQt5.QtWidgets import QApplication, QPushButton
app = QApplication([])
top_win = QWidget()
set_color(top_win, Qt.cyan)
top_win.setAutoFillBackground(True)
top_win.show()
top_win.resize(1920,1080)
top_win.setWindowTitle("Synth-01")
top_vlayout = QVBoxLayout()
top_win.setLayout(top_vlayout)
keyboard = QWidget()
keyboard.setMaximumWidth(1410)
top_vlayout.addWidget(keyboard)
keyboard_layout = QHBoxLayout()
keyboard.setAutoFillBackground(True)
keyboard.setLayout(keyboard_layout)
for i in range(15):
name = "key_" + str(i)
name = QPushButton()
name.setMaximumWidth(94)
name.setMaximumHeight(349)
keyboard_layout.addWidget(name)
I now want to add the black keys inbetween like this
In this case, it is most preferable to use QGraphicsScene with QGraphicsItem, for this case I will use svg:
from PyQt5 import QtCore, QtGui, QtWidgets, QtSvg
class PianoKey(QtWidgets.QGraphicsRectItem):
def __init__(self, black=False, rect = QtCore.QRectF(), parent=None):
super(PianoKey, self).__init__(rect, parent)
self.m_pressed = False
self.m_selectedBrush = QtGui.QBrush()
self.m_brush = QtGui.QBrush(QtCore.Qt.black) if black else QtGui.QBrush(QtCore.Qt.white)
self.m_black = black
def setPressedBrush(self, brush):
self.m_selectedBrush = brush
def paint(self, painter, option, widget):
rendered = QtSvg.QSvgRenderer("key.svg")
black_pen = QtGui.QPen(QtCore.Qt.black, 1)
gray_pen = QtGui.QPen(QtGui.QBrush(QtCore.Qt.gray), 1,
QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin)
if self.m_pressed:
if self.m_selectedBrush.style() != QtCore.Qt.NoBrush:
painter.setBrush(self.m_selectedBrush)
else:
painter.setBrush(QtWidgets.QApplication.palette().highlight())
else:
painter.setBrush(self.m_brush);
painter.setPen(black_pen)
painter.drawRoundedRect(self.rect(), 15, 15, QtCore.Qt.RelativeSize)
if self.m_black:
rendered.render(painter, self.rect())
else:
points = [
QtCore.QPointF(self.rect().left()+1.5, self.rect().bottom()-1),
QtCore.QPointF(self.rect().right()-1, self.rect().bottom()-1),
QtCore.QPointF(self.rect().right()-1, self.rect().top()+1)
]
painter.setPen(gray_pen)
painter.drawPolyline(QtGui.QPolygonF(points))
def mousePressEvent(self, event):
self.m_pressed = True
self.update()
super(PianoKey, self).mousePressEvent(event)
event.accept()
def mouseReleaseEvent(self, event):
self.m_pressed = False
self.update()
super(PianoKey, self).mouseReleaseEvent(event)
KEYWIDTH, KEYHEIGHT = 18, 72
class PianoKeyBoard(QtWidgets.QGraphicsView):
def __init__(self, num_octaves=2, parent=None):
super(PianoKeyBoard, self).__init__(parent)
self.initialize()
self.m_numOctaves = num_octaves
scene = QtWidgets.QGraphicsScene(QtCore.QRectF(0, 0, KEYWIDTH * self.m_numOctaves * 7, KEYHEIGHT), self)
self.setScene(scene)
numkeys = self.m_numOctaves * 12
for i in range(numkeys):
octave = i//12*7
j = i % 12
if j >= 5: j += 1
if j % 2 == 0:
x = (octave + j/2)*KEYWIDTH
key = PianoKey(rect=QtCore.QRectF(x, 0, KEYWIDTH, KEYHEIGHT), black=False)
else:
x = (octave + j//2) * KEYWIDTH + KEYWIDTH * 6//10 + 1
key = PianoKey(rect=QtCore.QRectF(x, 0, KEYWIDTH * 8//10 - 1, KEYHEIGHT * 6//10 ), black=True)
key.setZValue(1)
key.setPressedBrush(QtWidgets.QApplication.palette().highlight())
self.scene().addItem(key)
def initialize(self):
self.setAttribute(QtCore.Qt.WA_InputMethodEnabled, False)
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setCacheMode(QtWidgets.QGraphicsView.CacheBackground)
self.setViewportUpdateMode(QtWidgets.QGraphicsView.MinimalViewportUpdate)
self.setRenderHints(QtGui.QPainter.Antialiasing|
QtGui.QPainter.TextAntialiasing |
QtGui.QPainter.SmoothPixmapTransform)
self.setOptimizationFlag(QtWidgets.QGraphicsView.DontClipPainter, True)
self.setOptimizationFlag(QtWidgets.QGraphicsView.DontSavePainterState, True)
self.setOptimizationFlag(QtWidgets.QGraphicsView.DontAdjustForAntialiasing, True)
self.setBackgroundBrush(QtWidgets.QApplication.palette().base())
def resizeEvent(self, event):
super(PianoKeyBoard, self).resizeEvent(event)
self.fitInView(self.scene().sceneRect(), QtCore.Qt.KeepAspectRatio)
def sizeHint(self):
return self.mapFromScene(self.sceneRect()).boundingRect().size()
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
app.setStyle('fusion')
w = QtWidgets.QWidget()
lay = QtWidgets.QVBoxLayout(w)
lay.addWidget(QtWidgets.QLabel("Piano Keyboard", alignment=QtCore.Qt.AlignCenter))
lay.addWidget(PianoKeyBoard())
w.resize(640, 480)
w.show()
sys.exit(app.exec_())
The complete code + key.svg can be found on this link

How to add list of dictionary key data items into QTableWidget using pyqt4

Here is my code,i want to add my list of items into qtabl widget in one key i have a list of items when i want to add my list of items in to qtable widget i am getting the problem i.e my last items is overriding the previous item because of the idx index in columns.i tried many ways but i not able to all the items in qtable widget.
Given below is my sample tried code:
from PyQt4 import QtCore, QtGui
from functools import partial
import os, sys
import time
from datetime import datetime
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
self.data_arraylist = {'85207':[{'item1':"Fruites", 'Qty':'10','Price':'100','total':'100'},{'item1':"Banana", 'Qty':'20','Price':'200','total':'200'}],'97895':{'item1':"vegitables", 'Qty':'2kg','Price':'200','total':'200'},'97055':{'item1':"snacks", 'Qty':'10p','Price':'200','total':'200'}}
super(MainWindow, self).__init__(parent)
self.dataw = QtGui.QWidget()
self._gridlayout = QtGui.QGridLayout()
self.vboxdata = QtGui.QVBoxLayout(self.dataw)
self.scrollArea = QtGui.QScrollArea()
self.vboxdata.addWidget(self.scrollArea)
self.scrollArea.setWidgetResizable(True)
self.vbox = QtGui.QVBoxLayout()
self.hbox1 = QtGui.QHBoxLayout()
self.timelabel = QtGui.QLabel()
self.orderbtn = QtGui.QPushButton("Orders")
self.newbtn = QtGui.QPushButton("New")
self.newbtn.clicked.connect(self.items_list)
self.hbox1.addWidget(self.timelabel)
self.hbox1.addWidget(self.orderbtn)
self.hbox1.addWidget(self.newbtn)
self.vbox.addLayout(self.hbox1)
self.mainLayout = QtGui.QGridLayout()
self.mainLayout.addWidget(self.dataw, 0, 0)
self.mainLayout.addLayout(self.vbox, 1, 0)
self.setCentralWidget(QtGui.QWidget(self))
self.centralWidget().setLayout(self.mainLayout)
def items_list(self):
self.mainw2 = QtGui.QWidget()
self.scrollArea.setWidget(self.mainw2)
self.newvbox = QtGui.QVBoxLayout(self.mainw2)
self.linedit = QtGui.QLineEdit()
self.search = QtGui.QLabel("Search")
self.newhbox = QtGui.QHBoxLayout()
self.newhbox.addWidget(self.linedit)
self.newhbox.addWidget(self.search)
self.newvbox.addLayout(self.newhbox)
self.table = QtGui.QTableWidget()
self.table_item = QtGui.QTableWidgetItem()
self.table.setRowCount(5)
self.table.verticalHeader().hide()
self.table.setColumnCount(5)
self.table.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
self.table.setHorizontalHeaderLabels(("S.no, Item Description,Qty,Rate(Rs:),Total").split(','))
self.newvbox.addWidget(self.table)
def keyPressEvent(self, event):
print event,event.key(),QtCore.Qt.Key_Return
if event.key() == QtCore.Qt.Key_Return:
text_key = self.linedit.text()
self.searchitems(text_key)
def searchitems(self,text_key):
if str(text_key) in self.data_arraylist:
for ridx,row in enumerate(range(1)):
for idx, column in enumerate(range(5)):
if idx ==0:
self.table.setItem(row,column,QtGui.QTableWidgetItem(str(ridx+1)))
elif idx ==1:
for i in range(len(self.data_arraylist[str(text_key)])):
self.table.setItem(row,column,QtGui.QTableWidgetItem(
str(self.data_arraylist[str(text_key)][i][
'item1'])))
elif idx ==2:
for i in range(len(self.data_arraylist[str(text_key)])):
self.table.setItem(row,column,
QtGui.QTableWidgetItem(str(
self.data_arraylist[str(
text_key)][i]['Qty'])))
elif idx ==3:
for i in range(len(self.data_arraylist[str(text_key)])):
self.table.setItem(row,column,QtGui.QTableWidgetItem(str(self.data_arraylist[str(text_key)][i]['Price'])))
elif idx ==4:
for i in range(len(self.data_arraylist[str(text_key)])):
self.table.setItem(row,column,QtGui.QTableWidgetItem(str(self.data_arraylist[str(text_key)][i]['total'])))
else:
pass
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.show()
w.setGeometry(500,500,800,400)
sys.exit(app.exec_())

How to set property of QTextCharFormat in PyQt?

I am trying to set a custom property of an image inserted into a QTextEdit. I have the following example code which sets then outputs the value of the property to the terminal:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
class TestEditor(QWidget):
def __init__(self):
QWidget.__init__(self)
layout = QVBoxLayout()
self.setLayout(layout)
self.layout().setSpacing(0)
self.layout().setContentsMargins(0, 0, 0, 0)
self.textEdit = QTextEdit()
self.layout().addWidget(self.textEdit)
document = self.textEdit.document()
cursor = QTextCursor(document)
cursor.insertImage("./testimage.png")
f = cursor.charFormat()
print(f)
prop_id = 0x100000 + 1
f.setProperty(prop_id, 100)
print(f.intProperty(prop_id))
print('------')
block = document.firstBlock()
while block.length() > 0:
print(block)
it = block.begin()
while not it.atEnd():
f = it.fragment()
fmt = f.charFormat()
print(fmt)
print(fmt.intProperty(prop_id))
it += 1
block = block.next()
class TestWindow(QWidget):
def __init__(self):
QWidget.__init__(self)
self.initUi()
def initUi(self):
layout = QVBoxLayout()
layout.addWidget(HextEditor())
self.setLayout(layout)
self.layout().setSpacing(0)
self.layout().setContentsMargins(0, 0, 0, 0)
self.setWindowTitle('button tooltip')
self.show()
def main():
app = QApplication(sys.argv)
window = TestWindow()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
The program results in an output of:
<PyQt5.QtGui.QTextCharFormat object at 0x107109ba8>
100
------
<PyQt5.QtGui.QTextBlock object at 0x105448318>
<PyQt5.QtGui.QTextCharFormat object at 0x107109ba8>
0
Note that the second time the value is gotten it has a value of 0 rather than 100. It even appears to be the same instance of a QTextCharFormat. How would I accomplish something like this? Am I missing something simple here?
I solved this by saving the range of the inserted image, selecting it, and using QTextCursor.setCharFormat() to save the changes:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
class TestEditor(QWidget):
def __init__(self):
QWidget.__init__(self)
layout = QVBoxLayout()
self.setLayout(layout)
self.layout().setSpacing(0)
self.layout().setContentsMargins(0, 0, 0, 0)
self.textEdit = QTextEdit()
self.layout().addWidget(self.textEdit)
document = self.textEdit.document()
cursor = QTextCursor(document)
# Save the position of the beginning and end of the inserted image
p1 = cursor.position()
cursor.insertImage("./testimage.png")
p2 = cursor.position()
f = cursor.charFormat()
print(f)
prop_id = 0x100000 + 1
f.setProperty(prop_id, 100)
# Select the inserted fragment and apply format
cursor.setPosition(p1)
cursor.setPosition(p2, QTextCursor.KeepAnchor)
cursor.setCharFormat(f)
print(f.intProperty(prop_id))
print('------')
block = document.firstBlock()
while block.length() > 0:
print(block)
it = block.begin()
while not it.atEnd():
f = it.fragment()
fmt = f.charFormat()
print(fmt)
print(fmt.intProperty(prop_id))
it += 1
block = block.next()
class TestWindow(QWidget):
def __init__(self):
QWidget.__init__(self)
self.initUi()
def initUi(self):
layout = QVBoxLayout()
layout.addWidget(TestEditor())
self.setLayout(layout)
self.layout().setSpacing(0)
self.layout().setContentsMargins(0, 0, 0, 0)
self.setWindowTitle('button tooltip')
self.show()
def main():
app = QApplication(sys.argv)
window = TestWindow()
sys.exit(app.exec_())
if __name__ == '__main__':
main()

Categories