How to make a list of line editors without many variables? (smth like self.line_1 = QLineEdit(self), self.line_2 = QLineEdit(self), ... , self.line_9000 = QLineEdit(self))
For example, I want to create this
window with ability to get access to each element.
A simple cycle does not provide access to each element, only last. How I can do this?
One way is to make widgets as you said - cycle,
and you can access to the widget with using layout.itemAtPosition
it would go like this :
layout = QVBoxLayout()
for i in range(list_length):
line_edit = QLineEdit(self)
layout.addWidget(line_edit)
to access the widget :
def access_widget(int):
item = layout.itemAtPosition(int)
line_edit = item.widget()
return line_edit
now you can access to the designated QLineEdit.
layout = QFormLayout()
self.alphabet_line_edits = dict.fromkeys(['а', 'б', 'в', 'г'])
for letter in self.alphabet_line_edits:
line_edit = QLineEdit()
layout.addRow(letter, line_edit)
self.alphabet_line_edits[letter] = line_edit
def button_clicked(self):
print(self.alphabet_line_edit['б'].text())
Related
I have a situation where i want to add 3 buttons in a QTableWidget.
I could able to add a single button using below code.
self.tableWidget = QtGui.QTableWidget()
saveButtonItem = QtGui.QPushButton('Save')
self.tableWidget.setCellWidget(0,4,saveButtonItem)
But i want to know how to add multiple (lets say 3) buttons. I Mean Along with Save Button i want to add other 2 buttons like Edit, Delete in the same column (Actions)
You can simply create your own widget, containing the three buttons, e.g. via subclassing QWidget:
class EditButtonsWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(EditButtonsWidget,self).__init__(parent)
# add your buttons
layout = QtGui.QHBoxLayout()
# adjust spacings to your needs
layout.setContentsMargins(0,0,0,0)
layout.setSpacing(0)
# add your buttons
layout.addWidget(QtGui.QPushButton('Save'))
layout.addWidget(QtGui.QPushButton('Edit'))
layout.addWidget(QtGui.QPushButton('Delete'))
self.setLayout(layout)
And then, set this widget as the cellwidget:
self.tableWidget.setCellWidget(0,4, EditButtonsWidget())
You use a layout widget to add your widgets to, then add the layout widget to the cell.
There are a couple of different ones you can use.
http://doc.qt.io/qt-4.8/layout.html
self.tableWidget = QtGui.QTableWidget()
layout = QtGui.QHBoxLayout()
saveButtonItem = QtGui.QPushButton('Save')
editButtonItem = QtGui.QPushButton('Edit')
layout.addWidget(saveButtonItem)
layout.addWidget(editButtonItem)
cellWidget = QtGui.QWidget()
cellWidget.setLayout(layout)
self.tableWidget.setCellWidget(0, 4, cellWidget)
I created different tabs using QTableWidget in a loop:
self.table_widget = QTableWidget()
for i in range(0, 5):
self.table_widget.tab = QWidget()
self.table_widget.tabs.addTab(self.table_widget.tab, f"{i}")
self.table_widget.tab.Layout = QVBoxLayout(self)
self.tab_table = QTableWidget(self)
self.table_widget.tab.Layout.addWidget(self.tab_table)
self.table_widget.tab.setLayout(self.table_widget.tab.Layout)
self.table_widget.show()
How can I access the QTableWidget inside the different tabs? Each tab does not have a specific variable name, which can be used to control the widget. I can get the currentIndex of the tab, but I don't know how to use this information.
The simple solution is to create a list as an instance attribute, and add the table widgets to it. Note that there's no point in setting instance attributes in a loop, as they will be overwritten every time.
Also, you should not create a layout with a widget argument if you're going to set that layout to another widget.
self.tables = []
for i in range(5):
tab = QWidget()
self.table_widget.tabs.addTab(tab, f"{i}")
layout = QVBoxLayout(tab)
tab_table = QTableWidget()
layout.addWidget(tab_table)
self.tables.append(tab_table)
Alternatively, you can make the table an instance member of the page:
for i in range(5):
tab = QWidget()
self.table_widget.tabs.addTab(tab, f"{i}")
layout = QVBoxLayout(tab)
tab.tab_table = QTableWidget()
layout.addWidget(tab.tab_table)
def get_table(self, index):
tab = self.table_widget.tabs.widget(index)
return tab.tab_table
Another possibility, as long as it's guaranteed that each tab only has one table, is to use findChild():
def get_table(self, index):
tab = self.table_widget.tabs.widget(index)
return tab.findChild(QTableWidget)
The Labels
self.titlelabel = QLabel(self)
self.artistlabel = QLabel(self)
self.albumlabel = QLabel(self)
in the UI do not update, when i run the method.
I mean, they do work on the initial initialization of the initUI(self), but when i change the item in the combobox, the do not update with the new information
I run this command in the initUI(self) which is connected to the dropdown /Qcombobox self.cb.activated.connect(self.updateTrackInfo)
def currentTrackInfo(self):
currentTrackInfoDict = {}
currentZone = str(self.cb.currentText())
deviceDict = self.sonosZonesCoordinatorsIP()
for key, value in deviceDict.items():
if value == currentZone:
device = SoCo(key)
track = device.get_current_track_info()
current_title = track['title']
current_artist = track["artist"]
current_album = track["album"]
currentTrackInfoDict.update({"current_title":current_title})
currentTrackInfoDict.update({"current_artist":current_artist})
currentTrackInfoDict.update({"current_album":current_album})
return currentTrackInfoDict
def updateTrackInfo(self):
self.currentTrackInfoDict = self.currentTrackInfo()
self.titlelabel = QLabel(self)
self.artistlabel = QLabel(self)
self.albumlabel = QLabel(self)
self.titlelabel.move((PLAYICONHEIGHT-100),(WINDOWHEIGHT-230))
self.artistlabel.move((PLAYICONHEIGHT-100),(WINDOWHEIGHT-220))
self.albumlabel.move((PLAYICONHEIGHT-100),(WINDOWHEIGHT-250))
self.titlelabel.setText("Title: {}".format(self.currentTrackInfoDict["current_title"]))
print(self.currentTrackInfoDict["current_title"])
self.artistlabel.setText("Artist: {}".format(self.currentTrackInfoDict["current_artist"]))
self.albumlabel.setText("Album: {}".format(self.currentTrackInfoDict["current_album"]))
The print function : print(self.currentTrackInfoDict["current_title"]) - works, but the labels are not being updated.
thank you in advance.
In your updateTrackInfo method each time you create the new QLabel objects instead of just updating the text on the existing ones. It may cause a problems since the new labels overlap with old (you are not deleting the old labels and they still exist after updateTrackInfo is called). I would suggest to move
self.titlelabel = QLabel(self)
self.artistlabel = QLabel(self)
self.albumlabel = QLabel(self)
self.titlelabel.move((PLAYICONHEIGHT-100),(WINDOWHEIGHT-230))
self.artistlabel.move((PLAYICONHEIGHT-100),(WINDOWHEIGHT-220))
self.albumlabel.move((PLAYICONHEIGHT-100),(WINDOWHEIGHT-250))
into the __init__(self) method and keep only the labels updating code in your updateTrackInfo method
I would suggest to use currentIndexChanged QComboBox signal instead of activated
datainputHbox = QHBoxLayout()
layout = QVBoxLayout(self)
layout.addLayout(datainputHbox)
pagedatainputdeletboxbutton1.clicked.connect(lambda:self.boxdelete(datainputHbox))
def boxdelete(self, box):
This is the PyQt proragm
How write boxdelete funtion in order to remove datainputHbox form layout. I try a lot of. However I just can remove all the widgets but cannot remove layout.
As a generic answer: taken from here with slight, but important changes: you should not call widget.deleteLater(). At least in my case this caused python to crash
Global Function
def deleteItemsOfLayout(layout):
if layout is not None:
while layout.count():
item = layout.takeAt(0)
widget = item.widget()
if widget is not None:
widget.setParent(None)
else:
deleteItemsOfLayout(item.layout())
together with the boxdelete function from Brendan Abel's answer
def boxdelete(self, box):
for i in range(self.vlayout.count()):
layout_item = self.vlayout.itemAt(i)
if layout_item.layout() == box:
deleteItemsOfLayout(layout_item.layout())
self.vlayout.removeItem(layout_item)
break
You can remove QLayouts by getting their corresponding QLayoutItem and removing it. You should also be storing references to your Layouts, otherwise there is no other way to access them later on unless you know the widget they belong to.
datainputHbox = QHBoxLayout()
self.vlayout = QVBoxLayout(self)
layout.addLayout(datainputHbox)
pagedatainputdeletboxbutton1.clicked.connect(lambda: self.boxdelete(datainputHbox))
def boxdelete(self, box):
for i in range(self.vlayout.count()):
layout_item = self.vlayout.itemAt(i)
if layout_item.layout() == box:
self.vlayout.removeItem(layout_item)
return
A single function that implements TheTrowser's answer, arguably cleaner:
def clear_item(self, item):
if hasattr(item, "layout"):
if callable(item.layout):
layout = item.layout()
else:
layout = None
if hasattr(item, "widget"):
if callable(item.widget):
widget = item.widget()
else:
widget = None
if widget:
widget.setParent(None)
elif layout:
for i in reversed(range(layout.count())):
self.clear_item(layout.itemAt(i))
I have a problem desinging a window using PySide.
class MainForm(QWidget):
def __init__(self, parent=None):
super(MainForm, self).__init__()
# init window
self.hbox = QHBoxLayout(self)
self.scroll = QScrollArea(self)
self.table = QTableWidget(self)
self.leftspltr = QSplitter(QtCore.Qt.Vertical)
self.rightspltr = QSplitter(QtCore.Qt.Vertical)
self.scroll.setWidget(self.leftspltr)
self.rightspltr.addWidget(self.table)
self.hbox.addWidget(self.leftspltr)
self.hbox.addWidget(self.rightspltr)
self.setWindowTitle("...")
self.table.setColumnCount(3)
self.table.move(11,220)
self.table.verticalHeader().hide()
self.table.setHorizontalHeaderLabels(["Key","Full","HR"])
dic = dumpered_hash.dict_naming_values
os.popen("rm dumpered_hash dumpered_hash.py dumpered_hash.pyc")
xpos = 0
ypos = 0
for key, val1 in sorted(dic.iteritems()):
btn = QPushButton(key, self)
btn.clicked.connect(partial(self.fillTbl, val1, len(val1) + 1))
btn.setFixedSize(84,20)
self.leftspltr.addWidget(btn)
im trying to design a window that has some button (more than 30) placed virtically, so I want to have them in scroll bar that fits the window size, and a table at the right side that doesnt move while scrolling.
the code above gives me a tiny scroll bar that moves the button, bur they are out of the window size.
what wrong there ?
I think I understand what you are trying to do here. However, you are placing your buttons in a vertical splitter and then fixing their size. Instead, place the buttons in a vertical layout, and then place that and the table widget into a horizontal splitter.
class MainForm(QtGui.QWidget):
def __init__(self, parent=None):
super(MainForm, self).__init__()
# init window
self.hbox = QtGui.QHBoxLayout(self)
self.btnbox = QtGui.QVBoxLayout()
self.scroll = QtGui.QScrollArea(self)
self.table = QtGui.QTableWidget(self)
self.spltr = QtGui.QSplitter(QtCore.Qt.Horizontal)
self.setWindowTitle("...")
self.table.setColumnCount(3)
self.table.move(11,220)
self.table.verticalHeader().hide()
self.table.setHorizontalHeaderLabels(["Key","Full","HR"])
dic = {}
for i in range(30):
dic['foo '+str(i)] = [i]
for key, val1 in sorted(dic.iteritems()):
btn = QtGui.QPushButton(key, self)
self.btnbox.addWidget(btn)
# must place layout into a widget before adding to QScrollArea
holder = QtGui.QWidget()
holder.setLayout(self.btnbox)
self.scroll.setWidget(holder)
self.spltr.addWidget(self.scroll)
self.spltr.addWidget(self.table)
self.hbox.addWidget(self.spltr)
I would also like to note, that is it better to include the simplest piece of code necessary to reproduce your problem. I don't know what you are trying to achieve with the lines containing dumpered_hash, but it seems to be irrelevant, as well as a dubious use of a deprecated function, and makes it impossible to run your code without modification. Make it easier for people to help you!