Zwierzak
Zwierzak

Reputation: 686

How to switch between two windows in python using PyQt

I am working on some app. I wanted to create a toolbar that after having been clicked will open Settings window. However I don't know how to do it exactly. The way it is now is that i have a Toolbar icon connected to ShowSettings function. This function creates a new instance of settings each time I click on the icon ( i know it shouldn't create new instances each time but only one in the beginning and then work on it. I don't know how to do it though) and then show the settings window associated with this instance. However in this way the settings window only flashes for a second and then disappears. I don't know what's wrong hope you can help me out :)

import sys
import time
from PyQt4 import QtCore, QtGui
from ui import Ui_MainWindow
from ui import Ui_SettingsWindow

#Aplikacja obslugujaca bramki LF
#zamiana pliku .ui na kod pythona
#pyuic4 untitled.ui -o output.py
class timerThread(QtCore.QThread):
    timeElapsed = QtCore.pyqtSignal(float)

    def __init__(self, parent=None):
        super(timerThread, self).__init__(parent)
        self.timeStart = None

    def start(self, timeStart):
        self.timeStart = timeStart

        return super(timerThread, self).start()

    def run(self):
        while self.parent().isRunning():
            self.timeElapsed.emit(time.time() - self.timeStart)
            time.sleep(0.1)


class myThread(QtCore.QThread):
    timeElapsed = QtCore.pyqtSignal(float)
    def __init__(self, parent=None):
        super(myThread, self).__init__(parent)

        self.timerThread = timerThread(self)
        self.timerThread.timeElapsed.connect(self.timeElapsed.emit)

    def run(self):
        self.timerThread.start(time.time())

        iterations = 10000000000
        while iterations:
            print "Running {0}".format(self.__class__.__name__)
            iterations -= 1
            time.sleep(10)   

class SettingsWindow(QtGui.QMainWindow):
    #Constructor:
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.ui_settigns = Ui_SettingsWindow()
        self.ui_settigns.setupUi(self)

class MainWindow(QtGui.QMainWindow):

    #Constructor:
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)


        self.myThread = myThread(self)
        self.myThread.timeElapsed.connect(self.on_myThread_timeElapsed)
        self.myThread.finished.connect(self.on_myThread_finished)

        #Nie wiem jak przerzucic to do pliku UI bez errorow
        #Toolbar
        settingsAction = QtGui.QAction(QtGui.QIcon('tools.jpg'), 'Ustawienia', self)
        settingsAction.setShortcut('Ctrl+U')
        settingsAction.triggered.connect(self.ShowSettings)

        self.toolbar = self.addToolBar('Settings')
        self.toolbar.addAction(settingsAction)

    def UpdateList(self):
        contest_name = self.ui.comboBox.currentText()

        #jakis try-catch tutaj sie przyda gdyby nie plik nie istnial
        #zczytuje z pliku liste robotow
        with open('database\%s.txt' % contest_name) as f:
                robots_list = f.read().splitlines()

        self.ui.listWidget.clear()
        self.ui.listWidget.addItems(robots_list)

    def Search(self):
        text = self.ui.lineEdit.text()
        self.ui.lineEdit.clear() 
        item = self.ui.listWidget.findItems(text, QtCore.Qt.MatchExactly)

        #jakiegos try-catcha trzeba tutaj walnac
        self.ui.listWidget.setItemSelected(item[0], True)

    def ShowSettings(self):
        settings = SettingsWindow() #creates settings instance
        settings.show()

    @QtCore.pyqtSlot()
    def on_button_clicked(self):
        self.myThread.start()

    @QtCore.pyqtSlot(int)
    def on_myThread_timeElapsed(self, seconds):
        self.ui.lcdNumber.display(seconds)

    @QtCore.pyqtSlot()
    def on_myThread_finished(self):
        self.myThread.terminate()
        print "Done"


if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    myapp = MainWindow()
    settings = SettingsWindow()
    myapp.show()
    settings.show()

    sys.exit(app.exec_())

And Here is the UI file

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'untitled.ui'
#
# Created: Fri Apr 24 08:04:20 2015
#      by: PyQt4 UI code generator 4.11.3
#
# WARNING! All changes made in this file will be lost!

from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_SettingsWindow(object):
    def setupUi(self, SettingsWindow):
        SettingsWindow.setObjectName(_fromUtf8("Ustawienia"))
        SettingsWindow.resize(686, 556)

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        MainWindow.resize(686, 556)

        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.groupBox = QtGui.QGroupBox(self.centralwidget)
        self.groupBox.setGeometry(QtCore.QRect(10, 10, 341, 491))
        self.groupBox.setObjectName(_fromUtf8("groupBox"))
        self.pushButton = QtGui.QPushButton(self.groupBox)
        self.pushButton.setGeometry(QtCore.QRect(10, 460, 231, 23))
        self.pushButton.setObjectName(_fromUtf8("pushButton"))
        self.label = QtGui.QLabel(self.groupBox)
        self.label.setGeometry(QtCore.QRect(10, 80, 90, 16))
        self.label.setObjectName(_fromUtf8("label"))
        self.lineEdit = QtGui.QLineEdit(self.groupBox)
        self.lineEdit.setGeometry(QtCore.QRect(130, 77, 191, 20))
        self.lineEdit.setObjectName(_fromUtf8("lineEdit"))
        self.listWidget = QtGui.QListWidget(self.groupBox)
        self.listWidget.setGeometry(QtCore.QRect(10, 110, 321, 341))
        self.listWidget.setObjectName(_fromUtf8("listWidget"))
        item = QtGui.QListWidgetItem()
        self.listWidget.addItem(item)
        item = QtGui.QListWidgetItem()
        self.listWidget.addItem(item)
        item = QtGui.QListWidgetItem()
        self.listWidget.addItem(item)
        self.label_2 = QtGui.QLabel(self.groupBox)
        self.label_2.setGeometry(QtCore.QRect(10, 50, 111, 16))
        self.label_2.setObjectName(_fromUtf8("label_2"))
        self.comboBox = QtGui.QComboBox(self.groupBox)
        self.comboBox.setGeometry(QtCore.QRect(130, 50, 191, 22))
        self.comboBox.setObjectName(_fromUtf8("comboBox"))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.groupBox_2 = QtGui.QGroupBox(self.centralwidget)
        self.groupBox_2.setGeometry(QtCore.QRect(360, 10, 311, 491))
        self.groupBox_2.setObjectName(_fromUtf8("groupBox_2"))
        self.lcdNumber = QtGui.QLCDNumber(self.groupBox_2)
        self.lcdNumber.setGeometry(QtCore.QRect(10, 20, 281, 151))
        self.lcdNumber.setSmallDecimalPoint(True)
        self.lcdNumber.setObjectName(_fromUtf8("lcdNumber"))
        self.pushButton_2 = QtGui.QPushButton(self.groupBox_2)
        self.pushButton_2.setGeometry(QtCore.QRect(20, 340, 75, 23))
        self.pushButton_2.setObjectName(_fromUtf8("pushButton_2"))
        self.pushButton_3 = QtGui.QPushButton(self.groupBox_2)
        self.pushButton_3.setGeometry(QtCore.QRect(200, 340, 75, 23))
        self.pushButton_3.setObjectName(_fromUtf8("pushButton_3"))
        MainWindow.setCentralWidget(self.centralwidget)


        self.retranslateUi(MainWindow)
        QtCore.QObject.connect(self.pushButton, QtCore.SIGNAL(_fromUtf8("clicked()")), self.lineEdit.clear)
        QtCore.QObject.connect(self.lineEdit, QtCore.SIGNAL("returnPressed()"), MainWindow.Search) #connected to Search method in class MainWindow
        QtCore.QObject.connect(self.comboBox, QtCore.SIGNAL(_fromUtf8("currentIndexChanged(QString)")), MainWindow.UpdateList)
        QtCore.QObject.connect(self.pushButton_2, QtCore.SIGNAL(_fromUtf8("clicked()")), MainWindow.on_button_clicked)
        QtCore.QObject.connect(self.pushButton_3, QtCore.SIGNAL(_fromUtf8("clicked()")), MainWindow.on_myThread_finished)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(_translate("MainWindow", "LF Timer", None))
        self.groupBox.setTitle(_translate("MainWindow", "Wybierz robota", None))
        self.pushButton.setText(_translate("MainWindow", "Uruchom Aplikację Pomiaru Czasu", None))
        self.label.setText(_translate("MainWindow", "Wyszukaj robota:", None))
        self.lineEdit.setText(_translate("MainWindow", "cos tam", None))
        __sortingEnabled = self.listWidget.isSortingEnabled()
        self.listWidget.setSortingEnabled(False)
        item = self.listWidget.item(0)
        item.setText(_translate("MainWindow", "Robot 1", None))
        item = self.listWidget.item(1)
        item.setText(_translate("MainWindow", "Robot 2", None))
        item = self.listWidget.item(2)
        item.setText(_translate("MainWindow", "Robot 3", None))
        self.listWidget.setSortingEnabled(__sortingEnabled)
        self.label_2.setText(_translate("MainWindow", "Wybierz Konkurencje:", None))
        self.comboBox.setItemText(0, _translate("MainWindow", "", None))
        self.comboBox.setItemText(1, _translate("MainWindow", "LF", None))
        self.comboBox.setItemText(2, _translate("MainWindow", "TURBO LF", None))
        self.comboBox.setItemText(3, _translate("MainWindow", "LEGO LF", None))
        self.groupBox_2.setTitle(_translate("MainWindow", "Pomiar Czasu", None))
        self.pushButton_2.setText(_translate("MainWindow", "Start", None))
        self.pushButton_3.setText(_translate("MainWindow", "Stop", None))

Upvotes: 0

Views: 2348

Answers (2)

Zwierzak
Zwierzak

Reputation: 686

Thank you three_pineapples for your help. I used the second way that you have described. It works like a dream :) Here's the code if anyone needs it.

import sys
import time
from PyQt4 import QtCore, QtGui
from ui import Ui_MainWindow
from ui import Ui_SettingsWindow

#Aplikacja obslugujaca bramki LF
#zamiana pliku .ui na kod pythona
#pyuic4 untitled.ui -o output.py

#py to exe
#python setup.py py2exe --includes sip
class timerThread(QtCore.QThread):
    timeElapsed = QtCore.pyqtSignal(float)

    def __init__(self, parent=None):
        super(timerThread, self).__init__(parent)
        self.timeStart = None

    def start(self, timeStart):
        self.timeStart = timeStart

        return super(timerThread, self).start()

    def run(self):
        while self.parent().isRunning():
            self.timeElapsed.emit(time.time() - self.timeStart)
            time.sleep(0.1)


class myThread(QtCore.QThread):
    timeElapsed = QtCore.pyqtSignal(float)
    def __init__(self, parent=None):
        super(myThread, self).__init__(parent)

        self.timerThread = timerThread(self)
        self.timerThread.timeElapsed.connect(self.timeElapsed.emit)

    def run(self):
        self.timerThread.start(time.time())

        iterations = 10000000000
        while iterations:
            print "Running {0}".format(self.__class__.__name__)
            iterations -= 1
            time.sleep(10)   

class SettingsWindow(QtGui.QMainWindow):
    #Constructor:
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.ui_settigns = Ui_SettingsWindow()
        self.ui_settigns.setupUi(self)

class MainWindow(QtGui.QMainWindow):

    #Constructor:
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.settings = SettingsWindow()# Creates and stores SettingsWindow instance, MainWindow manages SettingsWindow

        self.myThread = myThread(self)
        self.myThread.timeElapsed.connect(self.on_myThread_timeElapsed)
        self.myThread.finished.connect(self.on_myThread_finished)

        #Nie wiem jak przerzucic to do pliku UI bez errorow
        #Toolbar
        settingsAction = QtGui.QAction(QtGui.QIcon('tools.jpg'), 'Ustawienia', self)
        settingsAction.setShortcut('Ctrl+U')
        settingsAction.triggered.connect(self.ShowSettings)

        self.toolbar = self.addToolBar('Settings')
        self.toolbar.addAction(settingsAction)

    def UpdateList(self):
        contest_name = self.ui.comboBox.currentText()

        #jakis try-catch tutaj sie przyda gdyby nie plik nie istnial
        #zczytuje z pliku liste robotow
        with open('database\%s.txt' % contest_name) as f:
                robots_list = f.read().splitlines()

        self.ui.listWidget.clear()
        self.ui.listWidget.addItems(robots_list)

    def Search(self):
        text = self.ui.lineEdit.text()
        self.ui.lineEdit.clear() 
        item = self.ui.listWidget.findItems(text, QtCore.Qt.MatchExactly)

        #jakiegos try-catcha trzeba tutaj walnac
        self.ui.listWidget.setItemSelected(item[0], True)

    def ShowSettings(self):
        self.settings.show()

    @QtCore.pyqtSlot()
    def on_button_clicked(self):
        self.myThread.start()

    @QtCore.pyqtSlot(int)
    def on_myThread_timeElapsed(self, seconds):
        self.ui.lcdNumber.display(seconds)

    @QtCore.pyqtSlot()
    def on_myThread_finished(self):
        self.myThread.terminate()
        print "Done"


if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    myapp = MainWindow()
    myapp.show()

    sys.exit(app.exec_())

Upvotes: 0

three_pineapples
three_pineapples

Reputation: 11849

The instance of the settings window is local to the MainWindow.ShowSettings method. As such, it is quickly garbage collected because nothing keeps a reference to the window.

You can fix this in two ways. The first is to specify a parent of the settings window when it is instantiated. The second is to store it as an instance attribute of MainWindow (eg self.settings = ...).

Upvotes: 3

Related Questions