Получение, задание и сохранение координат и положения окна программы на Qt

Вопрос заключается в том, что в PyQt я работаю относительно недавно и надо быстро изучать эту тему, но возникают некоторые затруднения. Сам пока нашел три метода это сделать, но все же логику не до конца осознал:

  1. При помощи прямоугольника QRect, используя методы geometry() для получения геометрии окна и setGeometry(QRect) для задания геометрии окна.
  2. При помощи вектора QPoint и размера QSize, используя методы pos() и size(), для получения координаты окна и его размера, а также методы move(QPoint) и resize(QSize) для задания координат и размера окна.
  3. Обращаясь к отдельным полям, используя методы x() и y() для получения координат окна, width() и height() для получения его размеров, а также используя методы move(int x, int y) и resize(int width, int height) для задания положения и размеров окна.

У меня есть код, который задает и запоминает в бинарном формате координаты Radiobutton:

import sys
from PyQt5 import uic
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtWidgets import QTableWidgetItem
from PyQt5.QtWidgets import QFileDialog
from PyQt5 import QtCore
import pickle
import pickletools

def on_open():
   name = QFileDialog.getOpenFileName()[0]
   print("Файл = ", name)
   file = open(name, 'rb')
   x = pickle.load(file)
   y = pickle.load(file)
   print("x = ", x, "y = ", y)
   ui.spinBoxX.setValue(x)
   ui.spinBoxY.setValue(y)

def on_save():
   name = QFileDialog.getSaveFileName () [0]
   print("Файл = ",name)
   file = open(name, 'wb')
   x = ui.spinBoxX.value()
   y = ui.spinBoxY.value()
   x1 = pickle.dump(x, file)
   y1 = pickle.dump(y, file)
   picktools.dis(x1)


   
def on_changedX():
   ui.radioButton.move(ui.spinBoxX.value(), ui.radioButton.y())

def on_changedY():
   ui.radioButton.move(ui.radioButton.x(), ui.spinBoxY.value())

app=QApplication([])
ui = uic.loadUi("MainWindow.ui")
ui.show()

ui.radioButton.setEnabled(False)
ui.spinBoxX.setPrefix("x=")
ui.spinBoxY.setPrefix("y=")
ui.spinBoxX.valueChanged.connect(on_changedX)
ui.spinBoxY.valueChanged.connect(on_changedY)
ui.pbSave.clicked.connect(on_save)
ui.pbOpen.clicked.connect(on_open)

exit(app.exec())

Ссылка на файл .ui: https://drive.google.com/file/d/1L91kMBsPqKzLDRWKyYQoLBWb-4ogh1jT/view?usp=sharing


Ответы (1 шт):

Автор решения: S. Nick

QWidget предоставляет несколько функций, которые работают с геометрией виджета. Некоторые из этих функций работают с чистой клиентской областью (то есть с окном, исключая оконную рамку), другие включают в себя оконную рамку. Дифференциация проводится таким образом, чтобы прозрачно охватить наиболее распространенное использование.

  • Включая рамку окна: x(), y(), frameGeometry(), pos() и move().

  • За исключением оконной рамы: geometry(), width(), height(), rect() и size().

Обратите внимание, что различие имеет значение только для украшенных виджетов верхнего уровня. Для всех дочерних виджетов геометрия фрейма равна геометрии клиента виджета.

На этой диаграмме показано большинство используемых функций:

введите сюда описание изображения

Я немного подправил ваш код с учетом ООП и подкрасил пару виджетов, чтобы вам было понятнее наблюдать. Попробуйте:

import sys
import pickle
#? import pickletools
from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(551, 403)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.gridLayout_2 = QtWidgets.QGridLayout(self.centralwidget)
        self.gridLayout_2.setObjectName("gridLayout_2")
        self.groupBox = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox.setObjectName("groupBox")
        self.label = QtWidgets.QLabel(self.groupBox)
        self.label.setGeometry(QtCore.QRect(10, 20, 91, 16))
        self.label.setObjectName("label")
        self.verticalLayoutWidget = QtWidgets.QWidget(self.groupBox)
        self.verticalLayoutWidget.setGeometry(QtCore.QRect(10, 40, 191, 51))
        self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
        self.verticalLayout.setObjectName("verticalLayout")
        self.spinBoxX = QtWidgets.QSpinBox(self.verticalLayoutWidget)
        self.spinBoxX.setMaximum(295)
        self.spinBoxX.setObjectName("spinBoxX")
        self.verticalLayout.addWidget(self.spinBoxX)
        self.spinBoxY = QtWidgets.QSpinBox(self.verticalLayoutWidget)
        self.spinBoxY.setMaximum(275)
        self.spinBoxY.setObjectName("spinBoxY")
        self.verticalLayout.addWidget(self.spinBoxY)
        self.label_2 = QtWidgets.QLabel(self.groupBox)
        self.label_2.setGeometry(QtCore.QRect(10, 100, 91, 16))
        self.label_2.setObjectName("label_2")
        self.frame = QtWidgets.QFrame(self.groupBox)
        self.frame.setGeometry(QtCore.QRect(210, 40, 311, 291))
        self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
        self.frame.setObjectName("frame")
        self.radioButton = QtWidgets.QRadioButton(self.frame)
        self.radioButton.setGeometry(QtCore.QRect(0, 0, 82, 17))
        self.radioButton.setText("")
        self.radioButton.setObjectName("radioButton")
        self.checkBox = QtWidgets.QCheckBox(self.groupBox)
        self.checkBox.setGeometry(QtCore.QRect(70, 210, 70, 17))
        self.checkBox.setObjectName("checkBox")
        self.pbSave = QtWidgets.QPushButton(self.groupBox)
        self.pbSave.setGeometry(QtCore.QRect(17, 131, 75, 23))
        self.pbSave.setObjectName("pbSave")
        self.pbOpen = QtWidgets.QPushButton(self.groupBox)
        self.pbOpen.setGeometry(QtCore.QRect(17, 160, 75, 23))
        self.pbOpen.setObjectName("pbOpen")
        self.textEdit = QtWidgets.QTextEdit(self.groupBox)
        self.textEdit.setGeometry(QtCore.QRect(17, 189, 181, 16))
        self.textEdit.setObjectName("textEdit")
        self.gridLayout_2.addWidget(self.groupBox, 0, 0, 1, 1)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 551, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.groupBox.setTitle(_translate("MainWindow", "GroupBox"))
        self.label.setText(_translate("MainWindow", "Управление"))
        self.label_2.setText(_translate("MainWindow", "Конфигурация"))
        self.checkBox.setText(_translate("MainWindow", "CheckBox"))
        self.pbSave.setText(_translate("MainWindow", "Сохранить"))
        self.pbOpen.setText(_translate("MainWindow", "Загрузить"))


class Example(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)

        self.radioButton.setEnabled(False)
        self.spinBoxX.setPrefix("x=")
        self.spinBoxY.setPrefix("y=")
        self.spinBoxX.valueChanged.connect(self.on_changed_X_Y)
        self.spinBoxY.valueChanged.connect(self.on_changed_X_Y) 
        self.pbSave.clicked.connect(self.on_save)
        self.pbOpen.clicked.connect(self.on_open)
        
        self.frame.setStyleSheet("background-color: #0aa;")
        self.radioButton.setStyleSheet("background-color: #f00;")

    def on_changed_X_Y(self):
       self.radioButton.move(self.spinBoxX.value(), self.spinBoxY.value()) 
       print(f'\ngeometry     : {self.radioButton.geometry()}')
       print(f'frameGeometry: {self.radioButton.frameGeometry()}')

    def on_open(self):
       name = QtWidgets.QFileDialog.getOpenFileName()[0]
       if not name:
           msg = QtWidgets.QMessageBox.information(
               self, 
               'Внимание', 
               'Выберите файл с данными!'
           )
           return
       print("Файл = ", name)
       file = open(name, 'rb')
       x = pickle.load(file)
       y = pickle.load(file)
       print("x = ", x, "y = ", y)
       self.spinBoxX.setValue(x)
       self.spinBoxY.setValue(y)

    def on_save(self):
       name = QtWidgets.QFileDialog.getSaveFileName()[0]
       if not name:
           msg = QtWidgets.QMessageBox.information(
               self, 
               'Внимание', 
               'Выберите файл для сохранения!'
           )
           return
       print("Файл = ",name)
       file = open(name, 'wb')
       x = self.spinBoxX.value()
       y = self.spinBoxY.value()
       x1 = pickle.dump(x, file)
       y1 = pickle.dump(y, file)
       # NameError: name 'picktools' is not defined   
       # ??? picktools.dis(x1)

        

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    ex = Example()
    ex.show()
    sys.exit(app.exec_())        

введите сюда описание изображения

→ Ссылка