PyQt5 ile form üstüne başka form açma

İyi günler. Hani bir giriş yap kısmı olur ve kişinin hesabı olmazda, kayıt ol butonuna tıklayınca kayıt arayüzüne yönlendirir ya. Aynen bunun nasıl yapıldığını bilen var mı? İnternetten bayağı araştırdım ama bulamadım.

Mesela bir buton olacak, ona basınca farklı bir pencere açılacak. Ana pencere arkada halen açık kalacak.

Nasıl yapabilirim bunu?

Ana pencereyi görünmez yap. Diğer ki pencereyi çalıştır. Ya da ana pencereyi boş bir pencere yapman lazım. Ana pencere olarak belirlediğin pencereyi ana menü penceresi yaparsın başka bir pencere oluşturup onu arkada çalışması için ana pencere yapabilirsin.


Örnek kod:

from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout
import sys 

class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.btn = QPushButton("Open the subwindow")
        self.subwindow = SubWindow()
        self.layout = QVBoxLayout(self)
        self.layout.addWidget(self.btn)
        
        self.btn.clicked.connect(lambda: self.subwindow.show())

class SubWindow(QWidget):
    def __init__(self):
        super().__init__()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    widget = MainWindow()
    widget.resize(800, 600)
    widget.show()
    sys.exit(app.exec_())
4 Beğeni

Hocam merhaba.

from PyQt5 import QtWidgets

from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QPushButton, QVBoxLayout

import sys

from Ui_ana import Ui_Form

from Ui_ekle import ui_ekle

from Ui_gor import ui_gor

class MainWindow(QtWidgets.QMainWindow):

    def __init__(self):

        super(MainWindow, self).__init__()

        self.anaui = Ui_Form()

        self.ekleui = ui_ekle()

        self.gorui = ui_gor()

       

        self.anaui.setupUi(self)

       

        self.btn = self.anaui.pushButton_2

        self.subwindow = ui_ekle()

       

        self.anaui.pushButton.clicked.connect(lambda: self.subwindow.show())

class SubWindow(QWidget):

    def __init__(self):

        super().__init__()

if __name__ == '__main__':

    app = QApplication(sys.argv)

    widget = MainWindow()

    widget.resize(800, 600)

    widget.show()

    sys.exit(app.exec_())

QT designer ile tasarladıgım arayüzleri klasöre dahil ettim ve compile ettim. Kodla form oluşturmak yerine kendi tasarladıgım arayüzü kullanmak istiyorum. Yukarıdaki kodla denedim ama olmuyor. Ve bir türlü çekemedim. Kusura bakmayın uğraştırdıysam.

Fark etmez. Hepsinin teorisi, mantığı aynı; hepsi Python, hepsi PyQt5. Bıraktığım örnek kodu ve linkleri dikkatlice incelediyseniz yapılan şeyin hepsinde aynı ve gayet basit olduğunu görmüş olmalısınız:

MainWindow classında SubWindow classının bir instance’i tanımlanır.(self.subwindow) ve SubWindow gösterilmek istendiği zaman show() metoduyla gösterilir.( self.subwindow.show() )


Burada aynı şeyi uygulamışsınız ama işe yaramadığına göre ui_ekle() classında bir problem olmalı. Onu da gösterebilir misiniz ?

Ayrıca nasıl olmadığını da açıklar mısınız ? Bir hata mesajı vs. var mı ?

1 Beğeni
# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'c:\Users\emiry\Desktop\deneme\ekle.ui'

#

# Created by: PyQt5 UI code generator 5.15.6

#

# WARNING: Any manual changes made to this file will be lost when pyuic5 is

# run again.  Do not edit this file unless you know what you are doing.

from PyQt5 import QtCore, QtGui, QtWidgets

class ui_ekle(object):

    def setupUi(self, Form):

        Form.setObjectName("ana")

        Form.resize(400, 300)

        self.lineEdit = QtWidgets.QLineEdit(Form)

        self.lineEdit.setGeometry(QtCore.QRect(120, 70, 161, 51))

        self.lineEdit.setObjectName("lineEdit")

        self.pushButton_4 = QtWidgets.QPushButton(Form)

        self.pushButton_4.setGeometry(QtCore.QRect(160, 160, 131, 51))

        self.pushButton_4.setObjectName("pushButton_4")

        self.retranslateUi(Form)

        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):

        _translate = QtCore.QCoreApplication.translate

        Form.setWindowTitle(_translate("Form", "Form"))

        self.pushButton_4.setText(_translate("Form", "Kaydet"))

Ekran Alıntısı

Butona bastığımda bu hatayı alıyorum:

Traceback (most recent call last):
  File "c:\Users\emiry\Desktop\deneme\index.py", line 22, in <lambda>   
    self.anaui.pushButton.clicked.connect(lambda: self.subwindow.show())
AttributeError: 'ui_ekle' object has no attribute 'show'

ui_ekle objesinin show diye bir metodu yok demek istiyor.
Neden ?
Çünkü show metodu PyQt5’teki pencere classlarına ait bir metot ve siz ui_ekle classında herhangi bir windowu (QWidget, QMainWindow) miras almamışsınız (inheritance)

Mesela

Burada QWidget’ı miras alırsanız bu sorun düzelecektir:

Ama QtDesigner dosyalarıyla çalışırken genelde tercih edilen şey bu değil ki zaten setupUi da boşuna yapılmıyor.

Yani demek istediğim:

from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow
from Ui_ekle import ui_ekle
import sys 


# Yeni bir class oluşturulur
class UIEkle(QWidget): # QWidget miras alınır. Show attribute'unu ve daha pek çok şeyi alıyoruz aslında burada
    def __init__(self):
        super().__init__() # QWidget'ı initialize ediyoruz
        self.ui = ui_ekle() # Designer UI'ının bir instance'ini tanımlıyoruz
        self.ui.setupUi(self) # setupUi ile içeriği/görüntüyü buraya aktarıyoruz

class MainWindow(QMainWindow): 
    def __init__(self):
        super().__init__()
        self.subwindow = UIEkle() # Öncesinde elimizde sadece görüntü vardı, bu sefer fonksiyonel materyalleri de aldık, işlevle görüntü birleşti
        self.subwindow.show() # O yüzden artık kullanılabilir 

if __name__ == '__main__':
    app = QApplication(sys.argv)
    widget = MainWindow()
    widget.resize(800, 600)
    widget.show()
    sys.exit(app.exec_())

Umarım anlatabilmişimdir.


Bu arada konuyla alakasız ama ek olarak söyleyeyim, Python’da class’ları PascalCase ile isimlendirmeliyiz.

3 Beğeni

Hocam kusura bakmayın cidden uğraştırıyorum ama. Bu sefer de ikisi bir açıldı. Click ile class’a bağlamayı denedikten sonra dönüş yapacağım.

        from Ui_ana import Ui_Form
        self.ana = Ui_Form()
        self.ana.setupUi(self) # setupUi ile içeriği/görüntüyü buraya aktarıyoruz

Bu kodları ekleyerek yapmayı denedim.

Nereye eklediniz ?


“Click ile class’a bağlamak” ne demek ?
Bir butona basıldığı zaman açılmasını mı istiyorsunuz ? Bunu yapmayı zaten biliyordunuz ? :thinking:

1 Beğeni

Hocam

    self.ana.pushButton.clicked.connect(UIEkle)

Bu kodu, mainWindows class’a ekledim. Bu hatayı alıyorum:

Traceback (most recent call last):
  File "c:\Users\emiry\.vscode\extensions\ms-python.python-2021.12.1559732655\pythonFiles\lib\python\debugpy\_vendored\pydevd\_pydevd_bundle\pydevd_trace_dispatch_regular.py", line 359, in __call__
    is_stepping = pydev_step_cmd != -1
RecursionError: maximum recursion depth exceeded in comparison

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "c:\Users\emiry\Desktop\deneme\index.py", line 13, in __init__
    self.subwindow = UIEkle() # Íncesinde elimizde sadece g÷r³nt³ vard², bu sefer fonksiyonel materyalleri de ald²k, i■levle g÷r³nt³ birle■ti       
  File "c:\Users\emiry\Desktop\deneme\index.py", line 13, in __init__
    self.subwindow = UIEkle() # Íncesinde elimizde sadece g÷r³nt³ vard², bu sefer fonksiyonel materyalleri de ald²k, i■levle g÷r³nt³ birle■ti       
  File "c:\Users\emiry\Desktop\deneme\index.py", line 13, in __init__
    self.subwindow = UIEkle() # Íncesinde elimizde sadece g÷r³nt³ vard², bu sefer fonksiyonel materyalleri de ald²k, i■levle g÷r³nt³ birle■ti
  [Previous line repeated 488 more times]
  File "c:\Users\emiry\Desktop\deneme\index.py", line 12, in __init__
    self.ui.setupUi(self) # setupUi ile ieri­i/g÷r³nt³y³ buraya aktar²yoruz
  File "c:\Users\emiry\Desktop\deneme\Ui_ekle.py", line 25, in setupUi
    self.retranslateUi(Form)
  File "c:\Users\emiry\Desktop\deneme\Ui_ekle.py", line 28, in retranslateUi
    def retranslateUi(self, Form):
  File "c:\Users\emiry\.vscode\extensions\ms-python.python-2021.12.1559732655\pythonFiles\lib\python\debugpy\_vendored\pydevd\_pydevd_bundle\pydevd_trace_dispatch_regular.py", line 469, in __call__
    return None if event == 'call' else NO_FTRACE
RecursionError: maximum recursion depth exceeded in comparison

Neden bu hatayı alıyor anlamadım. Hata anlamını anladım da, neden hata verdiğini anlayamadım.

class MainWindow(QMainWindow):

    def __init__(self):

        super().__init__()

        self.ana = Ui_Form()

        self.ana.setupUi(self)

       

        self.ana.pushButton.clicked.connect(UIEkle)

Kusura bakmayın uğraştırdıysam.

UIEkle bir fonksiyon mu ?

Bir class ise butona tıklandığında hiçbir şey olmaz. Bir fonksiyon olmalı orada.
Kodların yarıdan fazlasını bilmeden bir şey anlatmak çok zor.

Yapmak istediğin şey bir butona basıldığı zaman subwindow’un açılmasıysa "kaydet"e basıldığında subwindow’un açıldığı bir örnek:

from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow, QVBoxLayout, QPushButton
from Ui_ekle import ui_ekle
import sys 

class SubWindow(QWidget):
    def __init__(self):
        super().__init__()

class UIEkle(QWidget):
    def __init__(self):
        super().__init__()
        self.subwindow = SubWindow()
        self.ui = ui_ekle()
        self.ui.setupUi(self)
        self.ui.pushButton_4.clicked.connect(lambda: self.subwindow.show())

if __name__ == '__main__':
    app = QApplication(sys.argv)
    widget = UIEkle()
    widget.resize(800, 600)
    widget.show()
    sys.exit(app.exec_())

Çok teşekkür ederim, oldu.

Başkalarının da işine yarar diye kodu bırakayım:

from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow, QVBoxLayout, QPushButton

from Ui_ekle import ui_ekle

from Ui_ana import Ui_Form

import sys

class SubWindow(QWidget):

    def __init__(self):

        super().__init__()

        self.ui = ui_ekle()

        self.ui.setupUi(self)

class UIEkle(QWidget):

    def __init__(self):

        super().__init__()

        self.subwindow = SubWindow()

        self.ui = ui_ekle()

        self.ana = Ui_Form()

        self.ana.setupUi(self)

        self.ana.pushButton.clicked.connect(lambda: self.subwindow.show())

if __name__ == '__main__':

    app = QApplication(sys.argv)

    widget = UIEkle()

    widget.resize(800, 600)

    widget.show()

    sys.exit(app.exec_())