I get to POO, python and PyQt slowly and I have a problem to understand something about passing argument and attributes.
I found online a code dealing with QTreeView (see below) and I don't understand how Index is passed into showPath(). Also why self.filename and self.filepath are not passed to the instance?
I hope I am clear enough ... Thank a lot.
from PyQt4 import QtGui
class TreeViewWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(TreeViewWidget, self).__init__(parent)
self.model = QtGui.QFileSystemModel(self)
self.model.setRootPath(rootpath)
self.indexRoot = self.model.index(self.model.rootPath())
self.treeView = QtGui.QTreeView(self)
self.treeView.setExpandsOnDoubleClick(False)
self.treeView.setModel(self.model)
self.treeView.setRootIndex(self.indexRoot)
self.treeView.setColumnWidth(0,220)
self.treeView.clicked.connect(self.showPath)
self.treeView.doubleClicked.connect(self.openQuickLook)
self.labelFileName = QtGui.QLabel(self)
self.labelFileName.setText("File Name:")
self.lineEditFileName = QtGui.QLineEdit(self)
self.labelFilePath = QtGui.QLabel(self)
self.labelFilePath.setText("File Path:")
self.lineEditFilePath = QtGui.QLineEdit(self)
self.gridLayout = QtGui.QGridLayout()
self.gridLayout.addWidget(self.labelFileName, 0, 0)
self.gridLayout.addWidget(self.lineEditFileName, 0, 1)
self.gridLayout.addWidget(self.labelFilePath, 1, 0)
self.gridLayout.addWidget(self.lineEditFilePath, 1, 1)
self.layout = QtGui.QVBoxLayout(self)
self.layout.addLayout(self.gridLayout)
self.layout.addWidget(self.treeView)
def givePathName(self, index):
indexItem = self.model.index(index.row(), 0, index.parent())
self.filename = self.model.fileName(indexItem)
self.filepath = self.model.filePath(indexItem)
def showPath(self, index):
self.givePathName(index)
self.lineEditFileName.setText(self.filename)
self.lineEditFilePath.setText(self.filepath)
I don't understand how index is passed into showPath()
You connect the widget's click signal to showPath explicitly:
self.treeView.clicked.connect(self.showPath)
part of this signal is the index of the specific item clicked on; this is passed as an argument to showPath automatically.
Also why self.filename and self.filepath are not passed to the instance?
They are instance attributes, they belong to the instance and are accessible to all methods of that instance. They are created in givePathName(), and are then part of the TreeViewWidget instance object. They start with self. because that is, by convention, the name given to the instance in instance methods (and the implicit first argument to those methods).
Putting that together:
def showPath(self, index):
# ^ the instance object, so you can access its attributes
# ^ the index of the specific item clicked
The clicked signal of your QTreeView pass the QModelIndex of the item clicked as an argument to any connected slots.
See Qt Documentation and PyQt signal and slots documentation.
Related
This is the code
Entrypoint.py
def Data_For_MakePdf_Db(self):
mese = self.MakePdf_Strip_Month_select.currentText()
anno = self.MakePdf_Strip_Year_select.currentText()
MakeStrip(anno, mese)
return ### Breakpoint here
and MakeStrip.py
class SpecialStyledItemDelegate(QtWidgets.QStyledItemDelegate):
def __init__(self, parent=None):
super().__init__(parent)
self._values = dict()
def add_text(self, text, row):
self._values[row] = text
def initStyleOption(self, option, index):
super().initStyleOption(option, index)
row = index.row()
if row in self._values:
option.text = self._values[row]
option.displayAlignment = QtCore.Qt.AlignCenter
class MakeStrip(QtWidgets.QWidget):
def __init__(self, anno, mese):
super().__init__()
self.initUI(anno, mese)
def initUI(self, anno, mese):
self.title = "MAMbo - Strips di '%s' '%s' "%(mese, anno)
self.setWindowTitle(self.title)
self.setGeometry(50, 100, 900, 800)
self.callTable(anno, mese)
self.button = QtWidgets.QPushButton(self.tableWidget)
self.button.setGeometry(QtCore.QRect(440, 169, 70, 20))
self.button.setObjectName("button")
self.button.setText("close")
self.layout = QtWidgets.QHBoxLayout(self)
self.layout.addWidget(self.tableWidget)
self.show()
self.button.clicked.connect(self.on_click)
pippo = 0 ### Breakpoint here
def on_click(self):
print('Clicked')
# Functions.message_handler(message = "THIS WILL CLOSE THE APP")
return
def callTable(self, anno, mese):
# Create table
self.tableWidget = QtWidgets.QTableWidget()
self.tableWidget.move(100, 700)
self.tableWidget.setRowCount(33)
self.tableWidget.setColumnCount(3)
self.special_delegate = SpecialStyledItemDelegate()
self.tableWidget.setItemDelegate(self.special_delegate)
h_header = self.tableWidget.horizontalHeader()
h_header.hide()
for i in range(h_header.count()):
h_header.setSectionResizeMode(i, QtWidgets.QHeaderView.ResizeToContents)
v_header = self.tableWidget.verticalHeader()
v_header.hide()
v_header.setDefaultSectionSize(13)
self.tableWidget.setSpan(1, 0, 1, 3)
self.tableWidget.setSpan(0, 0, 1, 3)
...
pluto = 0
def on_click(self):
print('Clicked')
return
I use pycharm
Main problem
If I run the script I see for a fraction of second the result of Makescript even if there a push button
Alternative problem
If I debug it I need to put some breakpoints as shown in the scripts to see the result of the script
I know that the debugger keeps alive the connection but why do I need to put breakpoints in those positions to see the result?
The problem is in the following line:
MakeStrip(anno, mese)
What happens there is that you create an instance of MakeStrip which has absolutely no reference. The result is that it's created and immediately garbage collected as soon as its __init__ returns.
Imagine doing something like this:
def Data_For_MakePdf_Db(self):
list()
As soon as no reference to an object is left, python automatically destroys it. In the case above, you create an instance without any reference, so it gets immediately deleted.
Note that creating a local reference (a variable that exists only in the function) might be a solution, but since there is no locking, you'll have almost the same results, because the function will immediately returns, causing the instance to be destroyed as well:
def Data_For_MakePdf_Db(self):
strip = MakeStrip(anno, mese)
A possibility is to create a persistent reference, by making the object a member of the current instance:
def Data_For_MakePdf_Db(self):
self.strip = MakeStrip(anno, mese)
This has some, possibly unwanted, side effects: first of all, you could still switch between the current window to the new one (which will probably make things a bit confusing), and, most importantly, if you call Data_For_MakePdf_Db again while another MakeStrip window already exists, it will be probably destroyed and replaced by a new one.
A better and more consistent solution is to have MakeStrip a subclass of QDialog instead, and use its exec_(): it will make it a modal window and will return control only when the window is finally closed.
def Data_For_MakePdf_Db(self):
MakeStrip(self, anno, mese).exec_()
class MakeStrip(QtWidgets.QDialog):
def __init__(self, parent, anno, mese):
super().__init__(parent)
self.initUI(anno, mese)
def initUI(self, anno, mese):
# ...
self.button.clicked.connect(self.accept)
Note that in this specific case we can even create the dialog without the local or instance reference, thanks to the fact that exec_ creates an event loop that blocks the execution until the dialog is closed.
This is always a good idea, though, as you might need to know if the dialog was actually "accepted" or "rejected", or need access to some of the dialog's objects.
In that case, a local reference is required:
def Data_For_MakePdf_Db(self):
dialog = MakeStrip(<b>self</b>, anno, mese)
if dialog.exec_():
print(dialog.tableWidget.rowCount())
PS: capitalized names should always be used only for classes and constants, not for functions, so it should be data_for_MakePdf_Db; while you can name your function as you like, this standard convention is highly suggested, as it improves readability (it makes clear distinction between classes and functions). Read more on the official Style Guide for Python Code.
I have a class that Extends QWidget and this class contains multiple child's(QWidget, QLabel).
in the __init__ function of this class, I instantiate the View and fill the labels all of that works fine from another data source object from a singleton class.
now the problem is that I want when I change the value of the data source object the UI should reflect it.
I already tried
self.update()
but not working.
class HomeInterface(QWidget):
def __init__(self, parent: QWidget = None):
super(HomeInterface, self).__init__(parent)
self.setGeometry(QRect(0, 0, parent.width() - 30 - 30, 500))
self.setAttribute(Qt.WA_StyledBackground) # Used For Setting Style on Super Class
self.setObjectName("HomeInterface")
self.setStyleSheet(Styles.HOME_INTERFACE)
self.__createUI()
def __createUI(self):
builderWidget: QWidget = QWidget(self)
builderWidget.setGeometry(20, 30, self.width() - 20 - 20, 50)
myLabel: QLabel = QLabel(parent=builderWidget)
myLabel.setText(myCustomClass.getInstance().getMyTextValue())
myEditBtn: QPushButton = QPushButton(parent=builderWidget)
myEditBtn.clicked.connect(lambda: self.__changeVarValue())
def __changeVarValue(self):
myCustomClass.getInstance().setMyTextValue("New Text Value")
#TODO the UI Should reflect the changes in the variable
I want to design a custom ListView widget which has custom items similar to this:
https://i.stack.imgur.com/iTNbN.png
However, the qt documentation and some stackoverflow posts state that one should ideally use a QStyleItemDelegate. I never worked with 'delegates' before but as far as I understood from my research they are called by the ListView for drawing / rendering each item.
I found a delegate example in another project (https://github.com/pyblish/pyblish-lite/blob/master/pyblish_lite/delegate.py) and they draw everything by hand / are essentially rebuilding entire widgets by painting rectangles.
This seems a bit impractical for me as most of the time custom item widgets can be compounds of existing widgets. Take a look at the screenshot above. It essentially contains a Qlabel, QPixmap, and four DoubleSpinBoxes.
Question: How would you use the painting / rendering methods that already exist in them instead of manually painting everything on your own?
That way you can profit from existing member methods and can use layouts for structuring your widget.
For example the first ListViewItem should pass the model data to the delegate so that the text of the self.lightGroupName QLabel can be set to "Light1".
Any help is greatly appreciated, since I have no idea how to go on from here:
from PySide2 import QtCore, QtGui, QtWidgets
class LightDelagate(QtWidgets.QStyledItemDelegate): #custom item view
def __init__(self, parent=None):
super(LightDelagate, self).__init__(parent)
self.setupUI()
def setupUI(self):
self.masterWidget = QtWidgets.QWidget()
#Light Group Header
self.hlayLightHeader = QtWidgets.QHBoxLayout()
self.lightGroupName = QtWidgets.QLabel("Checker")
self.hlayLightHeader.addWidget(self.lightGroupName)
#Light AOV Preview
self.lightPreview = QtWidgets.QLabel()
#set size
self.aovThumbnail = QtGui.QPixmap(180, 101)
#self.lightPreview.setPixmap(self.aovThumbnail.scaled(self.lightPreview.width(), self.lightPreview.height(), QtCore.Qt.KeepAspectRatio))
# #Color Dials
# self.hlayColorDials = QtWidgets.QHBoxLayout()
# self.rgbDials = QtWidgets.QHBoxLayout()
# self.rDial = QtWidgets.QDoubleSpinBox()
# self.rDial.setButtonSymbols(QtWidgets.QAbstractSpinBox.NoButtons)
# self.gDial = QtWidgets.QDoubleSpinBox()
# self.gDial.setButtonSymbols(QtWidgets.QAbstractSpinBox.NoButtons)
# self.bDial = QtWidgets.QDoubleSpinBox()
# self.bDial.setButtonSymbols(QtWidgets.QAbstractSpinBox.NoButtons)
# self.rgbDials.addWidget(self.rDial)
# self.rgbDials.addWidget(self.gDial)
# self.rgbDials.addWidget(self.bDial)
# #Exposure
# self.hlayExposureDials = QtWidgets.QHBoxLayout()
# self.exposureDial = QtWidgets.QDoubleSpinBox()
# self.exposureDial.setButtonSymbols(QtWidgets.QAbstractSpinBox.NoButtons)
# self.hlayExposureDials.addWidget(self.exposureDial)
# self.hlayColorDials.addLayout(self.rgbDials)
# self.hlayColorDials.addLayout(self.hlayExposureDials)
#entire layout
self.vlayWidget = QtWidgets.QVBoxLayout()
self.vlayWidget.addLayout(self.hlayLightHeader)
self.vlayWidget.addWidget(self.lightPreview)
# self.vlayWidget.addLayout(self.hlayColorDials)
self.vlayWidget.setContentsMargins(2,2,2,2)
self.vlayWidget.setSpacing(2)
self.masterWidget.setLayout(self.vlayWidget)
def paint(self, painter, option, index):
rowData = index.model().data(index, QtCore.Qt.DisplayRole)
self.lightGroupName.setText(rowData[0])
print (option.rect)
painter.drawRect(option.rect)
painter.drawText()
def sizeHint(self, option, index):
return QtCore.QSize(200, 150)
class LightListModel(QtCore.QAbstractListModel): #data container for list view
def __init__(self, lightList= None):
super(LightListModel, self).__init__()
self.lightList = lightList or []
#reimplement
def rowCount(self, index):
return len(self.lightList)
def data(self, index, role):
if role == QtCore.Qt.DisplayRole:
lightGroupData = self.lightList[index.row()]
return lightGroupData
class LightListView(QtWidgets.QListView): #
def __init__(self):
super(LightListView, self).__init__()
self.setFlow(QtWidgets.QListView.LeftToRight)
self.setItemDelegate(LightDelagate(self))
self.setMinimumWidth(1880)
lightListTest = [
('Light1' , {'lightList' : [], 'lightColor': (0,0,0), 'mod_exposure': 1, 'mod_color' : (0,0,0)}),
('Light2' , {'lightList' : [], 'lightColor': (0,0,0), 'mod_exposure': 1, 'mod_color' : (0,0,0)}),
('Light3' , {'lightList' : [], 'lightColor': (0,0,0), 'mod_exposure': 1, 'mod_color' : (0,0,0)}),
('Light4' , {'lightList' : [], 'lightColor': (0,0,0), 'mod_exposure': 1, 'mod_color' : (0,0,0)})
]
app = QtWidgets.QApplication([])
LLV = LightListView()
model = LightListModel(lightList=lightListTest)
LLV.setModel(model)
LLV.show()
LLV.setSe
app.exec_()
Instead of QListView, could you use QListWidget and override itemWidget? The idea would be that this lets you return a QWidget (with children as per your screenshot) instead of having to implement a QStyledItemDelegate that calls each child widget's paint method.
I have a Qgroupbox which contains Qcombobox with Qlabels, I want to select a value from Qcombobox and display the value as Qlabel. I have the complete code, even I do print value before and after within function every thing works as it should, Only display setText wont set text to Qlabel and update it.
Current screen
What I want
I've corrected signal code, when Qgroupbox in it Qcombobox appears or value would be changed, self.activation.connect(......) would emit an int of the index. to ensure that would work I print it-value inside the def setdatastrength(self, index), see figure below indeed it works, then argument would be passed to function self.concreteproperty.display_condata(it) would be called and do a print of value inside def display_condata(self, value) to make sure about value passing, as shown figure below, it does work. This line code self.con_strength_value.setText(fmt.format(L_Display))
wont assign value to Qlabel.
The script
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class secondtabmaterial(QtWidgets.QWidget):
def __init__(self, parent=None):
super(secondtabmaterial, self).__init__(parent)
self.concretewidgetinfo = ConcreteStrengthInFo()
Concrete_Group = QtWidgets.QGroupBox(self)
Concrete_Group.setTitle("&Concrete")
Concrete_Group.setLayout(self.concretewidgetinfo.grid)
class ConcreteStrengthComboBox(QtWidgets.QComboBox):
def __init__(self, parent = None):
super(ConcreteStrengthComboBox, self).__init__(parent)
self.addItems(["C12/15","C16/20","C20/25","C25/30","C30/37","C35/45"
,"C40/50","C45/55","C50/60","C55/67","C60/75","C70/85",
"C80/95","C90/105"])
self.setFont(QtGui.QFont("Helvetica", 10, QtGui.QFont.Normal, italic=False))
self.compressive_strength = ["12","16","20","25","30","35","40",
"45","50","55","60","70","80","90"]
class ConcreteProperty(QtWidgets.QWidget):
def __init__(self, parent=None):
super(ConcreteProperty, self).__init__(parent)
self.setFont(QtGui.QFont("Helvetica", 10, QtGui.QFont.Normal, italic=False))
concretestrength_lay = QtWidgets.QHBoxLayout(self)
fctd = "\nfcd\n\nfctd\n\nEc"
con_strength = QtWidgets.QLabel(fctd)
self.con_strength_value = QtWidgets.QLabel(" ")
concretestrength_lay.addWidget(con_strength)
concretestrength_lay.addWidget(self.con_strength_value, alignment=QtCore.Qt.AlignRight)
self.setLayout(concretestrength_lay)
#QtCore.pyqtSlot(int)
def display_condata(self, value):
try:
L_Display = str(value)
print("-------- After ------")
print(L_Display, type(L_Display))
fmt = "{}mm"
self.con_strength_value.setText(fmt.format(L_Display))
except ValueError:
print("Error")
class ConcreteStrengthInFo(QtWidgets.QWidget):
def __init__(self, parent=None):
super(ConcreteStrengthInFo, self).__init__(parent)
self.concreteproperty = ConcreteProperty()
self.concretestrengthbox = ConcreteStrengthComboBox()
self.concretestrengthbox.activated.connect(self.setdatastrength)
hbox = QtWidgets.QHBoxLayout()
concrete_strength = QtWidgets.QLabel("Concrete strength: ")
hbox.addWidget(concrete_strength)
hbox.addWidget(self.concretestrengthbox)
self.grid = QtWidgets.QGridLayout()
self.grid.addLayout(hbox, 0, 0)
self.grid.addWidget(self.concreteproperty, 1, 0)
#QtCore.pyqtSlot(int)
def setdatastrength(self, index):
it = self.concretestrengthbox.compressive_strength[index]
self.concreteproperty.display_condata(it)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = secondtabmaterial()
w.show()
sys.exit(app.exec_())
Above code is corrected and final. Now it works as it should.
I think the issue is that your receiving slot doesn't match any of the available .activated signals.
self.activated.connect(self.setdatastrength)
#QtCore.pyqtSlot()
def setdatastrength(self):
index = self.currentIndex()
it = self.compressive_strength[index]
print(it)
self.concreteproperty.display_condata(it)
The QComboBox.activated signal emits either an int of the index, or a str of the selected value. See documentation.
You've attached it to setdatastrength which accepts doesn't accept any parameters (aside from self, from the object) — this means it doesn't match the signature of either available signal, and won't be called. If you update the definition to add the index value, and accept a single int it should work.
self.activated.connect(self.setdatastrength)
#QtCore.pyqtSlot(int) # add the target type for this slot.
def setdatastrength(self, index):
it = self.compressive_strength[index]
print(it)
self.concreteproperty.display_condata(it)
After the update — the above looks now to be fixed, although you don't need the additional index = self.currentIndex() in setdatastrength it's not doing any harm.
Looking at your code, I think the label is being updated. The issue actually is that you can't see the label at all. Looking at the init for ConcreteProperty
class ConcreteProperty(QtWidgets.QWidget):
def __init__(self, parent=None):
super(ConcreteProperty, self).__init__(parent)
self.setFont(QtGui.QFont("Helvetica", 10, QtGui.QFont.Normal, italic=False))
self.concretestrength_lay = QtWidgets.QHBoxLayout()
fctd = "\nfcd\n\nfctd\n\nEc"
con_strength = QtWidgets.QLabel(fctd)
self.con_strength_value = QtWidgets.QLabel(" ")
self.concretestrength_lay.addWidget(con_strength)
self.concretestrength_lay.addWidget(self.con_strength_value, alignment=QtCore.Qt.AlignLeft)
The reason the changes are not appearing is that you create two ConcreteProperty objects, one in ConcreteStrengthInfo and one in ConcreteStrengthComboBox. Updates to the combo box trigger an update of the ConcreteProperty attached to the combobox, not the other one (they are separate objects). The visible ConcreteProperty is unaffected.
To make this work, you need to move the signal attachment + the slot out of the combo box object. The following is a replacement for the two parts —
class ConcreteStrengthComboBox(QtWidgets.QComboBox):
def __init__(self, parent = None):
super(ConcreteStrengthComboBox, self).__init__(parent)
self.addItems(["C12/15","C16/20","C20/25","C25/30","C30/37","C35/45","C40/50","C45/55",
"C50/60","C55/67","C60/75","C70/85","C80/95","C90/105"])
self.setFont(QtGui.QFont("Helvetica", 10, QtGui.QFont.Normal, italic=False))
self.compressive_strength = ["12","16","20","25","30","35","40","45","50","55",
"60","70","80","90"]
class ConcreteStrengthInFo(QtWidgets.QWidget):
def __init__(self, parent=None):
super(ConcreteStrengthInFo, self).__init__(parent)
hbox = QtWidgets.QHBoxLayout()
concrete_strength = QtWidgets.QLabel("Concrete strength: ")
hbox.addWidget(concrete_strength)
self.concreteproperty = ConcreteProperty()
self.concretestrengthbox = ConcreteStrengthComboBox()
hbox.addWidget(self.concretestrengthbox)
self.concretestrengthbox.activated.connect(self.setdatastrength)
self.vlay = QtWidgets.QVBoxLayout()
self.vlay.addLayout(hbox)
self.vlay.addLayout(self.concreteproperty.concretestrength_lay)
#QtCore.pyqtSlot(int)
def setdatastrength(self, index):
it = self.concretestrengthbox.compressive_strength[index]
print(it)
self.concreteproperty.display_condata(it)
This works for me locally.
Here I have 2 different classes called c_elementOptFrame (lets call it class a) and c_elementFigFrame (and this is class b). In class a, I have radio button object, these button will change an image in which I construct with label in class b, in other words, I wanted to change this image when I click those radio button. The radio button has been set up with method called react , in this method I wanted to pass a value (string) to class b, so that class b will use this value to change the image. But it doesn't work as I expected. The value has been passed to class b (I printed the value) but the image doesn't come up, I tried several ways but I still couldn't do it yet. so this is my code, please let me know if you have couple of suggestions or an alternative to do it. Thank you
code:
class c_elementOptFrame(QFrame):
def __init__(self, parent=None):
super(c_elementOptFrame,self).__init__()
self.setVisible(True)
self.setMaximumWidth(150)
self.setFrameShadow(QFrame.Plain)
self.setFrameShape(QFrame.Box)
self.setLineWidth(1)
self.setFrameStyle(QFrame.StyledPanel)
#layoutmanager
layout = QVBoxLayout()
#all objects inside this frame
strel_lab = QLabel("Element Types")
strel_lab.setContentsMargins(0,0,10,10)
group_box = QGroupBox('Structural Element')
opts_group = QButtonGroup()
opts_group.setExclusive(True)
beam_but = QRadioButton("Beams")
slab_but = QRadioButton("Slabs")
beam_but.toggled.connect(self.react_1)
slab_but.toggled.connect(self.react_2)
opts_group.addButton(beam_but)
opts_group.addButton(slab_but)
group_box.setLayout(layout)
concls_lab = QLabel("Concrete Class")
concls_lab.setContentsMargins(0,15,10,10)
concls_opt = QComboBox()
concls_opt.addItem("C30")
concls_opt.addItem("C40")
concls_opt.addItem("C50")
mod_but = QPushButton("Modify Parameter", self)
mod_but.clicked.connect(self.modifyParam)
create_but = QPushButton("Create Model", self)
create_but.setDisabled(False)
create_but.clicked.connect(self.nextFrame)
#add objects to layout
layout.addWidget(strel_lab)
layout.addWidget(beam_but)
layout.addWidget(slab_but)
layout.addWidget(concls_lab)
layout.addWidget(concls_opt)
layout.addWidget(mod_but)
layout.addStretch()
layout.addWidget(create_but)
self.setLayout(layout)
def react_1(self, enabled):
if enabled:
pict_path = 1
c_elementFigFrame(pict_path)
class c_elementFigFrame(QFrame):
def __init__(self, pict_path):
super(c_elementFigFrame,self).__init__()
self.setFrameShadow(QFrame.Plain)
self.setFrameShape(QFrame.Box)
self.setLineWidth(1)
self.setFrameStyle(QFrame.StyledPanel)
layout = QVBoxLayout()
pict = QLabel('Test')
pict.sizeHint()
pixmap = QPixmap()
if pict_path == 1:
print(True)
pixmap.load('beam.png')
pict.setPixmap(pixmap)
#else:
#pixmap = QPixmap(pict_path)
#pict.setPixmap(pixmap)
layout.addWidget(pict)
self.setLayout(layout)