Bir pencereyi kapatıp başka birisini açmak

Pyqt5 ile çalışıyorum. Uygulamanın ana penceresinden önce bir Dialog penceresi göstermek istiyorum. Dialog penceresinde bir LineEdit ve PushButton var. Bu LineEdit’e girilen text ana pencerede kullanılacak. Push Button da Dialog penceresini kapatıp ana pencereyi getirecek.

İki sorum var:

  1. Bir Dialog penceresini kapatıp ana pencereyi nasıl açarım?
  2. İki pencere arasında bilgi aktarımını nasıl yaparım?

Login Screen

from PyQt5.QtWidgets import QApplication, QWidget, QDialog, QMainWindow
from PyQt5.QtCore import pyqtSignal
import sys

from Ui_LoginScreen import Ui_Dialog
from QtCar import Car

class LoginWindow(QDialog):

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

        #Makes the window from imported "Ui_Form"
        self.ui = Ui_Dialog()
        self.ui.setupUi(self)

        
        self.ui.loginButton.clicked.connect(self.doLogin)

    def doLogin(self):
        self.username = self.ui.lineEdit_username.text()

        window = Car()
        window.show()
        sys.exit(app.exec_())

if __name__ == "__main__":
    
    app = QApplication(sys.argv)
    dialog = LoginWindow()
    dialog.show()   #Pushes created objects
    sys.exit(app.exec_())

Main Window

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow, QDialog

from Ui_CarSim import Ui_MainWindow
from Ui_About import Ui_about_dialog


class Car(QMainWindow):

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

        #Setup Window
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        #Engine Status
        self.engine_status = False

        #General Window Adjustments
        self.ui.statusbar.showMessage("Welcome!", 3000)
        self.ui.actionAbout.triggered.connect(self.about)

        #Fuel Tank Values
        self.fuel_tank_capacity = 60
        self.fuel_tank = 0

        #Fuel Gauge
        self.ui.fuel_level.setMaximum(self.fuel_tank_capacity)

        #Signals and Slots
        self.ui.start_engine.clicked.connect(self.engine_start)
        self.ui.stop_engine.clicked.connect(self.engine_stop)
        self.ui.refuel.clicked.connect(self.refuel)
        self.ui.run.clicked.connect(self.run)

    #About Dialog Window
    def about(self):

        dialog = QDialog()
        dialog.ui = Ui_about_dialog()
        dialog.ui.setupUi(dialog)
        dialog.exec_()

    def refuel(self):
        """Refuels the car."""

        self.amount = self.ui.amount.text()
        self.ui.amount.clear()

        try:
            if self.engine_status == True:
                self.ui.statusbar.showMessage("Cannot refuel while engine is running!")
                print("Cannot refuel while engine is running!")

            elif self.fuel_tank == self.fuel_tank_capacity:
                self.ui.statusbar.showMessage("Tank full!")
                print("Tank full!")

            elif self.amount == "":
                f_amount = self.fuel_tank_capacity - self.fuel_tank
                self.fuel_tank = self.fuel_tank_capacity
                self.ui.fuel_level.setValue(self.fuel_tank)

                self.ui.statusbar.showMessage("Refueled {} liters!".format(f_amount))
                print("Refueled {} liters!".format(f_amount))
            
            elif int(self.amount) < 0:
                self.ui.statusbar.showMessage("Amount cannot be negative number!")
                print("Amount cannot be negative number!")
            
            elif int(self.amount) > 60:
                self.ui.statusbar.showMessage("Tank cannot hold {} liters. Capacity is {} liters.".format(
                    self.amount, self.fuel_tank_capacity))
                print("Tank cannot hold {} liters. Capacity is {} liters.".format(
                    self.amount, self.fuel_tank_capacity))

            elif (int(self.amount) <= 60) and ((int(self.amount) + self.fuel_tank) > 60):
                self.ui.statusbar.showMessage("Tank can hold only {} more liters.".format(self.fuel_tank_capacity - self.fuel_tank))
                print("Tank can hold only {} more liters.".format(self.fuel_tank_capacity - self.fuel_tank))
            
            else:
                self.fuel_tank += int(self.amount)
                self.ui.fuel_level.setValue(self.fuel_tank)

                self.ui.statusbar.showMessage("Refueled {} liters!".format(int(self.amount)))
                print("Refueled {} liters!".format(int(self.amount)))
        
        except ValueError:
            self.ui.amount.clear()
            self.ui.statusbar.showMessage("Amount have to be INT!")
            print("Amount have to be INT!")

    def engine_start(self):
        """Starts the engine."""
        if self.engine_status == True:
            self.ui.statusbar.showMessage("Engine already started!")
            print("Engine already started!")
        
        elif self.fuel_tank == 0:
            self.ui.statusbar.showMessage("Tank empty!")
            print("Tank empty!")

        else:
            self.engine_status = True

            self.ui.statusbar.showMessage("Engine started!")
            print("Engine started!")
            
    
    def engine_stop(self):
        """Stops the engine."""
        if self.engine_status == True:
            self.engine_status = False

            self.ui.statusbar.showMessage("Engine stopped!")
            print("Engine stopped!")
            
        else:
            self.ui.statusbar.showMessage("Engine already stopped!")
            print("Engine already stopped!")
    
    def run(self):
        """Moves the car."""
        try:
            self.distance = int(self.ui.distance.text())
            self.ui.distance.clear()
            
            if (self.distance > 0) and (self.engine_status == True) and (self.fuel_tank > 0):
                req_fuel = int(self.distance) * 0.093

                if req_fuel > self.fuel_tank:
                    self.ui.statusbar.showMessage("Not enough fuel!")
                    print("Not enough fuel!")
                
                else:
                    self.fuel_tank -= req_fuel
                    self.ui.fuel_level.setValue(self.fuel_tank)

                    self.ui.statusbar.showMessage("Car successfully runned {} km!".format(self.distance))
                    print("Car successfully runned {} km and consumed {} liters!".format(self.distance, req_fuel))
                    print("Fuel left: {}".format(self.fuel_tank))

            elif self.distance < 0:
                self.ui.statusbar.showMessage("Distance can't be negative!")
                print("Distance can't be negative!")

            elif self.engine_status == False:
                self.ui.statusbar.showMessage("Engine is not started!")
                print("Engine is not started!")
        
        except ValueError:
            self.ui.distance.clear()

            self.ui.statusbar.showMessage("Distance have to be INT!")
            print("Distance have to be INT!")
            
if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Car()
    window.show()
    sys.exit(app.exec_())

Eğer Ui.py dosyalarına da ihtiyaç olursa diye:

Kusura bakma,pyqtSignal ile pyqtSlot a bak,işini görecektir.Kodlarına bir düzenleme çekip size veririm(özür dilerim,telden yazıyorum, şu anda fazla örnek atamayacağım.)

from PyQt5.QtCore import *

class a(QObject):
    benim_sinyalim = pyqtSignal()

adana = a()

@pyqtSlot()
def seninFonksiyonun():
    print('sinyal aldim')

adana.benim_sinyalim.connect(seninFonksiyonun)
while True:
    cevap = input('benim_sinyalim adli sinyali yaymak ister misiniz e/h')
    if cevap == "h":
        break
    elif cevap == 'e':
        adana.benim_sinyalim.emit()   #burada sinyal yayarsiniz

Başka bir basit örnek:

from PyQt5.QtCore import *

class a(QObject):
    benim_sinyalim = pyqtSignal(str)

adana = a()

@pyqtSlot(str)
def seninFonksiyonun(emitFonksiyonuIleGelenString):
    print('sinyal aldim,şöyle bir kelime ile sinyal yaydim', emitFonksiyonuIleGelenString)

adana.benim_sinyalim.connect(seninFonksiyonun)
while True:
    cevap = input('benim_sinyalim adli sinyalle ne yazdirmak istediğini yaz')
   
    adana.benim_sinyalim.emit(cevap)   #burada sinyal yayarsiniz

Bu kodlari deneyip kendinizce geliştirmeye uğraşın,anlayamadiğiniz yeri sorun.Bilgi dahilinde cevaplanmaya çalışılır.

İyi çalışmalar,
Kolay gelsin :slightly_smiling_face:

Edit: Ayrica qtdesignerde slot bağlama konusuna da bir göz atmalısın,çok işine yarayacağını düşünüyorum.

2 Beğeni

Çok teşekkür ederim. Çok yararlı oldu, çok işime yaradı :slight_smile:

Bende takıldım bu konuda.
Bir tane anasayfa var. Burada içerik eklemek için toolbarda butona tıklanılacak ve içerik ekleme tasarımı açılıcak ama arkada hala anasayfa açık kalacak. Bunu nasıl yapabilirim?

Tkinter kullandıysanız bilirsiniz. Frame diye bir widget var. Pencere gibi üzerine birtakım widget eklenebiliyor. Ancak bir widget gibi ekrandan kaldırılıp tekrar getirilebiliyor. PyQt de böyle bir şey yok mu?

Tkinter kullanmadım hiç. Pyqt de de varmı bakayım frame.

Pyqt de de böyle bir şey var

Sizin aradığınız Dialog başlığı altında ModalDialog olarak geçiyor PyQt’de. Türkçesi bir kılavuzda “Akılsız diyalog” olarak çevrilmişti sanırım. Ayrıca Signals and Slots konusuna da bakmanız lazım. Sonuç olarak yeni bir pencere açmak için bir eyleme ihtiyacınız olacak.

Qt çok gelişmiş bir EventHandler’a sahip fakat bu gelişmişlik, basit durumlarda yeni öğrenen (benim gibi) kişilere karmaşık bir yapı olarak gözüküyor.

Bir örnek varmı widgets açmak istiyorum bununla alakalı.

Şöyle bir kod yazdım umarım işinizi görür:

import sys
from PyQt5.QtWidgets import (QWidget, QApplication, QPushButton, QLabel, QInputDialog)

class Ornek(QWidget):

    def __init__(self, *args):
        super().__init__(*args)
        
        #Burada ana pencereyi çalıştırıyoruz.
        self.ana_pencere()

    #Burada ana pencereyi tanımlıyoruz.    
    def ana_pencere(self):
        
        self.setGeometry(100, 100, 300, 100) #Pencere konumu (100,100) ve boyutları (300, 100)
        self.setWindowTitle("diyalog butonu denemesi") #Pencere başlığı

        self.buton = QPushButton("Diyalog", self) #Butonumuzu oluşturduk.
        self.buton.move(50,50) #Butonun konumunu ayarladık.

        self.etiket = QLabel(self) #Metin göstermek için bir etiket oluşturduk.
        self.etiket.move(50,15) #Etiketin konumunu ayarladık.
        self.etiket.setText("YER TUTUCU MESAJ") #Etiketin orjinal mesajı.

        self.buton.clicked.connect(self.diyalog_ac) #Buton için sinyal atadık.

        # "self.button" bizim butonumuz.
        # "clicked" butonun ne olduğunda sinyal yayacağını söylüyor. (Tıklanınca)
        # "connect" buton sinyalinin kime bağlanacağını gösteriyor. ("diyalog_ac" Fonsksiyonu)

        self.show() # Arkaplanda hazırladığımız pencereyi ekrana ittik.

    def diyalog_ac(self):
        metin, onay= QInputDialog.getText(self, "test", "Buraya metni gir:") 
        
        # QInputDialog hazır bir pencere türü. Kendisi içinde bir adet "QLineEdit" barındırıyor.
        # "metin" değişkenini yazdığımız yazı için belirledik.
        # "onay" değişkeni QInputDialog'un dönüşünde verdiği "True" ya da "False" için belirledik.

        if onay: #Eğer onay "True" dönerse (yani OK tuşuna basarsak)
            self.etiket.setText(str(metin)) #Ana penceredeki etiketin metnin yazdığımız ile değiştirdik.



if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = Ornek()
    sys.exit(app.exec_())

Şu şekilde birşey yaptım ancak fonksiyonu çalıştıramadım bir yerde eksiklik var ama çözemedim.

Anasayfa penceresi

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import sys
from ekle import *

        def ac(self):
            self.window = QtWidgets.QWidget()
            self.ui.ekle(self.window)
            self.window.show()

    class anamenu(QMainWindow):
        def __init__(self):
            super().__init__()
        
                self.setWindowTitle("Pul Koleksiyonum")
                self.setFixedHeight(600)
                self.setFixedWidth(900)
                
                sayfa = QPushButton(self)
                sayfa.move(50,50)
                sayfa.setText('Tıkla Aç')
                
                sayfa.clicked.connect(self.ac)

    
uygulama	=	QApplication(sys.argv)
pencere	=	anamenu()
pencere.show()
uygulama.exec_()

Açılacak pencere

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import sys

class ekle(QWidget):
    def __init__(self):
        super().__init__()
        
        self.setWindowTitle("Ekleme Sayfası")
        self.setFixedHeight(400)
        self.setFixedWidth(700)
        
        etiket = QLabel(self)
        etiket.move(300,200)
        etiket.setText('Açılan Sayfa')

    
uygulama	=	QApplication(sys.argv)
pencere	=	ekle()
pencere.show()
uygulama.exec_()

Fonksiyon tabi ki açılmaz:

def ac(self):
            self.window = QtWidgets.QWidget()
            self.ui.ekle(self.window)
            self.window.show()

    class anamenu(QMainWindow):
        def __init__(self):
            super().__init__()
        
                self.setWindowTitle("Pul Koleksiyonum")
                self.setFixedHeight(600)
                self.setFixedWidth(900)
                
                sayfa = QPushButton(self)
                sayfa.move(50,50)
                sayfa.setText('Tıkla Aç')
                
                sayfa.clicked.connect(self.ac)

ac fonksiyonu anamenu classının içinde değil ki.class ın dışında tanımlanmış.ac fonksıyonunu class ın içinde tanımlayın.Galiba dikkatsizlik olmuş:) olur oyle kazalar.

Kolay gelsin :blush:

O programın hiç çalışmaması gerekiyor.
İndention hatası vermeli.

Kodlarınızı inceledim. Sırayla bakalım:

  • Öncelikle @Cihat_Altiparmak dediği gibi ac(self) fonksiyonu sınıf dışında kalmış. Sınıf içerisinde olmalı.

  • @hasser dediği gibi ana pencereye ait kodlar bu haliyle Indention hatası verir. Bunun anlamı girintileme kurallarına uymamışız demek oluyor.

  • Burası önemli: from x import * ifadesi x modülündeki tüm isim alanlarını benim modülüme boca et anlamına geliyor. Belki örnek vermek için bu şekilde bir kullanım uygundur fakat unutmayın bu önerilen bir yöntem değildir. İsimlerde yaşanılacak bir çakışma sizi zor durumda bırakabilir.

Bunlar halledildikten sonra PyQt kurallarına uygun düzeltmeleri yapalım. Önce kodlarınızın düzenli ve çalışır halini vereyim:

ana_pencere.py

from PyQt5.QtWidgets import QMainWindow, QPushButton, QWidget, QApplication, QDialog
import sys
from ekle import ekle

class anamenu(QMainWindow):
    def __init__(self):
        super().__init__()
        
        self.setWindowTitle("Pul Koleksiyonum")
        self.setFixedHeight(600)
        self.setFixedWidth(900)
                
        sayfa = QPushButton(self)
        sayfa.move(50,50)
        sayfa.setText('Tıkla Aç')
                
        sayfa.clicked.connect(self.ac)

    #ac() fonksiyonunu sınıf içine aldık. 
    def ac(self):
        self.widget = QWidget() #Penceremiz bir widget olduğundan QWidget sınıfını örnekledik. 
        self.yeni_pencere = ekle() #Yeni açılacak olan penceremizi örnekledik. Bu sayede kullanıma hazır hale geldi. 
        self.yeni_pencere.show() #Oluşturduğumuz pencereyi ekrana gösterdik. 
        
#Burası da önemli: kodlarınızın doğrudan çalışmasını istediğinizde bu ifadeyi kullanın.
if __name__ == "__main__":  
    uygulama	=	QApplication(sys.argv)
    pencere	=	anamenu()
    pencere.show()
    uygulama.exec_()

ekle.py

from PyQt5.QtWidgets import QWidget, QLabel
import sys

class ekle(QWidget):
    def __init__(self):
        super().__init__()
        
        self.setWindowTitle("Ekleme Sayfası")
        self.setFixedHeight(400)
        self.setFixedWidth(700)
        
        etiket = QLabel(self)
        etiket.move(300,200)
        etiket.setText('Açılan Sayfa')

        self.show() #Bu ifade önemli. Oluşturduğumuz pencereyi ekranda göstermek için bu komutu kullanıyoruz. 

Ek olarak:

uygulama	=	QApplication(sys.argv)
pencere	=	ekle()
pencere.show()
uygulama.exec_()
  • Bu ifadelere açacağınız yeni pencerede ihtiyaç yok. Çünkü bu pencere diğerinin içinden açılacak. Doğrudan çalıştırılmayacak. Burada çıkardığımız "show() ifadesini init içine aldık.

Umarım yardımcı olur. Kolay gelsin :slight_smile:

1 Beğeni

Bu kadar ayrıntılı ve açıklamalı şekilde anlatıp kodları düzenlediğiniz için teşekkür ederim. Baya baya yardımcı oldu pencere işlemleri adına baya yardımcı oldu tekrar teşekkürler.

Rica ederim. Kolay gelsin :slight_smile: