The problem is that your subwindow must be owned by another object, else it is immediatly destroyed by the garbage collector. Therefore, this works (see the 'show_concentration_test_window' method):
#!/usr/bin/python3 import sys import time from random import choice from PyQt5.QtWidgets import QApplication, QMainWindow from PyQt5.uic import loadUi from PyQt5 import QtCore class ConcentrationTest(object): def __init__(self, COLORS, designated_color): self.COLORS = COLORS self.designated_color = designated_color self.start_time = None self.color = None self.color_locked = True self.reaction_times = [] self.false_positives = 0 self.color_missed = 0 self.key_too_often_pressed = 0 def space_pressed(self): if self.color == self.designated_color: if self.color_locked: self.key_too_often_pressed += 1 else: reaction_time = time.monotonic() - self.start_time self.reaction_times.append(reaction_time) self.color_locked = True else: self.false_positives += 1 def next_round(self): if not self.color_locked and self.color == self.designated_color: self.color_missed += 1 self.color_locked = False current_color = self.color while self.color == current_color: self.color = choice(list(self.COLORS.values())) self.start_time = time.monotonic() return self.color class MainWindow(QMainWindow): def __init__(self, parent=None): super().__init__() loadUi("mainwindow.ui", self) self.COLORS = {"Black": QtCore.Qt.black, "Blue": QtCore.Qt.blue, "Cyan": QtCore.Qt.cyan, "Green": QtCore.Qt.green, "Magenta": QtCore.Qt.magenta, "Red": QtCore.Qt.red, "Yellow": QtCore.Qt.yellow} self.comboBox_designated_color.addItems(self.COLORS) self.pushButton_start_test.clicked.connect(self.show_concentration_test_window) def get_designated_color(self): return self.COLORS[self.comboBox_designated_color.currentText()] def get_switch_time(self): return self.spinBox_switch_time.value() def show_concentration_test_window(self): self.concentration_test = ConcentrationTest(self.COLORS, self.get_designated_color()) self.concentration_test_window = ConcentrationTestWindow(self.concentration_test, self.get_switch_time()) self.concentration_test_window.show() self.concentration_test_window.change_screen_color() class ConcentrationTestWindow(QMainWindow): def __init__(self, concentration_test, switch_time, parent=None): super().__init__(parent) self.showFullScreen() self.concentration_test = concentration_test self.switch_time = switch_time self.timer = QtCore.QTimer() self.timer.timeout.connect(self.change_screen_color) self.pal = self.palette() self.setAutoFillBackground(True) def change_screen_color(self): color = self.concentration_test.next_round() self.pal.setColor(self.backgroundRole(), color) self.setPalette(self.pal) self.timer.start(self.switch_time) def keyPressEvent(self, event): if event.key() == QtCore.Qt.Key_Escape: self.close() if event.key() == QtCore.Qt.Key_Space: self.concentration_test.space_pressed() def main(): app = QApplication(sys.argv) main_window = MainWindow(app) main_window.show() sys.exit(app.exec_()) if __name__ == "__main__": main()From a quick look, the structure would also need to be reviewed a bit, i.e. why declare concentration_test here
def __init__(self, concentration_test, parent=None):as when you init the MainWindow, only app is passed
main_window = MainWindow(app)