I wonder if someone knows this.
as in attached pic let's say I have a tabwidget in qt designer and some lineEdit fields. What
I want to achieve is, if the user clicks on a row of the tabwidgets the values of the items will be moved to the lineEdit fields. I saw I can somehow connect them but how to achieve this with the signal and slot functionality in qt designer without programming.
No, it is not possible without implementing code manually as there is no signal to send the text. The logic is:
self.tableWidget.cellDoubleClicked.connect(self.handle_cellDoubleClicked)
# or self.tableWidget.cellClicked.connect(self.handle_cellDoubleClicked)
def cellDoubleClicked(self, row, column):
item = self.tableWidget.item(row, column)
text = item.text() if item is not None else ""
self.lineEdit.setText(text)
Related
so I have a mass of buttons on a QT Designer GUI application all named LED_i where i ranges from 0-191, ie: LED_0, LED_1, ..., LED_191. I would like basically the same thing to happen when clicked except changing the input i. So LED_0 when clicked would call the function OnClick(0), LED_75 would call OnClick(75) etc etc.
I am connecting my buttons with
ui.LED_0.clicked.connect(OnClick0)
usually using a separate function for each button. However this would require 191 functions, and 191 lines like the above connecting my buttons to their functions. I'm sure I could edit it s.t. I can use the same function by passing the button name that was clicked and getting the number from it but that would still require the 191 lines of button.clicked.connect. Is there any way to do this more efficiently?
TIA
It's not impossible with PyQt5. This is a good fit for a QButtonGroup. And there are a few ways to approach it.
QButtonGroup using Designer
To set up a QButtonGroup in Designer, do the following:
select two or more buttons, radioboxes, or checkboxes
right click on one of the buttons and you'll get a context menu item, Assign to button group --> New button group
After this, you'll see buttonGroup (the default name) show up in the Object Inspector.
To run code when one of your buttons is clicked, you can use the buttonClicked signal of QButtonGroup. It will give you a reference to the button that was clicked, and from the objectName, you can figure out what to do.
ui.buttonGroup.buttonClicked.connect(self.OnClicked)
then
def OnClicked(self, button):
# button objectName follows pattern LED_<number>
button_number = int(button.objectName()[4:])
... do stuff here with button_number
QButtonGroup in code
In the original post, there were 191 buttons in Designer. That is a lot of buttons to arrange. If for some reason, you wanted to do it in code instead, you could assign each button an id as it is added to the group and then you could use the idClicked signal:
grid = QGridLayout()
buttonGroup = QButtonGroup()
buttonGroup.idClicked.connect(OnClick)
buttonList = []
for row in range(14):
rowList = []
for col in range(14):
button_number = 14*row + col
button = QPushButton(f'{button_number}', objectName=f'LED_{button_number}')
rowList.append(button)
buttonGroup.addButton(button, button_number)
grid.addWidget(button, row, col)
then
def OnClick(self, idClicked):
... do something with idClicked here
I'm looking for some piece of code that enables me to get the information of a combobox that I've put it on a TableView created by QtDesigner.
For lack of knowledge I'm not using any classes or Delegates. When I was using TableWidget the line TableWidget.cellWidget(indexofthecurrentrow, 4).currentIndex() == 0 returned me the current status of the row allowing me to update the database, but that line doesn't work on TableView I'm assuming because of the model or absence of a Delegate.
Relevant Code Below:
for row in range(len(data_from_sqlite)):
comboBox = QComboBox()
comboBox.addItems('opt1', 'opt2')
index_combo = tableview.model().index(row, 5)
tableview.setIndexWidget(index_combo, comboBox)
I just don't know how to retrieve this QComboBox state through other function connected in a button.
I've tried both
tableview.model().index(0,4).itemData().currentIndex() #crashes
and
tableview.model().index(0,4).data() #returns None
Thanks in advance for any help.
I found a solution to a my problem and as pointed by musicamante the solution involves using classes witch is very basic and was very difficult for me.
The loop that implements the combobox in the tableview is:
for row in range(len(data)):
combo = combomaker(self)
index_combo = self.tableview.model().index(row, 5)
self.tableview.setIndexWidget(index_combo, combo)
being the combo maker as it follows
class combo(QComboBox):
def __init__(self, parent):
super().__init__(parent)
self.addItems(['a', 'b'])
self.currentIndexChanged.connect(self.getComboValue)
def getComboValue(self):
print(self.currentText())
# return self.currentText()
I took the code from Jie Jenn https://www.youtube.com/watch?v=KMJTJNUzo4E
Hope this help some clueless programmer in the future.
Using cell widgets makes absolutely no interaction with the table's model and its data.
If you need to access a specific cell widget, use the getter function opposite to setIndexWidget(), indexWidget():
combo = tableview.indexWidget(tableview.model().index(0,4))
combo_index = combo.currentIndex()
[I'm using PyQt4, but I think this Qt4 issue is not Python specific.]
I have a QTableWidget. In each row, the first column holds a button. When clicked, the row is removed.
To remove the row, I use removeRow(int row) method, which takes as argument the index of the row. When connecting the signal, I can't know the index of the row because it might change in the meantime (for instance if the first row is removed, all row indexes are changed).
The accepted answer here suggests to pass the callback an instance of a QTableWidgetItem in the line, then get the row number from this item at deletion time.
This would be nice, except none of the elements of the row is a QTableWidgetItem. The elements are the button itself and a few ComboBoxes.
I can't figure out a way around this.
Can I somehow fit one of my elements into a QTableWidgetItem? Should I add a QTableWidgetItem in some sort of hidden column?
Our current implementation uses indexAt(QtGui.qApp.focusWidget()) (see other answer to question mentioned above), which looks like a sorry workaround to me.
If I replace the button with a checkable QTableWidgetItem like this
rm_item = QtGui.QTableWidgetItem()
rm_item.setFlags(QtCore.Qt.ItemIsUserCheckable |
QtCore.Qt.ItemIsEnabled)
I have a QTableWidgetItem I can use to get back to the row index. But I don't know how to catch a "checked" or "clicked" event from it like I do with the button. All I found is the itemClicked signal of QTableWidget, but then I'd have to filter all the other widgets out.
There has to be something obvious I'm missing.
Edit
From what I read here, I could add both a QTableWidgetItem with setItem and a Button widget with setCellWidget to the same cell. This doesn't seem so natural to me, but apparently it works (can't test right now).
I guess I'll do that. Add the Button, plus a dummy QTableWidgetItem on the same cell to pass as a reference to the row.
Is this how it is meant to be?
Edit 2
Or maybe QTableWidget is not the proper Widget and I should be using a Layout, as suggested here.
It seems that using a layout rather than a table is possibly the most "correct" answer, but that may come with it's own difficulties, as seen in my answer to this question:
How to delete widgets from gridLayout
If you want to continue using a table, a somewhat cleaner solution than adding dummy items would be to use a persistent model index:
button = QtGui.QPushButton(text, self.table)
self.table.setCellWidget(row, column, button)
index = QtCore.QPersistentModelIndex(
self.table.model().index(row, column))
button.clicked.connect(
lambda *args, index=index: self.handleButton(index))
def handleButton(self, index):
print('button clicked:', index.row())
if index.isValid():
self.table.removeRow(index.row())
If I understand your question correctly:
def set_button(self, row, col):
# create a push button
btn = QtGui.QPushButton('Remove row')
# connect to action
btn.clicked.connect(self.remove_row)
# set in cell
self.setCellWidget(row, col, btn)
def remove_row(self):
# find what is clicked
clicked = QtGui.qApp.focusWidget()
# position
idx = self.indexAt(clicked.pos())
# remove this row
self.removeRow(idx.row())
I have 10 QTablewidgets. Each of the QTableWidget display different data. I want to get the name of the table widget that the last time user clicked ( on any of the cells).
Currently i tried putting all the tables in a list:
table1 = QtGui.QTableWidget()
table2 = QtGui.QTableWidget()
...
...
mytablelist = [table1,table2,....]
Using Signal and Slots I tried this:
for item in mytablelist:
self.connect(item,QtCore.SIGNAL("cellClicked()"),self.Identify)
My Identify function is as below:
def Identify(self):
sender = self.sender()
print sender
As far as i understand, the sender() method should tell me which Qobject the signal is coming from.
I don't seems to get any output from Identify function. What is causing the problem and how do i fix it?
Is there any better approach to this problem?
I think i found the problem. It was the problem with the signal cellClicked() i used (i have no idea why).
So, I tried to use itemSelectionChanged() signal instead of cellClicked() i used in my question. It works fine now. After that i just used index() method to get the position of table in the tablelist.
tableindex = mytablelist.index(sender)
I have dialog:
It contains many flat QPushButtons, QTextEdit and another QPushButton. After click on 'Get list' we can see list of checked buttons in QTextEdit.
My question is how to get this functionality in some smart way. Right now I'm checking every button:
if self.ui.bq6o.isChecked():
cards.append("Q6o")
if self.ui.bk2o.isChecked():
cards.append("K2o")
if self.ui.bq3o.isChecked():
cards.append("Q3o")
if self.ui.bt7s.isChecked():
cards.append("T7s")
if self.ui.bq4o.isChecked():
cards.append("Q4o")
if self.ui.bt4s.isChecked():
cards.append("T4s")
if self.ui.b98o.isChecked():
cards.append("98o")
if self.ui.bjto.isChecked():
cards.append("JTo")
if self.ui.btt.isChecked():
cards.append("TT")
if self.ui.bq7o.isChecked():
cards.append("Q7o")
[...]
Obviously I can't like code like that. I was looking for some widget "button matrix" like, but without luck. I will be grateful for advises.
All the buttons should be children of the same widget, probably the dialog itself. Just get a handle to that widget to get all the child buttons, then loop through them and if they're checked, included their text.
parent = dialog # or whatever
cards = [widget.text() for widget in parent.children() if isinstance(widget, QPushButton) and widget.isChecked()]
You may need to include some code in the if statement to exclude the "Get List" button, or any other pushbuttons in your dialog that could be set to "checked" but shouldn't be included in cards list.
As #Brendan suggested in the other question, you could loop through them in a single list comprehension. But one other approach is to connect each buttons toggled signal to a slot that allows them to register when they are checked.
# somewhere in your class
self.checkedList = set()
def buttonChecked(self, checked):
button = self.sender()
if checked:
self.checkedList.add(button)
else:
if button in self.checkedList:
self.checkedList.remove(button)
# when you create a new button
button.toggled.connect(self.buttonChecked)
This would let you always have a set of just the checked buttons, which are self reporting. Otherwise, you would have to track them under their parent and loop to find out which are checked each time.
Update
Here is a another version that combines #Brendans loop and my signal suggestion. This might help in a situation where your buttons are a bit more spread out across your UI as opposed to be all under a single parent... but first assuming them all under a parent...
parent = dialog
for widget in parent.children():
if isinstance(widget, QPushButton):
widget.toggled.connect(self.buttonChecked)
You could repeat this in your __init__() for all the locations of your buttons and get them all registered to the slot.