Найти - Пользователи
Полная версия: PyQt Несколько окон
Начало » GUI » PyQt Несколько окон
1
FLeX
Делаю на Qt тестовую программу (в смысле, для прохождения тестов студентами). Отрисовываю первое окно, куда студент вбивает свое имя, группу, выбирает тему теста, жмет кнопку “ОК”. Далее надо отрисовать окно собственно с самим тестом.
Внимание, вопрос: как лучше отрисовать второе окно?

Мои варианты на вскидку:
1. Запустить обработку другого файла, в котором будет класс нового окна
2. Реорганизовать текущее окно путем удаление старых и добавления новых виджетов
3. В этом же файле организовать еще один класс с окном
4. Что-нибудь другое
pasaranax
А зачемтебе вообще многооконный интерфейс? Имхо, это не очень удобно. Лучше бы что-то типа визарда. Но классы отображающие окно логина, теста и результатов, определенно разные, один класс мусолить разными задачами не стоит. Один элемент интерфейса - один класс.
А остальное, это уже на вкуц и свет.
FLeX
> Лучше бы что-то типа визарда
И как это организовать?
Тупо разными классами мусолить одно и то же окно?
pasaranax
Тупо у окна (если это QMainWindow) сменять один centralWidget (логин, вопросы, результаты) на другой на каждом шаге визарда. Это как вариант.
FLeX
Хорошо, почитаю про этот centralWidget (я так понимаю, что он может являться несколькими обычными виджетами?). Спасибо
UPD:
Оказывается, я как последний неудачник рисовал окно как QWidget, а не QMainWindow. Понятное дело, что теперь надо просто создать класс, который будет наследоваться от QMainWindow, и в него пихать centralWidget. Вопрос теперь в том, как это грамотно сделать. Чувствую, что придется реорганизовывать и рефакторить весь код, но хочу лишний раз посоветоваться: что с этим делать? Код прилагается
# -*- coding: utf-8 -*-
import handler
import sys
import base64
from PyQt4 import QtGui, QtCore

class Window (QtGui.QWidget):
def __init__ (self, parent = None):
QtGui.QWidget.__init__(self, parent)

self.resize(500, 150)
self.center()

self.data = handler.read_file('themes.yaml')

self.create_widgets()
self.connect_signals()

def center(self):
screen = QtGui.QDesktopWidget().screenGeometry()
size = self.geometry()
self.move((screen.width() - size.width()) / 2,\
(screen.height() - size.height()) / 2)

def create_widgets (self):
self.name_label = QtGui.QLabel(u'ФИО:')
self.group_label = QtGui.QLabel(u'Группа:')
self.name_input = QtGui.QLineEdit()
self.group_input = QtGui.QLineEdit()
self.group_input.setMaxLength(2)
self.subject_box = QtGui.QComboBox()
self.theme_box = QtGui.QComboBox()
self.ok_but = QtGui.QPushButton(u'Сохранить лог')

self.add_subjects()

#self.theme_box.hide()
#self.ok_but.hide()

sizer = QtGui.QGridLayout()
sizer.addWidget(self.name_label, 0, 0)
sizer.addWidget(self.name_input, 0, 1)
sizer.addWidget(self.group_label, 0, 2)
sizer.addWidget(self.group_input, 0, 3)
sizer.addWidget(self.subject_box, 1, 0, 1, 2)
sizer.addWidget(self.theme_box, 1, 2, 1, 2)
sizer.addWidget(self.ok_but, 2, 0, 1, 4)
self.setLayout(sizer)

def add_subjects (self):
for subject in self.data:
self.subject_box.addItem('%s' % subject)

def add_themes (self, subject):
for theme in self.data[subject]:
self.theme_box.addItem('%s' % theme)

def connect_signals (self):
self.connect(self.subject_box, QtCore.SIGNAL('activated(QString)'), self.selected_subject)
self.connect(self.ok_but, QtCore.SIGNAL('clicked()'), self.on_click)

def on_click (self):
#selected_subject = '%s' % self.subject_box.currentText().toUtf8()
selected_theme = '%s' % self.theme_box.currentText().toUtf8()
student_name = '%s' % self.name_input.text().toUtf8()
student_group = '%s' % self.group_input.text().toUtf8()

handler.Loger.save_log(selected_theme, student_name, student_group)

def selected_subject (self):
self.theme_box.clear()
self.theme_box.addItem(u'Выберите тему')

curr_subject = '%s' % self.subject_box.currentText().toUtf8()
curr_subject = curr_subject.decode('utf-8')
self.add_themes(curr_subject)

#self.theme_box.show()
#self.ok_but.show()

app = QtGui.QApplication(sys.argv)
dt = Window()
dt.show()
app.exec_()
dimabest
FLeX
Отрисовываю первое окно, куда студент вбивает свое имя, группу, выбирает тему теста, жмет кнопку “ОК”. Далее надо отрисовать окно собственно с самим тестом.
для таких целей лучше использовать QStackedWidget
pasaranax
Можно использовать любой виджет в роли окна, не обязательно QMainWindow. Если тебе не нужно что либо из , то можно и QWidget делать главным окном. Просто выделяй каждую сущность в отдельный класс, в случае с UI это совсем просто ввиду наглядности, и делай ее самостоятельным виджетом. Если создаваемая форма достаточно статична и имеет много элементов (пример: окно настроек программы), то можно нарисовать ее в Designer.
Рефакторить пока особо нечего. Я так понял, у тебя сейчас реализовано окно логина (регистрации или что-то типа того). Я бы выделил все что относится конкретно к нему из главного окна в отдельный виджет (класс). Потом так же отдельными классами все остальные экраны программы, которые будут являться параметрами (properties или дочерями) главного окна. И у них будут кнопочки, которые шлют сигналы о том, что работа с текущим экраном закончена. А твой Window может реализовать связь между ними. Он показывает текущий экран (отображает текущий виджет и скрывает остальные), принимает от них нужный сигнал сигнал и делает видимым следующий дочерний виджет.
Получится простейшая реализация интерфейса в стиле “wizard”. Еще, кстати, можно посмотреть в сторону виджета QWizard, может он подойдет :)
Но если очень хочется, то можно сделать и многооконный интерфейс, тогда просто каждый экран не будет иметь родительского виджета и будет вылезать в отдельном окне.
FLeX
для таких целей лучше использовать QStackedWidget
Спасибо, почитаю

to pasaranax
Собственно, об этом я изначально думал. Решил лишний раз у знающих тонкости Qt людей переспросить. Короче, наверное, оставлю такой вариант:
1. Билдим главное окно
2. Вытаскиваем с первого класса виджеты
3. Дожидаемся нажатия кнопки
4. Дестроим все виджеты, ресайзим окно
5. Вытаскиваем виджеты со второго класса

n. Выводим результат

UPD:
Чтобы уж не заводить отдельную тему, глупый вопрос “на засыпку”: Делаю комбобокс. Есть ли встроенные решения в Qt, которые позволят добавить один пункт (верхний) пустой или с надписью “Выберите что-нибудь”. Т.е. он есть в списке до тех пор, пока пользователь не выберет что-нибудь конкретное из предложенных вариантов
pasaranax
FLeX
UPD:
Чтобы уж не заводить отдельную тему, глупый вопрос “на засыпку”: Делаю комбобокс. Есть ли встроенные решения в Qt, которые позволят добавить один пункт (верхний) пустой или с надписью “Выберите что-нибудь”. Т.е. он есть в списке до тех пор, пока пользователь не выберет что-нибудь конкретное из предложенных вариантов
например так при первом клике первый пункт сразу удалится:
        self.combobox = QtGui.QComboBox(self)
self.combobox.addItems(["", "asdfsd", "asdfsdaf", "asdfsadf"])
self.connect(self.combobox, QtCore.SIGNAL("highlighted(QString)"), self.firstClick)

def firstClick(self, text):
if not text:
self.combobox.removeItem(0)
правда, лучше это внутри комбобокса реализовать и по клику, а не выделению, но это ты уже сам делай новый комбобокс и новый сигнал ему.
FLeX
Спасибо за решение. Собственно, до этого тоже уже дошел сам, но надеялся, что есть-таки какой-нибудь дополнительный параметр, который я в манах и туторах проглядел
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