Как мне поменять выводы print() на вывод в окно приложения PyQt5?
Мы делаем простенькую игру и я не знаю, как сделать вывод в отдельном окне,
т.к. не силен в PyQt5. Помогите, пожалуйста.
import random
from time import *
from random import choices as cho
from random import randrange as RR
from Enemies import enemylist
class Hero:
def __init__(self, name, health, armor, fights=0):
self.name = name
self.health = health
self.fights = fights
self.armor = armor
self.dmgup = 0
self.crtchup = 0
self.sboy1 = False
self.sboy2 = False
self.seek_points = False
self.weaponlist = [[10, 25, 'булава'], [15, 25, "полуторный меч"], [20, 15, "кувалда"],
[30, 10, "тяжёлая секира"], [10, 50, "кинжал"], [15, 30, "арбалет"]]
self.startweapon = random.choice(self.weaponlist)
self.weaponlist.pop(self.weaponlist.index(self.startweapon))
self.crit_chan = self.startweapon[1]
self.damage = self.startweapon[0]
self.weapon = self.startweapon[2]
self.health_default = self.health
self.armor_default = self.armor
def print_info(self):
print('Поприветстввуйте героя ->', self.name)
print('Уровень здоровья:', self.health_default)
print('Класс брони:', self.armor_default)
print('Сила удара:', self.damage + self.dmgup)
print('Оружие:', self.weapon)
print('Шанс критического удара:', str(self.crit_chan + self.crtchup) + '%')
print("\n")
sleep(5)
def strike(self, enemy):
if self.sboy1 == True:
self.crit_chan = (self.crit_chan + self.crtchup) // 2
self.sboy1 = False
crit_str = False
crit = cho([1, 2], weights=(self.crit_chan + self.crtchup, 100 - (self.crit_chan + self.crtchup)))[0]
if crit == 1:
crit_str = True
if crit_str == True:
if self.sboy2 == True:
self.damage = (self.damage + self.dmgup) * 4
else:
self.damage = (self.damage + self.dmgup) * 2
print('-> КРИТИЧЕСКИЙ УДАР! ' + self.name + ' атакует ' + enemy.name + ' с силой ' + str(
self.damage) + ', используя ' + self.weapon + '\n')
if self.seek_points == True:
enemy.health -= self.damage + self.dmgup
else:
enemy.armor -= self.damage + self.dmgup
if self.sboy2 == True:
self.damage //= 4
else:
self.damage //= 2
else:
print('-> УДАР! ' + self.name + ' атакует ' + enemy.name + ' с силой ' + str(
self.damage) + ', используя ' + self.weapon + '\n')
if self.seek_points == True:
enemy.health -= self.damage
else:
enemy.armor -= self.damage
sleep(2)
if enemy.armor < 0:
enemy.health += enemy.armor
enemy.armor = 0
print(enemy.name + ' покачнулся(-ась).\nКласс его(её) брони упал до ' + str(
enemy.armor) + ', а уровень здоровья до ' + str(enemy.health))
def fight(self, enemy):
while self.health and enemy.health > 0:
self.strike(enemy)
if enemy.health <= 0:
print(enemy.name, 'пал(а) в этом нелёгком бою!\n')
enemy.health = 0
sleep(2)
if self.health > 0:
rul = cho([1, 2, 3, 4], weights=(25, 25, 25, 25))[0]
self.health = self.health_default
self.armor = self.armor_default
if rul == 1:
self.health_default += 10
print('HP UP')
elif rul == 2:
self.dmgup += 7
print('DMG UP')
elif rul == 3:
self.armor_default += 10
print('DEF UP')
elif rul == 4:
self.crtchup += 5
print('CRIT chance UP')
self.fights += 1
if self.fights % 4 == 0:
bigrul = cho([1, 2], weights=(75, 25))[0]
if bigrul == 1 and self.sboy2 == False:
print(self.name,
'получил пасивный навык "Сбой": его шанс критического удара уменьшился в 2 раза, но урон от критической атаки вырос в 2 раза')
self.sboy1 = True
self.sboy2 = True
elif bigrul == 2:
print(self.name, 'получил пасивный навыу "Взгляд палача": его атки игнорируют защиту врга')
self.seek_points = True
if self.fights % 3 == 0:
dropedweap = random.choice(self.weaponlist)
if dropedweap != self.startweapon:
print('Какая удача вы обнаружили', dropedweap[2], 'с уроном', dropedweap[0],
'и шансом критического удара', dropedweap[1], ". Подобрать его?")
print("ДА или НЕТ")
while True:
otvet1 = input()
if otvet1.upper() == 'ДА':
self.startweapon = dropedweap
self.weaponlist.pop(self.weaponlist.index(dropedweap))
self.crit_chan = self.startweapon[1]
self.damage = self.startweapon[0]
self.weapon = self.startweapon[2]
self.print_info()
break
elif otvet1.upper() == 'НЕТ':
print('Вы оставили', dropedweap[2], "валятся на земле")
break
else:
print('Да или Нет?')
break
sleep(5)
enemy.strike(self)
if self.health <= 0:
print(self.name, 'пал в этом нелёгком бою!\n')
self.health = 0
sleep(5)
class Monster:
def __init__(self):
self.names = enemylist
enemynow = self.names[RR(0, len(self.names))]
self.name = enemynow[0]
self.health = enemynow[1]
self.armor = enemynow[2]
self.crit_chan = enemynow[3]
self.damage = enemynow[4]
self.weapon = enemynow[5]
if cho([1, 2], weights=(25, 75))[0] == 1:
self.damage *= 2
self.armor = round(self.armor * 1.5)
self.health = round(self.health * 1.5)
self.crit_chan += 10
print("Кажется,", self.name, "мутирует: его здоровье теперь", self.health, ', броня', self.armor, ', урон',
self.damage, ", а шанс критического удара", self.crit_chan, "\n")
sleep(3)
def print_info(self):
print('На пути появился', str(self.name))
print('Уровень здоровья:', self.health)
print('Класс брони:', self.armor)
print('Сила удара:', self.damage)
print('Шанс критического удара:', str(self.crit_chan) + '%')
print('\n')
sleep(5)
def strike(self, enemy):
crit_str = False
crit = cho([1, 2], weights=(self.crit_chan, 100 - self.crit_chan))[0]
if crit == 1:
crit_str = True
if crit_str == True:
self.damage *= 2
print('-> КРИТИЧЕСКИЙ УДАР! ' + self.name + ' атакует ' + enemy.name + ' с силой ' + str(
self.damage) + ', используя ' + self.weapon + '\n')
enemy.armor -= self.damage
else:
print('-> УДАР! ' + self.name + ' атакует ' + enemy.name + ' с силой ' + str(
self.damage) + ', используя ' + self.weapon + '\n')
enemy.armor = self.damage
sleep(3)
if enemy.armor < 0:
enemy.health += enemy.armor
enemy.armor = 0
print(enemy.name + ' покачнулся(-ась).\nКласс его(её) брони упал до ' + str(
enemy.armor) + ', а уровень здоровья до ' + str(enemy.health))
def fight(self, enemy):
while self.health and enemy.health > 0:
self.strike(enemy)
if enemy.health <= 0:
print(enemy.name, 'пал(а) в этом нелёгком бою!\n')
enemy.health = 0
sleep(3)
break
sleep(5)
enemy.strike(self)
if self.health <= 0:
print(self.name, 'пал в этом нелёгком бою!\n')
self.health = 0
sleep(5)
class location():
def __init__(self, hardness):
self.hardness = hardness
self.roomcount = (self.hardness * 5) + RR(-2, 2)
def generation(self):
campfiersgen = self.roomcount // 1 + (self.hardness)
print("Добро пожаловать в Hero's quest".title())
print("Введите свое имя")
n = input()
knight = Hero(n, 25, 10)
knight.print_info()
print(' ')
print("Введите колличество раундов (1-5)")
co = int(input())
print("Начнется же приключение" + '\n')
for i in range(1, co + 1):
rascal = Monster()
sleep(3)
rascal.print_info()
sleep(3)
knight.print_info()
sleep(1)
knight.fight(rascal)
sleep(2)
P.S. Модуль Enemies.py содержит список и только список.
Ответы (1 шт):
Всегда приводите минимально-воспроизводимый пример, который демонстрирует проблему.
Чтобы запустить и как-то протестировать ваше приложение, я заменил модуль Enemies.py на выдуманныйenemylist = [...]
Не используйте
timr.sleep()
в основном потоке GUI - это ничего кроме заморозки интерфейса не делает.Будьте осторожны с использованием
while True:
в основном цикле,
это также может заморозить ваше приложение.
Помните, что длительные вычисления должны выполняться в дополнительном потоке.
QApplication.processEvents() - обрабатывает некоторые ожидающие события для вызывающего потока.
Вы можете вызывать эту функцию время от времени, когда ваша программа занята выполнением длительной операции. Обычно он используется в качестве запасного wheel при использовании длинных циклов блокировки в коде, выполняющемся в потоке графического интерфейса, чего следует избегать.В общем случае, ответ на ваш вопрос заключается в замене строки:
print(f'Какая-то строка для печати')
на
_print = f'Какая-то строка для печати' self.textBrowser.append(_print)
где
self.textBrowser
это экземпляр класса QTextBrowser, который предоставляет браузер форматированного текста с гипертекстовой навигацией.input()
- не используется в GUI.
Вместо него вам надо вызвать какое-то модальное окно и запросить в нем какие-то данные.
Я не проверял вашу логику программы, но внес некоторые
изменения, которые необходимы для работы приложения.
Попробуйте, если что-то конкретное будет не понятно - спросите.
import sys
#import random
#from time import *
from random import choices as cho, choice
from random import randrange as RR
from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5.Qt import *
#?from Enemies import enemylist #?#?#?#?#?#?#?
enemylist = [
['Name_1', 2, 3, 4, 5, 'weapon6'],
['Name_2', 22, 23, 24, 25, 'weapon26'],
['Name_3', 3332, 3333, 3334, 3335, 'weapon336'],
]
class Hero(QObject):
def __init__(self, name, health, armor, fights, parent=None):
super().__init__(parent)
self.parent = parent
self.name = name
self.health = health
self.fights = fights
self.armor = armor
self.dmgup = 0
self.crtchup = 0
self.sboy1 = False
self.sboy2 = False
self.seek_points = False
self.weaponlist = [
[10, 25, 'булава'],
[15, 25, "полуторный меч"],
[20, 15, "кувалда"],
[30, 10, "тяжёлая секира"],
[10, 50, "кинжал"],
[15, 30, "арбалет"]
]
self.startweapon = choice(self.weaponlist)
self.weaponlist.pop(self.weaponlist.index(self.startweapon))
self.crit_chan = self.startweapon[1]
self.damage = self.startweapon[0]
self.weapon = self.startweapon[2]
self.health_default = self.health
self.armor_default = self.armor
def print_info(self):
self.parent.textBrowser.append(f"Поприветстввуйте героя: {self.name}")
self.parent.textBrowser.append(f"Уровень здоровья: {self.health_default}")
self.parent.textBrowser.append(f"Класс брони: {self.armor_default}")
self.parent.textBrowser.append(f"Сила удара: {self.damage + self.dmgup}")
self.parent.textBrowser.append(f"Оружие: {self.weapon}")
self.parent.textBrowser.append(f"Шанс критического удара:{self.crit_chan + self.crtchup}%")
def strike(self, enemy):
if self.sboy1 == True:
self.crit_chan = (self.crit_chan + self.crtchup) // 2
self.sboy1 = False
crit_str = False
crit = cho(
[1, 2],
weights=(self.crit_chan + self.crtchup,
100 - (self.crit_chan + self.crtchup))
)[0]
if crit == 1:
crit_str = True
if crit_str == True:
if self.sboy2 == True:
self.damage = (self.damage + self.dmgup) * 4
else:
self.damage = (self.damage + self.dmgup) * 2
_print = f'-> КРИТИЧЕСКИЙ УДАР! {self.name} атакует '\
f'{enemy.name} с силой {self.damage} '\
f'используя {self.weapon}\n'
self.parent.textBrowser.append(_print)
if self.seek_points == True:
enemy.health -= self.damage + self.dmgup
else:
enemy.armor -= self.damage + self.dmgup
if self.sboy2 == True:
self.damage //= 4
else:
self.damage //= 2
else:
_print = f'-> УДАР! {self.name}, атакует {enemy.name}' \
f' с силой {self.damage}, используя {self.weapon}\n'
self.parent.textBrowser.append(_print)
if self.seek_points == True:
enemy.health -= self.damage
else:
enemy.armor -= self.damage
# sleep(2)
if enemy.armor < 0:
enemy.health += enemy.armor
enemy.armor = 0
_print = f'{enemy.name} покачнулся(-ась).\n' \
f'Класс его(её) брони упал до {enemy.armor}' \
f', а уровень здоровья до {enemy.health}'
self.parent.textBrowser.append(_print)
def fight(self, enemy):
while self.health and enemy.health > 0:
self.strike(enemy)
if enemy.health <= 0:
self.parent.textBrowser.append(
f'{enemy.name}, пал(а) в этом нелёгком бою!\n')
enemy.health = 0
if self.health > 0:
rul = cho([1, 2, 3, 4], weights=(25, 25, 25, 25))[0]
self.health = self.health_default
self.armor = self.armor_default
if rul == 1:
self.health_default += 10
# print('HP UP')
self.parent.textBrowser.append('HP UP')
elif rul == 2:
self.dmgup += 7
self.parent.textBrowser.append('DMG UP')
elif rul == 3:
self.armor_default += 10
self.parent.textBrowser.append('DEF UP')
elif rul == 4:
self.crtchup += 5
self.parent.textBrowser.append('CRIT chance UP')
self.fights += 1
if self.fights % 4 == 0:
bigrul = cho([1, 2], weights=(75, 25))[0]
if bigrul == 1 and self.sboy2 == False:
_print = f'{self.name} получил пасивный навык ' \
f'"Сбой": его шанс критического удара ' \
f'уменьшился в 2 раза, но урон от ' \
f'критической атаки вырос в 2 раза'
self.parent.textBrowser.append(_print)
self.sboy1 = True
self.sboy2 = True
elif bigrul == 2:
_print = f'{self.name} получил пасивный навыу '\
f'"Взгляд палача": его атки игнорируют '\
f'защиту врга'
self.parent.textBrowser.append(_print)
self.seek_points = True
if self.fights % 3 == 0:
dropedweap = choice(self.weaponlist)
if dropedweap != self.startweapon:
self.parent.textBrowser.append(f'Какая удача вы обнаружили {dropedweap[2]}, с уроном, {dropedweap[0]}, '
f'и шансом критического удара, {dropedweap[1]}. Подобрать его?')
self.parent.textBrowser.append("ДА или НЕТ")
while True:
# --- otvet1 = input()
otvet1 = self.getTextInputDialog(dropedweap)
if otvet1.upper() == 'ДА':
self.startweapon = dropedweap
self.weaponlist.pop(self.weaponlist.index(dropedweap))
self.crit_chan = self.startweapon[1]
self.damage = self.startweapon[0]
self.weapon = self.startweapon[2]
# ??? self.print_info()
break
elif otvet1.upper() == 'НЕТ':
_print = f'Вы оставили {dropedweap[2]} валятся на земле'
self.parent.textBrowser.append(_print)
break
# else:
# print('Да или Нет?')
#? break
# sleep(5)
enemy.strike(self) # ?
if self.health <= 0:
_print = f'{self.name} пал в этом нелёгком бою!\n'
self.parent.textBrowser.append(_print)
self.health = 0
# sleep(5)
QApplication.processEvents()
# +++
def getTextInputDialog(self, dropedweap):
text, okPressed = QtWidgets.QInputDialog.getText(
None,
"Критический удар",
f"""Какая удача вы обнаружили `{dropedweap[2]}`, с уроном `{dropedweap[0]}`,
и шансом критического удара, {dropedweap[1]}. Подобрать его?'
ДА или НЕТ?""",
QtWidgets.QLineEdit.Normal,
"Да")
if not okPressed:
text = 'НЕТ'
return text.upper()
class Monster(QObject):
def __init__(self, parent=None):
super(Monster, self).__init__(parent)
self.parent = parent
self.names = enemylist
enemynow = self.names[RR(0, len(self.names))]
self.name = enemynow[0]
self.health = enemynow[1]
self.armor = enemynow[2]
self.crit_chan = enemynow[3]
self.damage = enemynow[4]
self.weapon = enemynow[5]
if cho([1, 2], weights=(25, 75))[0] == 1:
self.damage *= 2
self.armor = round(self.armor * 1.5)
self.health = round(self.health * 1.5)
self.crit_chan += 10
_print = f'\nКажется, {self.name} мутирует: его здоровье '\
f'теперь {self.health}, броня {self.armor} , урон ' \
f'{self.damage}, а шанс критического удара {self.crit_chan}\n'
self.parent.textBrowser.append(_print)
def print_info(self):
self.parent.textBrowser.append(f"""
На пути появился -> {self.name}
Уровень здоровья: {self.health}
Класс брони: {self.armor}
Сила удара: {self.damage}
Шанс критического удара: {self.crit_chan}%
""")
def strike(self, enemy):
crit_str = False
crit = cho([1, 2], weights=(self.crit_chan, 100 - self.crit_chan))[0]
if crit == 1:
crit_str = True
if crit_str == True:
self.damage *= 2
_print = f'-> КРИТИЧЕСКИЙ УДАР! {self.name}, атакует ' \
f'{enemy.name} с силой {self.damage}' \
f', используя {self.weapon}\n'
self.parent.textBrowser.append(_print)
enemy.armor -= self.damage
else:
_print = f'-> УДАР! {self.name}, атакует {enemy.name}' \
f' с силой {self.damage}, используя {self.weapon}\n'
self.parent.textBrowser.append(_print)
enemy.armor = self.damage
if enemy.armor < 0:
enemy.health += enemy.armor
enemy.armor = 0
_print = f'{enemy.name} покачнулся(-ась).\n'\
f'Класс его(её) брони упал до {enemy.armor}' \
f', а уровень здоровья до {enemy.health}'
self.parent.textBrowser.append(_print)
def fight(self, enemy):
while self.health and enemy.health > 0:
self.strike(enemy)
if enemy.health <= 0:
_print = f'{enemy.name} пал(а) в этом нелёгком бою!\n'
self.parent.textBrowser.append(_print)
enemy.health = 0
# break
# sleep(5)
enemy.strike(self)
if self.health <= 0:
_print = f'{self.name} пал в этом нелёгком бою!\n'
self.parent.textBrowser.append(_print)
self.health = 0
QApplication.processEvents()
''' ???????????????
class location():
def __init__(self, hardness):
self.hardness = hardness
self.roomcount = (self.hardness * 5) + RR(-2, 2)
def generation(self):
campfiersgen = self.roomcount // 1 + (self.hardness)
'''
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.central_widget = QWidget(self)
self.setCentralWidget(self.central_widget)
self.label = QLabel("Добро пожаловать в Hero's quest")
self.label.setAlignment(Qt.AlignHCenter|Qt.AlignTop)
self.label_2 = QLabel("Введите свое имя")
self.label_2.setAlignment(Qt.AlignRight|Qt.AlignTop)
self.health = QSpinBox()
self.health.setRange(0, 100)
self.health.setSingleStep(5)
self.health.setValue(25)
self.armor = QSpinBox()
self.armor.setRange(0, 100)
self.armor.setSingleStep(1)
self.armor.setValue(10)
self.fights = QSpinBox(minimum=0, maximum=4)
self.co = QSpinBox(minimum=1, maximum=5)
self.button = QPushButton('Start')
self.button.clicked.connect(self.on_clicked)
self.groupBox = QGroupBox("Настройте параметры и нажмите Start")
self.gb_layout = QFormLayout(self.groupBox)
self.gb_layout.addRow("Уровень здоровья:", self.health)
self.gb_layout.addRow("Класс брони:", self.armor)
self.gb_layout.addRow("Fights:", self.fights)
self.gb_layout.addRow("Введите колличество раундов:", self.co)
self.gb_layout.addRow("", self.button)
self.name_lineEdit = QLineEdit(
placeholderText='Введите ваше имя и нажмите Enter')
self.name_lineEdit.returnPressed.connect(self._returnPressed)
self.textBrowser = QTextBrowser()
self.layout = QGridLayout(self.central_widget)
self.layout.addWidget(self.label, 0, 0, 1, 2)
self.layout.addWidget(self.label_2, 1, 0)
self.layout.addWidget(self.name_lineEdit, 1, 1)
self.layout.addWidget(self.groupBox, 3, 0, 1, 1)
self.layout.addWidget(self.textBrowser, 2, 1, 3, 1)
self.layout.setRowStretch(2, 1)
self.layout.setRowStretch(4, 1)
self.layout.setColumnStretch(1, 1)
self.groupBox.setEnabled(False)
def _returnPressed(self):
if not self.name_lineEdit.text():
return
self.groupBox.setEnabled(True)
self.co.setFocus()
def _rascal(self):
for i in range(self.co.value()): #(1, co + 1):
self.textBrowser.append(f"<h3>-=- {i+1} раунд. -=-</h3>")
self.rascal = Monster(self)
self.rascal.print_info()
# ??? self.knight.print_info() # ???
self.knight.fight(self.rascal)
def on_clicked(self):
self.textBrowser.append("<h2>Начинается приключения.</h2>")
self.groupBox.setEnabled(False)
QApplication.processEvents()
self.knight = Hero(
self.name_lineEdit.text(),
self.health.value(),
self.armor.value(),
self.fights.value(),
self)
self.knight.print_info()
self._rascal()
self.textBrowser.append(
f"<b style='color: #C81912;'> {'-'*77}</b><br>")
self.groupBox.setEnabled(True)
Stylesheet = '''
/* тут вы можете установить свои стили для виджетов */
'''
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
app.setStyleSheet(Stylesheet)
app.setFont(QtGui.QFont("Times", 11, QtGui.QFont.Bold))
w = MainWindow()
w.setWindowTitle("Простенькая игра")
w.resize(1200, 600)
w.show()
sys.exit(app.exec())