Источник вашей проблемы состоит в том, что вы, вероятно, редактируете код, сгенерированный pyuic
(или пытаетесь имитировать его поведение), что никогда * не должно будет сделано. Эти файлы должны быть импортированы только как модули и не должны изменяться без всякой причины. Чтобы узнать, как правильно использовать ui
файлы, созданные с помощью Designer, читайте подробнее о с помощью Designer .
Результатом применения такого подхода, как вы это сделали, является то, что mousePressEvent
и mouseMoveEvent
никогда не будут вызваны * 1014. *
Причина этого заключается в том, что в вашем коде эти методы принадлежат Ui_MainWindow
class instance (ui
, созданный ближе к концу), который является ничем иным, как базовым c Python object
подклассом: он почти ничего не делает, кроме сборки UI на экземпляре QMainWindow в его setupUi()
; что Экземпляр QMainWindow должен получать эти события вместо этого, и эти методы должны быть реализованы там.
Или, по крайней мере, теоретически . Это связано с тем, что mousePressEvent и mouseMoveEvent, которые вы хотите перехватить, должны быть получены из объекта infoBar
, а не из главного окна.
Распространенным решением является создание подкласса виджета, который будет получать эти события, и реализации этих методов, но так как вы, вероятно, используете пользовательский интерфейс, созданный в Designer, он не так быстр, как кажется (подробнее об этом позже).
Самый прямой подход - установить фильтр событий на наблюдаемом виджете, чтобы мы могли фильтровать эти события и реагировать на них, если мы хотим.
В следующем примере я предполагаю, что вы воссоздали файл с помощью pyuic
с именем ui_mainwindow.py
:
from PyQt5 import QtCore, QtGui, QtWidgets
from ui_mainwindow import Ui_MainWindow
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
self.offset = None
# install the event filter on the infoBar widget
self.infoBar.installEventFilter(self)
def eventFilter(self, source, event):
if source == self.infoBar:
if event.type() == QtCore.QEvent.MouseButtonPress:
self.offset = event.pos()
elif event.type() == QtCore.QEvent.MouseMove and self.offset is not None:
# no need for complex computations: just use the offset to compute
# "delta" position, and add that to the current one
self.move(self.pos() - self.offset + event.pos())
# return True to tell Qt that the event has been accepted and
# should not be processed any further
return True
elif event.type() == QtCore.QEvent.MouseButtonRelease:
self.offset = None
# let Qt process any other event
return super().eventFilter(source, event)
Об использовании подклассов в Designer, упомянутом выше: можно создавать собственные подклассы и «использовать» их в Designer. Вы должны создать подкласс в своем коде, а затем добавить к своему пользовательскому интерфейсу его самого близкого предка (в вашем случае, QFrame), который будет работать как своего рода заполнитель, а затем продвигать его. Проведите некоторое исследование о «продвигаемых виджетах», чтобы узнать больше.
Важное предложение: использование фиксированных размеров и позиций не является хорошим выбором, и менеджеры по расположению должны всегда быть предпочтительным вместо этого. Причина этого заключается в том, что то, что вы видите на своем компьютере, почти всегда будет отображаться очень по-разному в других (среди самых распространенных причин: различные размеры экрана, настройки по умолчанию, DPI, шрифты и т. Д. c), и это может привести к ваш GUI становится непригодным для использования, так как виджеты могут стать невидимыми, перекрывающимися или нечитаемыми. Есть очень, очень редкие ситуации, в которых можно использовать фиксированные геометрии (но когда программисты понимают, что они им нужны, это, возможно, связано с плохим дизайном кода / пользовательского интерфейса), и это, конечно, не ваш случай.
Например, если я Попробуйте изменить размер окна до меньшего размера, чем оригинал, верхние правые кнопки станут недоступны. Кроме того, кнопка справа рядом с кнопкой «выход» неправильно выровнена. Если вы используете менеджер макетов (например, горизонтальный макет в виджете infoBar
), он автоматически решит все эти проблемы.