Я все еще новичок в Python, и я не уверен, как правильно подключить сигналы в PyQt5.Мой код ниже сделан на PyQt4, и я хотел бы преобразовать его в более новый стандарт.(В основном я написал это в другой среде, и теперь я пытаюсь заставить его работать на этом компьютере)
Как правильно подключить элементы графического интерфейса к каждой функции?Прежде чем я подключил свой элемент кнопки pushButtonNext
через:
@QtCore.Slot()
def on_pushButtonSolution_clicked(self):
print('Total Solutions to Display {}'.format(self.total_questions))
И для подключения пунктов меню я назвал это в __init__
:
self.actionNew.triggered.connect(self.MenuNew)
self.actionNew.setShortcut("Ctrl+N")
, где MenuNew()
выглядит следующим образом:
def MenuNew(self):
print('clicked on new')
fileToOpen = QtWidgets.QFileDialog.getOpenFileName(self)
print(fileToOpen)
if(fileToOpen[0] is not ''):
print('Change doc')
self.clearObjects()
self.setWindowTitle("OpenTester - " + fileToOpen[0])
#self.convertDocx(fileToOpen[0])
#self.parse(fileToOpen[0])
self.displayQuestion(self.test[0],1)
Для удобства вот мой полный код:
# -*- coding: utf-8 -*-
# imports for gui
import sys
import os
from PyQt5 import QtCore, QtWidgets, uic, QtGui
#from testevalutils import gui
# imports for parser
import docx2txt
import Question
# Path to the directory containing this .py file (same directory as .ui file)
THIS_DIR = os.path.abspath(os.path.dirname(__file__))
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
# Calls the QDialog __init__ method with the given parent
super().__init__(parent)
# Load the ui file (created by Qt Designer)
ui_path = os.path.abspath(os.path.join(THIS_DIR, 'MainWindow.ui'))
uic.loadUi(ui_path, self)
# initialize test variables
self.test = []
self.total_questions = 0
self.currentQuestion = 0
self.displayedQuestion = None
# elements
self.checkBoxFlag.setText("QUESTION NUM / 999")
self.textBrowserQuestion.setText("")
# menu bar
self.actionNew.triggered.connect(self.MenuNew)
self.actionNew.setShortcut("Ctrl+N")
# This decorator (@QtCore.Slot) makes it so this method is automatically
# connected to the "clicked" signal of the "pushButton_Add" widget by
# using the naming convention "on_<ObjectName>_<SignalName>"
@QtCore.Slot()
def on_actionNew_clicked(self):
print('Menu>New clicked')
@QtCore.Slot()
def on_pushButtonSolution_clicked(self):
print('Total Solutions to Display {}'.format(self.total_questions))
@QtCore.Slot()
def on_pushButtonNext_clicked(self):
print('Next pushed')
self.saveState()
# if not at the last question
if (self.currentQuestion is self.total_questions):
print("Finished!")
else:
self.currentQuestion = self.currentQuestion + 1
self.displayQuestion(self.test[self.currentQuestion],1)
@QtCore.Slot()
def on_pushButtonBack_clicked(self):
print('Back pushed')
self.saveState()
# go to next question in test array
self.currentQuestion = self.currentQuestion - 1
self.displayQuestion(self.test[self.currentQuestion],1)
# Saves any user changes with check box selections
# usually called when next or back button is pushed
def saveState(self):
checkBoxState = self.checkBoxFlag.isChecked()
answers = []
answer1State = self.checkBoxAnswer1.isChecked()
answers.append(answer1State)
answer2State = self.checkBoxAnswer2.isChecked()
answers.append(answer2State)
answer3State = self.checkBoxAnswer3.isChecked()
answers.append(answer3State)
answer4State = self.checkBoxAnswer4.isChecked()
answers.append(answer4State)
self.displayedQuestion.SaveState(checkBoxState, answers)
print('The answer is set to {} {} {} {}'.format(answer1State,answer2State,answer3State,answer4State))
def disableButton(self, button):
button.setEnabled(False)
### Helper methods ###
def displayQuestion(self, Question, Number):
# display question from object we've parsed
# Add one due to index 0
num = self.currentQuestion + 1
self.checkBoxFlag.setText("Question {} of {}".format(num, len(self.test)))
self.textBrowserQuestion.setText(Question.question)
self.checkBoxAnswer1.setText(Question.AnswerSetAt(0))
self.checkBoxAnswer2.setText(Question.AnswerSetAt(1))
self.checkBoxAnswer3.setText(Question.AnswerSetAt(2))
self.checkBoxAnswer4.setText(Question.AnswerSetAt(3))
# load user changes
self.checkBoxFlag.setChecked(Question.IsFlagged())
self.checkBoxAnswer1.setChecked(Question.LoadAnswer(0))
self.checkBoxAnswer2.setChecked(Question.LoadAnswer(1))
self.checkBoxAnswer3.setChecked(Question.LoadAnswer(2))
self.checkBoxAnswer4.setChecked(Question.LoadAnswer(3))
#if first question disable next button
if(num is 1):
self.pushButtonBack.setEnabled(False)
elif (num is self.total_questions - 1):
self.pushButtonNext.setText("Finish")
else:
self.pushButtonBack.setEnabled(True)
self.pushButtonNext.setText("Next")
self.displayedQuestion = self.test[self.currentQuestion]
None
# Create a txt file "_processed" to read from
def convertDocx(self, filename):
rawtext = docx2txt.process(filename + '.docx')
f = open(filename + '_processed.txt', 'w')
f.write(rawtext)
f.close()
def incrementQuestion(self):
self.total_questions = self.total_questions + 1
def addToTest(self, Question):
self.test.append(Question)
def clearObjects(self):
self.test = []
self.total_questions = 0
self.currentQuestion = 0
self.displayedQuestion = 1
def MenuNew(self):
print('clicked on new')
fileToOpen = QtWidgets.QFileDialog.getOpenFileName(self)
print(fileToOpen)
if(fileToOpen[0] is not ''):
print('Change doc')
self.clearObjects()
self.setWindowTitle("OpenTester - " + fileToOpen[0])
#self.convertDocx(fileToOpen[0])
#self.parse(fileToOpen[0])
self.displayQuestion(self.test[0],1)
# Parse from the txt file
def parse(self, filename):
question_block = False
answer_block = False
explain_block = False
with open(filename + '_processed.txt') as openfileobject:
# set our variable for the question
q_number = None
q_question = ""
q_options = []
q_answer = None
q_explain = ""
for line in openfileobject:
# line.split('\n')
# print(line)
# if only a new line then skip it
if(line == "\n"):
continue
if (not question_block and "QUESTION" in line):
question_block = True
q_number = line
self.total_questions = self.total_questions + 1
# skip to next line to check for its properties
continue
# if found next qustion then get each propertiy and add them
if(question_block):
#keep adding lines until we reach the end
if("?") in line:
question_block = False
answer_block = True
q_question = q_question + line
continue
if(answer_block):
if("A. " in line or "B. " in line or "C. " in line or "D. " in line):
line = line[:-1]
q_options.append(line)
continue
if("Correct Answer:") in line:
q_answer = line
answer_block = False
explain_block = True
continue
if(explain_block):
if("Reference" not in line):
q_explain = q_explain + line
continue
else:
explain_block = False
# Add everything into one question
new_question = Question.Question(q_number, q_question, q_options, q_answer, q_explain)
self.addToTest(new_question)
# Reset our question
q_number = None
q_question = ""
q_options = []
q_answer = None
q_explain = ""
if __name__ == '__main__':
"""Main function that tests the dialog."""
app = QtWidgets.QApplication.instance()
if not app:
app = QtWidgets.QApplication([])
# This ensures errors are reported from GUI callbacks.
# Otherwise it would
# gui.handle_unhandled()
filedocx = 'comptia_practice_3-21-2018'
# initialize our window along with the test components already
w = MainWindow()
w.show()
w.setWindowTitle("OpenTester - " + filedocx + ".docx")
w.convertDocx(filedocx)
w.parse(filedocx)
# load first question object
w.displayQuestion(w.test[w.currentQuestion],1)
# execute app
app.exec_()