Как устранить ошибку (завершение программы) при попытке переместить окно без рамки за кнопку?
Проблема следующая - как основное окно использую класс QMainWindow, убрал рамку с помощью флага FramelessWindowHint, далее добавил функций для перемещения за любую область.
Всё работает отлично, но наткнулся на следующую ошибку.
При попытке нажать на кнопку "свернуть", с задержкой примерно в 1 секунду и смещением мыши с зажатой кнопкой - приложение захлопывается и возвращает следующее исключение:
delta = QPoint(event.globalPos() - self.oldPos) AttributeError: 'MainWindow' object has no attribute 'oldPos' <class 'AttributeError'> 'MainWindow' object has no attribute 'oldPos' <traceback object at 0x000001EFC7B2ABC0>
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
QtWidgets.QMainWindow.__init__(self, parent, flags=QtCore.Qt.Window | QtCore.Qt.MSWindowsFixedSizeDialogHint |
QtCore.Qt.FramelessWindowHint)
self.setWindowTitle("blah-blah")
self.setFixedSize(1000, 600)
self.settings = QtCore.QSettings("blabla", "bla")
self.SGM = Widget()
self.setCentralWidget(self.SGM)
quit_button = QtWidgets.QPushButton('X', self) # кнопка закрытия окна
quit_button.setFixedSize(20, 20)
quit_button.move(980, 0)
quit_button.setFlat(True)
quit_button.clicked.connect(self.close)
minimize_button = QtWidgets.QPushButton('_', self) # кнопка сворачивания окна
minimize_button.setFixedSize(20, 20)
minimize_button.move(960, 0)
minimize_button.setFlat(True)
minimize_button.clicked.connect(self.showMinimized)
def center(self): # блок 3х функций для перетаскивания окна за любое место
qr = self.frameGeometry()
cp = QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
self.move(qr.topLeft())
def mousePressEvent(self, event):
self.oldPos = event.globalPos()
def mouseMoveEvent(self, event):
delta = QPoint(event.globalPos() - self.oldPos)
self.move(self.x() + delta.x(), self.y() + delta.y())
self.oldPos = event.globalPos()
Решение возможно в трёх способах:
- Обработать ошибку так, чтобы программа не прекращала работу.
- Изменить каким-то образом поведение функций, чтобы они перетаскивали окно только за элемент
QLabel, который присобачен к верхней части окна(к примеру) - Отредактировать код так, чтобы ошибка не возникала.
Подойдет любое решение из трёх.
Ответы (2 шт):
Искал не там, где нужно, пока оставил следующий костыль в виде try-except:
def mouseMoveEvent(self, event):
try:
delta = QPoint(event.globalPos() - self.oldPos)
self.move(self.x() + delta.x(), self.y() + delta.y())
self.oldPos = event.globalPos()
except:
pass
То есть таким образом тупо скипаем(пропускаем) какое-либо перемещение как событие.
Но всё же, если у кого-то найдется более эффективное решение - сообщите! Буду признателен!
Решение возможно в трёх способах:
1 Обработать ошибку так, чтобы программа не прекращала работу.
3 Отредактировать код так, чтобы ошибка не возникала.
Чтобы ошибка не возникала достаточно добавить флажок, например self.pressing,
и выполнять действия, прописанные в методе mouseMoveEvent,
когда self.pressing имеет значение True.
Если у вас возникнут проблемы с перетаскиванием окна только за элемент QLabel,
который находится в верхней части окна, то задайте новый вопрос,
с котором покажите ваш QLabel и расскажите, что вы успели попробовать делать.
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
self.setWindowTitle("blah-blah")
self.resize(1000, 600)
# ? self.settings = QtCore.QSettings("blabla", "bla") # ?
# self.SGM = Widget() # ? Widget
self.centralWidget = QtWidgets.QWidget() # +++
self.setCentralWidget(self.centralWidget) # +++
quit_button = QtWidgets.QPushButton('X', self.centralWidget) # self.centralWidget
quit_button.setFixedSize(20, 20)
quit_button.move(980, 0)
quit_button.setFlat(True)
quit_button.clicked.connect(self.close)
minimize_button = QtWidgets.QPushButton('_', self.centralWidget) # self.centralWidget
minimize_button.setFixedSize(20, 20)
minimize_button.move(960, 0)
minimize_button.setFlat(True)
minimize_button.clicked.connect(self.showMinimized)
self.center() # +++
self.pressing = False # +++ !!!
def center(self):
qr = self.frameGeometry()
cp = QtWidgets.QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
self.move(qr.topLeft())
def mousePressEvent(self, event):
self.oldPos = event.globalPos()
self.pressing = True # +++ !!!
def mouseMoveEvent(self, event):
if self.pressing: # +++ !!!
delta = QtCore.QPoint(event.globalPos() - self.oldPos)
self.move(self.x() + delta.x(), self.y() + delta.y())
self.oldPos = event.globalPos()
def mouseReleaseEvent(self, event): # +
self.pressing = False # +++ !!!
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
