Что мешает переместить этот QWidget?Python

Программы на Python
Ответить
Anonymous
 Что мешает переместить этот QWidget?

Сообщение Anonymous »

Я работаю над медиаплеером (клоном Spotify?) и хочу воссоздать меню «фрикадельки», найденное в песнях
Изображение
и мне нравится, как он свободно плавает рядом с кнопкой с фрикаделькой и остается там.
Моей первоначальной мыслью было использовать диалоговое окно, однако это не похоже на тот способ, которым Spotify реализовал меню, поскольку оно не является отдельным окном. Затем я решил использовать виджет «подполе», чтобы хранить все мои виджеты песен, а затем добавить кнопку в виджете песни, которая будет действовать как якорь (?) для создания меню.
Я создал небольшой макет в отдельном файле, чтобы попытаться заставить это работать, и на данный момент у меня есть кнопка для создания виджета с использованием специального сигнала.
class subBox(QWidget):
def __init__(self, widgets: list[QWidget]):
super().__init__()

layout = QVBoxLayout()
for count, wi in enumerate(widgets):
layout.addWidget(wi)

self.setLayout(layout)

@Slot()
def addWid(self, item: testSong):
# TODO
'''
We have the song object that is part of the overall layout.
Now we can create the meatball menu, and slot it over the list of stuff?
'''
layout = self.layout()
idx = layout.indexOf(item)
if idx == -1:
print("Not present.")
return

button: testSongButton = item.findChild(testSongButton)
if button.findChild(testSongMeatball):
print("Meatball spawned.")
return

item.setStyleSheet("background-color: blue")

meatball = testSongMeatball(button)
meatball.setStyleSheet("background-color: red")
meatball.show()

subBox является центральным виджетом mainWindow и содержит виджет testSong, записанный как:
class testSong(QWidget):
meatballCreated = Signal(QWidget, name="meatballCreated")

meatballDestroyed = Signal(QWidget, name="meatballDestroyed")

def __init__(self, data={"name": "name", "album": "album"}):
super().__init__()
# song needs a label and a meatball?
# Horizontal

# init layout
layout = QHBoxLayout()

label = QLabel(data['name'])
album = QLabel(data['album'])

meatball = testSongButton("Meatball menu")

# connect clicked signal to relay into a meatballCreate signal, passing this widget
# as a param
meatball.clicked.connect(
lambda checked: self.meatballCreated.emit(self))

layout.addWidget(label)
layout.addWidget(album)
layout.addWidget(meatball)

self.setLayout(layout)

Есть много дополнительных вещей, которые можно попытаться имитировать мое настоящее приложение, но главное: testSong содержит две метки и кнопку, при нажатии на которую «порождается» виджет с фрикадельками. subBox.addwid — это слот, который получает виджет testSong и ищет в этом виджете дочернюю кнопку и использует эту кнопку как родительскую для вновь созданного меню с фрикадельками. Я пробовал использовать sizePolicy, sizeHint, updateGeometry и другие, чтобы заставить виджет фрикадельки перемещаться внутри кнопки, но мне не удалось заставить его двигаться.
Изображение
Вот как окно выглядит изначально.
Изображение
А вот (уродливые цвета фона) — после нажатия кнопки, вызывающей меню. Я изменил размер окна, чтобы показать, чем QLabel и QPushButton sizePolicy различаются, и я попытался сделать фрикадельку дочерним элементом QLabel, чтобы посмотреть, поможет ли это. но это не так. Я надеялся изменить размер виджета с фрикадельками, чтобы он был больше виджета с кнопкой, а затем как-то сместить его, но теперь понимаю, что это, вероятно, глупый способ сделать это.
Думаю, я сделаю это вместо этого. попробуйте сделать виджет фрикадельки дочерним элементом subBox и используйте геометрию кнопки, чтобы переопределить метод resizeEvent() фрикадельки, немного осмотревшись. Однако мне все же хотелось бы знать, почему я не могу переместить или изменить размер виджета фрикаделек в детстве? Есть ли что-то, что мне нужно переопределить??
Любая помощь будет приветствоваться, и я надеюсь, что я правильно отформатировал вопрос и в удобном для чтения формате.РЕДАКТИРОВАТЬ: 16.11.24
Виджет песни будет содержать две метки и кнопку для создания фрикадельки
class testSong(QWidget):
meatballCreated = Signal(QWidget, name="meatballCreated")

meatballDestroyed = Signal(QWidget, name="meatballDestroyed")

def __init__(self, data={"name": "name", "album": "album"}):
super().__init__()
# song needs a label and a meatball?
# Horizontal

self.setStyleSheet("background-color: blue")
# init layout
layout = QHBoxLayout()

label = QLabel(data['name'])
album = QLabel(data['album'])

meatball = testSongButton("Meatball button")

# connect clicked signal to relay into a meatballCreate signal, passing this widget
# as a param
meatball.clicked.connect(
lambda checked: self.meatballCreated.emit(self))

layout.addWidget(label)
layout.addWidget(album)
layout.addWidget(meatball)

self.setLayout(layout)

class testSongButton(QPushButton):
def __init__(self, text):
super().__init__(text)
self.setStyleSheet("background-color: purple")

def resizeEvent(self, event):
# print("Button resized!")
return super().resizeEvent(event)

def moveEvent(self, event):
# print("Button moved!")
return super().moveEvent(event)

Подкласс Фрикадельки QWidget. Вот попытки перемещения/изменения размера путем переопределения обработчиков событий, они никогда не печатаются, поэтому я предполагаю, что менеджер макета для subBox ограничивает события перемещения только дочерними элементами макета? Совершенно не понимаю, что здесь делать.
class testSongMeatball(QWidget):
def __init__(self, parent=None):
super().__init__(parent)

layout = QHBoxLayout(self)
text = QLabel()
text.setText("Meatball Menu")
layout.addWidget(text)

def resizeEvent(self, event):
# when resizing what do I need to do really?
# return the new size of the function?
print("Meatball Resized!")
return QWidget.resizeEvent(self, event)

def moveEvent(self, event):
print("Meatball Moved!")
self.findPlace()
return super().moveEvent(event)

def findPlace(self):
# get parent, find song widget and position accordingly
p: subBox = self.parent()
if not p:
print("Not p")
return
print("Finding Place")
item: testSong = p.findChild(testSong)
item_pos = item.pos()

button: testSongButton = item.findChild(testSongButton)
button_pos = button.pos()

x,y = item_pos.x(), item_pos.y()
nx,ny, = button_pos.x(), button_pos.y()

meatball_pos = QPoint(x+nx,y+ny)
meatball_geo = QRect(meatball_pos, self.size())
self.setGeometry(meatball_geo)
return

def sizePolicy(self):
return QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Preferred)

def sizeHint(self):
return QSize(70,50)
# return super().sizeHint()


subBox QWidget подкласс, который принимает список виджетов песен (я когда-либо пробовал только один виджет песни и не смог заставить его работать, так что это не так). вообще необходим. Имеет два слота, в которых будут появляться фрикадельки.
class subBox(QWidget):
def __init__(self, widgets: list[QWidget]):
super().__init__()

self.setStyleSheet("background-color: green")
layout = QVBoxLayout()
for count, wi in enumerate(widgets):
layout.addWidget(wi)

self.setLayout(layout)

@Slot()
def addWid(self, item: testSong):
# TODO
'''
We have the song object that is part of the overall layout.
Now we can create the meatball menu, and slot it over the list of stuff?
'''
layout = self.layout()
idx = layout.indexOf(item)
if idx == -1:
print("Not present.")
return

button: testSongButton = item.findChild(testSongButton)
if button.findChild(testSongMeatball):
print("Meatball already present.")
return

meatball = testSongMeatball(self) #

Подробнее здесь: https://stackoverflow.com/questions/791 ... positioned
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»