问题
I am trying to make dynamic widgets and make them clickable. By clicking on one widget it should pass dynamic value to other widget. I have tried sender() and other options accessing the widget but nothing worked. All the widgets are sending information from the last widget.
Below is the code:
import sys
from PyQt5.QtGui import QIcon, QPixmap
from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow, QPushButton, QLabel, QMessageBox,QSizePolicy, QLayoutItem,QFrame,QHBoxLayout, QGridLayout, QVBoxLayout
from PyQt5.QtCore import QCoreApplication,QSize,QFileInfo
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from functools import partial
from PyQt5.QtCore import pyqtSlot
import sip
class Screen(QWidget):
def __init__(self):
super(Screen, self).__init__()
self.running_layout = QVBoxLayout()
self.action_layout = QVBoxLayout()
self.layout = QHBoxLayout(self)
self.layout.addLayout(self.running_layout)
self.layout.addLayout(self.action_layout)
self.setLayout(self.layout)
self.show()
self.all_running()
self.actions_1('1')
def buttonClicked(self):
sender = self.sender()
print(sender + ' was pressed')
def all_running(self):
for i in range(5):
button = QLabel("btn "+str(i))
button.mouseReleaseEvent = lambda _ : self.actions_1(str(button.text()).split()[1])
self.running_layout.addWidget(button)
button2 = QLabel("btn 5")
button2.mouseReleaseEvent = lambda _ : self.actions_1(str(button2.text()).split()[1])
self.running_layout.addWidget(button2)
def actions_1(self,value):
while not self.action_layout.isEmpty():
print(self.action_layout.isEmpty())
widget = self.action_layout.itemAt(0).widget()
print("removing", widget)
widget.setVisible(False)
self.action_layout.removeWidget(widget)
del widget
self.action_layout = QVBoxLayout()
self.layout.addLayout(self.action_layout)
val = int(value)
for i in range(val):
actions_item = QLabel(str(i))
self.action_layout.addWidget(actions_item)
app = QApplication(sys.argv)
Gui = Screen()
sys.exit(app.exec_())
Edited: I am trying to pass an int to actions based on the int value that number of widgets need to get populate. This int is based on the dynamic widget which i generated using the for loop. For example if the first widget of running_layout "btn 0" is clicked there won't be any widgets in the action_layout, If the second widget of running_layout "btn 1" is clicked there will be one widget "0" in the action_layout and so on based on the widget number. I am able to send the signal but on whichever dynamically created widget i click it is sending value 4 of last widget "btn 4" to the action_layout.
回答1:
To simplify the task we will create 2 widgets, the first one will be ClickableWidget
that will have a signal indicating the number associated with the widget, whereas the second DynamicWidget
will have a method that will be in charge of updating the number of widgets.
To know if an element is pressed we use the method installEventFilter()
and eventFilter()
, this filters the events giving information of the object and event, we will use setProperty("index", )
to store the number.
In the second widget I have implemented a method that is responsible for cleaning the widgets and creating some new widgets.
class ClickableWidget(QWidget):
clicked = pyqtSignal(int)
def __init__(self, n=5, parent=None):
QWidget.__init__(self, parent)
self.hlayout = QVBoxLayout(self)
for i in range(n):
label = QLabel("btn {}".format(i), self)
label.setProperty("index", i)
self.hlayout.addWidget(label)
label.installEventFilter(self)
def eventFilter(self, obj, event):
if isinstance(obj, QLabel) and event.type() == QEvent.MouseButtonPress:
i = obj.property("index")
self.clicked.emit(i)
return QWidget.eventFilter(self, obj, event)
class DynamicWidget(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.hlayout = QVBoxLayout(self)
def changeWidget(self, n):
def clearLayout(layout):
item = layout.takeAt(0)
while item:
w = item.widget()
if w:
w.deleteLater()
lay = item.layout()
if lay:
clearLayout(item.layout())
item = layout.takeAt(0)
clearLayout(self.hlayout)
for i in range(n):
label = QLabel("btn {}".format(i), self)
self.hlayout.addWidget(label)
class Screen(QWidget):
def __init__(self):
super(Screen, self).__init__()
self.layout = QHBoxLayout(self)
c = ClickableWidget(6, self)
d = DynamicWidget(self)
c.clicked.connect(d.changeWidget)
self.layout.addWidget(c)
self.layout.addWidget(d)
来源:https://stackoverflow.com/questions/46696362/pyqt5-making-dynamic-widgets-clickable-and-pass-arguments-to-another-function