Найти - Пользователи
Полная версия: PyQt модальные окна
Начало » GUI » PyQt модальные окна
1 2 3
Loki
Patrik, точно по центру исходя из моего предыдущего примера будет так:
# -*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui
class ModalWind(QtGui.QWidget):
    def __init__(self, parent=None):
        super(ModalWind, self).__init__(parent)
        self.setWindowFlags(QtCore.Qt.Dialog | QtCore.Qt.WindowSystemMenuHint)
        self.setWindowModality(QtCore.Qt.WindowModal)
        self.setWindowTitle("Модальное окно")
        butt_hide = QtGui.QPushButton('Закрыть модальное окно')   
        vbox = QtGui.QVBoxLayout()
        vbox.addWidget(butt_hide)
        self.setLayout(vbox)
        butt_hide.clicked.connect(self.close)   
class MainWind(QtGui.QWidget):
    def __init__(self, parent=None):
        super(MainWind, self).__init__(parent)
        self.setWindowTitle("Главное окно")
        self.resize(400, 200)
        butt_show = QtGui.QPushButton('Показать модальное окно')   
        vbox = QtGui.QVBoxLayout()
        vbox.addWidget(butt_show)
        self.setLayout(vbox)
        butt_show.clicked.connect(self.on_show)
    def on_show(self):
        win = ModalWind(self)
        win.resize(200, 100)
        # сначало отображаем окно за пределами видимости
        win.move(win.width()*-2,0)
        # обязательно отображаем, потому-что, только так frameSize()
        # вернет коректное значение
        win.show()
        x = self.x()+(self.frameSize().width()-win.frameSize().width())//2
        y = self.y()+(self.frameSize().height()-win.frameSize().height())//2
        win.move(x, y)
        
if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    window = MainWind()
    window.show()
    sys.exit(app.exec_())

Patrik
Loki А если нужно несколько модальных окно, то просто вводим новый классы class ModalWind1, 2 т.п?
Loki
Все зависит от твоей задачи…
К примеру, если бы у тебя стояла задача запускать модальные окна из одного основного, и чтобы все модальные окна запускались обязательно по центру родителя, то разумно было бы ввести в основной класс новый метод, которому бы передавались ссылки на сами модальные окна, и уже в этом методе двигать их…
P.S. Просто совет… старайся своим классам давать емкие, но достаточно развернутые имена, исходя из их функционала… Modal1, Modal2 такие названия лучше использовать только в примерах, а не в своих программах…
Patrik
У меня в программе всего будет три модальных окна:
1) о программе
2) окошко информация
3) окошко с ошибкой

Все будут вылетать по центру.
Имена классам я стараюсь давать названия, чтобы соответсвовали назначению.

Еще попутный вопрос появился, к примеру в окне с ошибкой, перед текстом хочу вставить картинку восклицательный знак.
Я правильно понимаю, что нужно поставить label и в качестве фона задать ему картинку?
Loki
Мне кажется лучше воспользоваться QtGui.QMessageBox.warning(<родитель>,<Текст сообщения>), метод возвращает код нажатой кнопки, если укажешь родителя будет центроваться относительно его и будет его модалить(насколько я помню)…
Не понравится этот виджет посмотри QMessageBox.
Patrik
Я думал взять виджет QWidget в нем вывести картинку label.setPixmap(pixmap) и label с описанием ошибки и кнопку закрыть. Единственное, что я не понимаю. К примеру класс назову
class Error(QtGui.QWidget), если модифицировать твой пример:

# -*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui
class Error(QtGui.QWidget):
    def __init__(self, parent=None):
        super(Error, self).__init__(parent)
        ...
class ModalWind(QtGui.QWidget):
    def __init__(self, parent=None):
        super(ModalWind, self).__init__(parent)
        self.setWindowFlags(QtCore.Qt.Dialog | QtCore.Qt.WindowSystemMenuHint)
        self.setWindowModality(QtCore.Qt.WindowModal)
        self.setWindowTitle("Модальное окно")
        butt_hide = QtGui.QPushButton('Закрыть модальное окно')   
        vbox = QtGui.QVBoxLayout()
        vbox.addWidget(butt_hide)
        self.setLayout(vbox)
        butt_hide.clicked.connect(self.close)   
class MainWind(QtGui.QWidget):
    def __init__(self, parent=None):
        super(MainWind, self).__init__(parent)
        self.setWindowTitle("Главное окно")
        self.resize(400, 200)
        butt_show = QtGui.QPushButton('Показать модальное окно')   
        butt_error = QtGui.QPushButton('Показать окно об ошибке')
        vbox = QtGui.QVBoxLayout()
        vbox.addWidget(butt_show)
        vbox.addWidget(butt_error)
        self.setLayout(vbox)
        butt_show.clicked.connect(self.on_show)
        butt_error.clicked.connect(self.on_show)
    def on_show(self):
        win = ModalWind(self)
        win.resize(200, 100)
        # сначало отображаем окно за пределами видимости
        win.move(win.width()*-2,0)
        # обязательно отображаем, потому-что, только так frameSize()
        # вернет коректное значение
        win.show()
        x = self.x()+(self.frameSize().width()-win.frameSize().width())//2
        y = self.y()+(self.frameSize().height()-win.frameSize().height())//2
        win.move(x, y)
        
if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    window = MainWind()
    window.show()
    sys.exit(app.exec_())

Как класс Error передать методу on_show?
Loki
Patrik, я практически ничего не понял, что ты хочешь сделать…

Обьясни по подробнее, что ты хочешь сделать, и как это должно работать.
Из того что ты написал я понял, что тебе лучше использовать МэсэджБоксы для вывода сообщения об ошибке…
По поводу передать класс методу…Твой класс находится в глобальной области видимости имен, ты его можешь вызвать непосредственно внутри метода другого класса…или я что-то не так понял.


Loki
Если ты хотел на нажатие другой кнопки повесить окно Ошибки, то:
# -*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui
class Error(QtGui.QWidget):
    def __init__(self, parent=None):
        super(Error, self).__init__(parent)
        ...
class ModalWind(QtGui.QWidget):
    def __init__(self, parent=None):
        super(ModalWind, self).__init__(parent)
        self.setWindowFlags(QtCore.Qt.Dialog | QtCore.Qt.WindowSystemMenuHint)
        self.setWindowModality(QtCore.Qt.WindowModal)
        self.setWindowTitle("Модальное окно")
        butt_hide = QtGui.QPushButton('Закрыть модальное окно')   
        vbox = QtGui.QVBoxLayout()
        vbox.addWidget(butt_hide)
        self.setLayout(vbox)
        butt_hide.clicked.connect(self.close)   
class MainWind(QtGui.QWidget):
    def __init__(self, parent=None):
        super(MainWind, self).__init__(parent)
        self.setWindowTitle("Главное окно")
        self.resize(400, 200)
        butt_show = QtGui.QPushButton('Показать модальное окно')   
        butt_error = QtGui.QPushButton('Показать окно об ошибке')
        vbox = QtGui.QVBoxLayout()
        vbox.addWidget(butt_show)
        vbox.addWidget(butt_error)
        self.setLayout(vbox)
        butt_show.clicked.connect(self.on_show)
        butt_error.clicked.connect(self.on_show_error)
    def on_show(self):
        win = ModalWind(self)
        win.resize(200, 100)
        # сначало отображаем окно за пределами видимости
        win.move(win.width()*-2,0)
        # обязательно отображаем, потому-что, только так frameSize()
        # вернет коректное значение
        win.show()
        x = self.x()+(self.frameSize().width()-win.frameSize().width())//2
        y = self.y()+(self.frameSize().height()-win.frameSize().height())//2
        win.move(x, y)
      def on_show_error(self):
        win_er = Error(self)
        ...
        win_er.show()
        x = self.x()+(self.frameSize().width()-win_er.frameSize().width())//2
        y = self.y()+(self.frameSize().height()-win_er.frameSize().height())//2
        win_er.move(x, y)   
        
if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    window = MainWind()
    window.show()
    sys.exit(app.exec_())
Patrik
А есть возможность объединить 2 метода on_show и on_show_error они же дублируют друг дргуга?
Loki
Patrik, Есть и такой, но мне этот способ кажется не очень предпочтительным.
Я еще раз повторяю зачем изобретать велосипед, если в Qt уже есть QMessageBox?
Но если ты не ишешь легких путей, то:
# -*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui
# я немного дописал твой класс, чтобы проще было проверить работоспособность
class Error(QtGui.QWidget):
    def __init__(self, parent=None):
        super(Error, self).__init__(parent)
        self.setWindowFlags(QtCore.Qt.Dialog | QtCore.Qt.WindowSystemMenuHint)
        self.setWindowModality(QtCore.Qt.WindowModal)
        self.setWindowTitle('Окно с ошибкой')
        butt_hide = QtGui.QPushButton('Закрыть окно c ошибкой')   
        vbox = QtGui.QVBoxLayout()
        vbox.addWidget(butt_hide)
        self.setLayout(vbox)
        butt_hide.clicked.connect(self.close)        
class ModalWind(QtGui.QWidget):
    def __init__(self, parent=None):
        super(ModalWind, self).__init__(parent)
        self.setWindowFlags(QtCore.Qt.Dialog | QtCore.Qt.WindowSystemMenuHint)
        self.setWindowModality(QtCore.Qt.WindowModal)
        self.setWindowTitle("Модальное окно")
        butt_hide = QtGui.QPushButton('Закрыть модальное окно')   
        vbox = QtGui.QVBoxLayout()
        vbox.addWidget(butt_hide)
        self.setLayout(vbox)
        butt_hide.clicked.connect(self.close)   
class MainWind(QtGui.QWidget):
    def __init__(self, parent=None):
        super(MainWind, self).__init__(parent)
        self.setWindowTitle("Главное окно")
        self.resize(400, 200)
        butt_show = QtGui.QPushButton('Показать модальное окно')   
        butt_error = QtGui.QPushButton('Показать окно об ошибке')
        vbox = QtGui.QVBoxLayout()
        vbox.addWidget(butt_show)
        vbox.addWidget(butt_error)
        self.setLayout(vbox)
        # здесь на сигнал вместо ссылки вешаешь лямбду с параметром
        butt_show.clicked.connect(lambda: self.on_show(ModalWind))
        butt_error.clicked.connect(lambda: self.on_show(Error))
    def on_show(self, widget):        
        win = widget(self)
        win.resize(200, 100)
        # сначало отображаем окно за пределами видимости
        win.move(win.width()*-2,0)
        # обязательно отображаем, потому-что, только так frameSize()
        # вернет коректное значение
        win.show()
        x = self.x()+(self.frameSize().width()-win.frameSize().width())//2
        y = self.y()+(self.frameSize().height()-win.frameSize().height())//2
        win.move(x, y)      
        
if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    window = MainWind()
    window.show()
    sys.exit(app.exec_())


This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB