Замена значений QLabel и QRadiobutton с использованием файла .json
Пишу программу похожую на обычную викторину.
Есть файл data.json, в котором записаны следующие данные:
- Вопрос
- Варианты ответа
- Номер верного ответа.
Моя программа написана на PyQt, интерфейс присутствует. Я хочу лишь понять как мне данные из файла data.json использовать так, чтобы:
- Вопрос из json заменял пустое значение
label. - Варианты ответов вставлялись в наименования
radiobutton. - А верный ответ под номер
radiobutton.
Для примера который более менее подходит предоставлю эту программу:
from tkinter import *
from tkinter import messagebox as mb
import json
class Quiz:
def __init__(self):
self.q_no = 0
self.display_title()
self.display_question()
self.opt_selected = IntVar()
self.opts = self.radio_buttons()
self.display_options()
self.buttons()
self.data_size = len(question)
self.correct = 0
def display_result(self):
wrong_count = self.data_size - self.correct
correct = f"Correct: {self.correct}"
wrong = f"Wrong: {wrong_count}"
score = int(self.correct / self.data_size * 100)
result = f"Score: {score}%"
mb.showinfo("Result", f"{result}\n{correct}\n{wrong}")
def check_ans(self, q_no):
if self.opt_selected.get() == answer[q_no]:
return True
def next_btn(self):
if self.check_ans(self.q_no):
self.correct += 1
self.q_no += 1
if self.q_no == self.data_size:
self.display_result()
gui.destroy()
else:
self.display_question()
self.display_options()
def buttons(self):
next_button = Button(gui, text="Next", command=self.next_btn,
width=10, bg="blue", fg="white", font=("ariel", 16, "bold"))
next_button.place(x=350, y=380)
quit_button = Button(gui, text="Quit", command=gui.destroy,
width=5, bg="black", fg="white", font=("ariel", 16, " bold"))
quit_button.place(x=700, y=50)
def display_options(self):
val = 0
self.opt_selected.set(0)
for option in options[self.q_no]:
self.opts[val]['text'] = option
val += 1
def display_question(self):
q_no = Label(gui, text=question[self.q_no], width=60,
font=('ariel', 16, 'bold'), anchor='w')
q_no.place(x=70, y=100)
def display_title(self):
# The title to be shown
title = Label(gui, text="Тест закинуть в программу",
width=50, bg="green", fg="white", font=("ariel", 20, "bold"))
title.place(x=0, y=2)
def radio_buttons(self):
q_list = []
y_pos = 150
while len(q_list) < 4:
radio_btn = Radiobutton(gui, text=" ", variable=self.opt_selected,
value=len(q_list) + 1, font=("ariel", 14))
q_list.append(radio_btn)
radio_btn.place(x=100, y=y_pos)
y_pos += 40
return q_list
gui = Tk()
gui.geometry("800x450")
gui.title("Тест в программу интерфейс вопросы")
with open('data.json', encoding='UTF-8') as f:
data = json.load(f)
question = (data['question'])
options = (data['options'])
answer = (data['answer'])
quiz = Quiz()
gui.mainloop()
data.json:
{
"question": [
"Q1. Тут вопрос?",
"Q2. Тут вопрос?",
"Q3. Тут вопрос?",
"Q4. Тут вопрос?"
],
"answer": [
1,
1,
1,
1
],
"options": [
["Ответ",
"Не ответ",
"Не ответ",
"Не ответ"
],
["Ответ",
"Не ответ",
"Не ответ",
"Не ответ"
],
["Ответ",
"Не ответ",
"Не ответ",
"Не ответ"
],
["Ответ",
"Не ответ",
"Не ответ",
"Не ответ"
]
]
}
Я понимаю как это работает с Tkinter, но не понимаю как это все реализовать в PyQt.
Сам интерфейс, кнопки, поле для вопроса все есть. Нужно только подключить data.json и заменять значения label и radiobutton на значения из файлов после каждого вопроса.
Ответы (1 шт):
Автор решения: S. Nick
→ Ссылка
Как вариант:
main.py:
import sys
import json
from PyQt5.Qt import *
class Example(QWidget):
def __init__(self):
super().__init__()
with open('data.json', encoding='UTF-8') as f:
data = json.load(f)
self.question = (data['question'])
self.options = (data['options'])
self.answer = (data['answer'])
self.data_size = len(self.question)
self.q_no = 0
self.correct = 0
self.setObjectName('example')
self.title = QLabel("Тест закинуть в программу",
objectName='title', alignment=Qt.AlignCenter)
self.quit_button = QPushButton("Quit", objectName='quit_button')
self.quit_button.clicked.connect(self.close)
self.label_q_no = QLabel(
self.question[self.q_no],
alignment=Qt.AlignCenter,
objectName='label_q_no'
)
self.layout = QGridLayout(self)
self.layout.addWidget(self.title, 0, 0, 1, 3, alignment=Qt.AlignTop)
self.layout.addWidget(self.quit_button, 1, 2,
alignment=Qt.AlignRight|Qt.AlignTop)
self.layout.setRowStretch(2, 1)
self.layout.addWidget(self.label_q_no, 3, 0, 1, 3)
self.radiobuttons = {}
list_rb = []
self.radiobutton_1 = QRadioButton(self.options[self.q_no][0])
self.layout.addWidget(self.radiobutton_1, 4, 0, 1, 3)
list_rb.append(self.radiobutton_1)
self.radiobutton_2 = QRadioButton(self.options[self.q_no][1])
self.layout.addWidget(self.radiobutton_2, 5, 0, 1, 3)
list_rb.append(self.radiobutton_2)
self.radiobutton_3 = QRadioButton(self.options[self.q_no][2])
self.layout.addWidget(self.radiobutton_3, 6, 0, 1, 3)
list_rb.append(self.radiobutton_3)
self.radiobutton_4 = QRadioButton(self.options[self.q_no][3])
self.layout.addWidget(self.radiobutton_4, 7, 0, 1, 3)
list_rb.append(self.radiobutton_4)
self.radiobuttons[self.q_no] = list_rb
self.radiobutton_5 = QRadioButton()
self._group = QButtonGroup(self)
self._group.addButton(self.radiobutton_1, 0)
self._group.addButton(self.radiobutton_2, 1)
self._group.addButton(self.radiobutton_3, 2)
self._group.addButton(self.radiobutton_4, 3)
self._group.addButton(self.radiobutton_5, 4)
self.layout.setRowStretch(8, 1)
self.next_button = QPushButton("Next", objectName='next_button')
self.next_button.clicked.connect(self.next_btn)
self.layout.addWidget(self.next_button, 9, 1,
alignment=Qt.AlignCenter)
self.layout.setSpacing(0)
def next_btn(self):
correct_answer = self.answer[self.q_no]
rb = self.radiobuttons[self.q_no][correct_answer]
if rb.isChecked():
self.correct += 1
self.q_no += 1
if self.q_no >= self.data_size:
self.next_button.setEnabled(False)
text = f'''<br>Score : {int(self.correct / self.data_size * 100)}%<br>
Correct : {self.correct} <br>
Wrong : {self.data_size - self.correct} '''
msg = QMessageBox.information(
self,
'Результат',
f"<p style='color: white; text-align: center; \
font: 15pt \"Consolas\" Bold'>{text}</p>",
)
return
self.label_q_no.setText(self.question[self.q_no])
list_rb = []
self.radiobutton_5.setChecked(True)
self.radiobutton_1.setText(self.options[self.q_no][0])
list_rb.append(self.radiobutton_1)
self.radiobutton_2.setText(self.options[self.q_no][1])
list_rb.append(self.radiobutton_2)
self.radiobutton_3.setText(self.options[self.q_no][2])
list_rb.append(self.radiobutton_3)
self.radiobutton_4.setText(self.options[self.q_no][3])
list_rb.append(self.radiobutton_4)
self.radiobuttons[self.q_no] = list_rb
QSS = '''
#example {
background-color: #F0E68C;
}
#title {
background-color: green;
color: white;
font: 25pt "ariel" bold;
max-height: 50px;
}
#label_q_no {
background-color: #F0E68C;
color: #000080;
font: 17pt "ariel" bold;
}
#quit_button {
background-color: black;
color: white;
font: 16pt "ariel" bold;
min-height: 30px;
min-width: 70px;
margin: 10px 0px;
}
#next_button {
background-color: blue;
color: white;
font: 16pt "ariel" bold;
min-width: 100px;
min-height: 30px;
margin-top: 10px;
}
QRadioButton {
background-color: #F0E68C;
color: #000;
font: 15pt "ariel" bold;
max-height: 50px;
margin-top: 10px;
margin-left: 20px;
}
QMessageBox {
background: black;
messagebox-information-icon: url(./images/Close.png);
}
QMessageBox QPushButton {
padding: 2px;
border-radius: 5px;
background: white;
}
QMessageBox QPushButton:hover {
background: darkCyan;
}
QDialogButtonBox {
dialogbuttonbox-buttons-have-icons: 1;
dialog-ok-icon: url(./images/Ok.png);
}
'''
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setStyleSheet(QSS)
w = Example()
w.resize(500, 500)
w.show()
sys.exit(app.exec_())
data.json:
{
"question": [
"Q1. Тут вопрос 1?",
"Q2. Тут вопрос 2?",
"Q3. Тут вопрос 3?",
"Q4. Тут вопрос 4?"
],
"answer": [
0,
1,
2,
3
],
"options": [
["Ответ правильный1",
"Не ответ",
"Не ответ",
"Не ответ"
],
["Не ответ",
"Ответ правильный2",
"Не ответ",
"Не ответ"
],
["Не ответ",
"Не ответ",
"Ответ правильный3",
"Не ответ"
],
["Не ответ",
"Не ответ",
"Не ответ",
"Ответ правильный4"
]
]
}

