PyQt5 projem İle alakalı bir sorun var

PyQt5 Öğrenmeye yeni başladım. Belirli bir kısma kadar geldim. Sonra biraz kendi projelerimi ürettikten sonra öğrenmeye devam edecektim.
Bu o projelerden bir tanesi.

Ders çalışırken pomodoro tekniği kullandığım için ona yönelik bir şey yaptım.
25 dakika
5 dakika
20 dakika

olmak üzere 3 tane buton bulunmakta.
Butonların üçü de çalışıyor. Süre bitince alarm misali müzik çalıyor.

Ancak şöyle 2 tane problem var :
birincisi :
karşımıza çıkan 3 butonun altında bir yazı alanı bulunmakta. “Pomodoro için hangi işlemi kullanacaksınız” diye. Butonlardan herhangi birine bastığımda x dakika çalışmaya başladı demesini istiyorum ancak yazdığım kod işe yaramadı nedense.

Ve müzikler sadece 1 kere çalınabiliyor. Başka bir dakikaya bastığımda uygulama hata verip donuyor.

Ne yapmalıyım ?

import sys
from PyQt5 import QtWidgets
import simpleaudio as sa
import time


class pencere(QtWidgets.QWidget):

    def __init__(self):
        
        super().__init__()
        self.init_ui()


    def init_ui(self):
        self.yazialani = QtWidgets.QLabel("Pomodoro Tekniği İçin Hangisini seçeceksin ?")
        self.minute = 0
        self.button1 = QtWidgets.QPushButton("25 Dakika")
        self.button2 = QtWidgets.QPushButton("5 Dakika")
        self.button3 = QtWidgets.QPushButton("20 Dakika")
        

        v_box = QtWidgets.QVBoxLayout()
        v_box.addWidget(self.button1)
        v_box.addWidget(self.button2)
        v_box.addWidget(self.button3) 
        v_box.addWidget(self.yazialani)
        v_box.addStretch()

        h_box = QtWidgets.QHBoxLayout()
        h_box.addStretch()
        h_box.addLayout(v_box)
        h_box.addStretch()

        self.setLayout(h_box)

        self.button1.clicked.connect(self.click1)
        self.button2.clicked.connect(self.click2)
        self.button3.clicked.connect(self.click3)
        

        self.show()


    def click1(self):
        self.minute = 25
        self.yazialani.setText("{} Dakika sonra alarm  çalacaktır".format(str(self.minute)))
        time.sleep(self.minute * 60)
        wave_obj = sa.WaveObject.from_wave_file("C:/Users/taylan öztürk/Desktop/NCS/Alan Walker/Wav/Force.wav")
        play_obj = wave_obj.play()
        play_obj.wait_done()
        

    def click2(self):
        self.minute = 5
        self.yazialani.setText("{} Dakika sonra alarm  çalacaktır".format(str(self.minute)))
        time.sleep(self.minute * 60)
        wave_obj = sa.WaveObject.from_wave_file("C:/Users/taylan öztürk/Desktop/NCS/Alan Walker/Wav/Force.wav")
        play_obj = wave_obj.play()
        play_obj.wait_done()


    def click3(self):
        self.minute = 20
        self.yazialani.setText("{} Dakika sonra alarm  çalacaktır".format(str(self.minute)))
        time.sleep(self.minute * 60)
        wave_obj = sa.WaveObject.from_wave_file("C:/Users/taylan öztürk/Desktop/NCS/Alan Walker/Wav/Force.wav")
        play_obj = wave_obj.play()
        play_obj.wait_done()
        


    


    


app = QtWidgets.QApplication(sys.argv)
window = pencere()

sys.exit(app.exec_())




hadi ama en azından bir müziği çalıştırdığımda programın donma sorununu yazabilecek yok mu :frowning:

Merhaba;

Bu kolay. Anahtar kelime: QMessageBox

Bu bir problem değil. Siz bunu yapmak istiyorsunuz. Programı ‘uyuttuğunuz’ zaman, program ‘uykudan’ çıkmadan başka bir işlem yapamaz. x dakika kadar “uyu!” diyorsunuz ve ardından hala uykuda iken başka bir emir vermeye çalışıyorsunuz.

Şuan kodlarınızı kopyaladım, üzerinde çalışıyorum.

1 Beğeni

Multithreading kullanmalısın. Qt nin kendi multithreading class ı vardı sanırım ama araştırmam lazım bilgi verebilmek için. Ama threading kütüphanesini kullanırsan sorunu çözebilirsin.

burayı şöyle düzenleyin

self.button3.clicked.connect(lambda:Thread(target=self.click3).start())

ve en üst satıra gelip

from threading import Thread

yazarsanız sorununuz hallolacaktır.

1 Beğeni

Hayır. Sleep kısmında elbette bir işlemin gerçekleşmemesi normal.
Fakat sorun şu ki :

Sleep bittiğinde bir müzik çalıyor.
O müzikten sonrasında da yeni bir dakika deneyemiyorum.

Sabah deneyeceğim şimdiden teşekkürler

Vaktim olmadığı için yorumda bulunucam sadece probleminiz pyqt5 yüzünden olmuyor büyük ihtimalle normalde pythonla bir script yazdığınızda işlemler sırayla ilerler biri biter diğeri başlar vesaire burda wait_done işlemi sonlandırmıyor tıkla Burayı okuyun is_playing() ve stop methodlarini deneyin. Bunlari yaptıktan sonra olumlu olumsuz dönüş yapın , olmadi ben yardimci olucam

Programı sıfırdan yazmak durumunda kaldım ama kodları paylaşmadan önce yaptığınız hatalardan biraz bahsetmek istiyorum.

  • Zamanlayıcıya ihtiyacınız varsa time.sleep() kullanmayın. Direkt threading modülünden Timer sınıfını veya başka güncel modülleri kullanın.
  • Her zaman söylüyorum; tasarımlarınız ya farklı bir sınıfta ya da farklı bir dosyada olsun.
  • show() metodunu sınıf içerisinde kullanmayın.Çünkü show() metodu sadece kendisinden önce gelen/tanımlanan nesneleri ‘gösterir’.
    Örnek: 5. satırda bir buton oluşturdunuz ve hemen ardından 6. satırda show() metodunu kullandınız. 7.satırda ise tekrar bir buton oluşturdunuz. 7. satırda oluşturulan buton ekranda gözükmeyecektir. Çünkü show() metodundan sonra oluşturuldu. Treni kaçırdı :slight_smile:
  • wait_done() metodunu kullanarak ‘Oynatılan ses dosyasının bitmesini bekle’ diyorsunuz. Ardından henüz bu işlem tamamlanmadan başka bir komut vermeye çalışıyorsunuz (başka bir butona tıklamak). Dolayısıyla program ‘yanıt veremiyor’. Bunun sebebi de wait_done() metodunun ses dosyası oynatıldığı sürece arkada time.sleep(0.05) komutunu çalıştırması. Bu problemi de @ertugrulcakici arkadaşımızın tavsiyesi ile çözebiliriz. Ancak bu kez de farklı bir sorun çıkacak: Butona her tıklandığında ses dosyası bir kere daha oynatılacak ve sesler üst üste binecek.

Ben tasarım dosyasını ayrı bir dosyada tutmayı tercih ettim. Aynı dosya içerisinde, farklı bir sınıfta da olabilirdi.

# program.py

import sys
from PyQt5.QtWidgets import (QApplication, QMainWindow, QMessageBox, QPushButton)
from PyQt5.QtCore import QTimer
import simpleaudio as sa
from tasarim import Ui_Form




class Pomodoro(QMainWindow):
	def __init__(self):
		super().__init__()
		self.ui = Ui_Form()
		self.ui.setupUi(self)
		self.setWindowTitle("Pomodoro Tekniği ile Çalış")

		self.ui.pushButton.clicked.connect(self.period1)
		self.ui.pushButton_2.clicked.connect(self.period2)
		self.ui.pushButton_3.clicked.connect(self.period3)
		self.ui.pushButton_4.clicked.connect(self.period4)

		self.timer = QTimer()
		self.audio = sa.WaveObject.from_wave_file("audio.wav")
	def period1(self):
		self.timer.stop()
		self.timer.singleShot(300000, lambda:self.audio.play())
		QMessageBox.information(self, "Bilgilendirme", "5 dakikalık periyot başladı.")

	def period2(self):
		self.timer.stop()
		self.timer.singleShot(900000, lambda:self.audio.play())
		QMessageBox.information(self, "Bilgilendirme", "15 dakikalık periyot başladı.")
	
	def period3(self):
		self.timer.stop()
		self.timer.singleShot(1500000, lambda:self.audio.play())
		QMessageBox.information(self, "Bilgilendirme", "25 dakikalık periyot başladı.")

	def period4(self):
		self.timer.stop()
		self.timer.singleShot(2100000, lambda:self.audio.play())
		QMessageBox.information(self, "Bilgilendirme", "35 dakikalık periyot başladı.")


if __name__ == "__main__":
    app = QApplication(sys.argv)

    window = Pomodoro()
    window.show()

    sys.exit(app.exec_())
# tasarim.py

from PyQt5.QtCore import (QCoreApplication, QDate, QDateTime, QMetaObject,
    QObject, QPoint, QRect, QSize, QTime, QUrl, Qt)
from PyQt5.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont,
    QFontDatabase, QIcon, QKeySequence, QLinearGradient, QPalette, QPainter,
    QPixmap, QRadialGradient)
from PyQt5.QtWidgets import *


class Ui_Form(object):
    def setupUi(self, Form):
        if not Form.objectName():
            Form.setObjectName(u"Form")
        Form.resize(400, 400)
        self.gridLayoutWidget = QWidget(Form)
        self.gridLayoutWidget.setObjectName(u"gridLayoutWidget")
        self.gridLayoutWidget.setGeometry(QRect(9, 119, 381, 271))
        self.gridLayout = QGridLayout(self.gridLayoutWidget)
        self.gridLayout.setObjectName(u"gridLayout")
        self.gridLayout.setContentsMargins(0, 0, 0, 0)
        self.pushButton_3 = QPushButton(self.gridLayoutWidget)
        self.pushButton_3.setObjectName(u"pushButton_3")
        font = QFont()
        font.setPointSize(11)
        self.pushButton_3.setFont(font)

        self.gridLayout.addWidget(self.pushButton_3, 1, 0, 1, 1)

        self.pushButton_2 = QPushButton(self.gridLayoutWidget)
        self.pushButton_2.setObjectName(u"pushButton_2")
        self.pushButton_2.setFont(font)

        self.gridLayout.addWidget(self.pushButton_2, 0, 1, 1, 1)

        self.pushButton_4 = QPushButton(self.gridLayoutWidget)
        self.pushButton_4.setObjectName(u"pushButton_4")
        self.pushButton_4.setFont(font)

        self.gridLayout.addWidget(self.pushButton_4, 1, 1, 1, 1)

        self.pushButton = QPushButton(self.gridLayoutWidget)
        self.pushButton.setObjectName(u"pushButton")
        self.pushButton.setFont(font)

        self.gridLayout.addWidget(self.pushButton, 0, 0, 1, 1)

        self.horizontalLayoutWidget = QWidget(Form)
        self.horizontalLayoutWidget.setObjectName(u"horizontalLayoutWidget")
        self.horizontalLayoutWidget.setGeometry(QRect(9, 9, 381, 101))
        self.horizontalLayout = QHBoxLayout(self.horizontalLayoutWidget)
        self.horizontalLayout.setObjectName(u"horizontalLayout")
        self.horizontalLayout.setContentsMargins(0, 0, 0, 0)

        self.retranslateUi(Form)

        QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        Form.setWindowTitle(QCoreApplication.translate("Form", u"Form", None))
        self.pushButton_3.setText(QCoreApplication.translate("Form", u"25 Dakika", None))
        self.pushButton_2.setText(QCoreApplication.translate("Form", u"15 Dakika", None))
        self.pushButton_4.setText(QCoreApplication.translate("Form", u"35 Dakika", None))
        self.pushButton.setText(QCoreApplication.translate("Form", u"5 Dakika", None))

Kodlar sorunsuz çalışıyor ama gereksiz kod tekrarı var. Bu kod tekrarlarından kaçınmak için butonlar yerine radioButton lar kullanabilirsiniz. (4 tane radioButton 1 tane pushButton. pushButton'a tıklandığında radioButton'ları kontrol edip işlem yapacak). Ben sadece probleme odaklandım, o yüzden detaya girmedim.

Teşekkürler. Birkaç saat sonra deneyebilirim.
Güzel anlattınız. Çalışacağından eminim.
Bir de radiobutton’u henüz öğrenmemiştim.
O yüzden kod tekrarları vs. Olmuştu.

Bundan sonra show() kısmını classın içinde kullanmamaya da dikkat edeceğim.

Bir şey daha sormak istiyorum.

@Ertuğrulçakıcı 'nın yazdığı gibi yapsam.
Wait done kısmını silsem ve
Stop metodunun çalışacağı ayrı bir buton oluştursam

Müzik çaldığında oluşturduğum buton müziği durdurur mu

wait_done() kullandığınız için threading tavsiye edildi.

wait_done() kısmını silecekseniz thread kullanmanıza gerek kalmaz.

Evet, durdurabilirsiniz.

1 Beğeni

Evet tam olarak istediğimi yaptım şu anda.
Çok teşekkür ederim :blue_heart: :blue_heart: :blue_heart: :blue_heart: :blue_heart: :blue_heart:

Şuan tam istediğim gibi çalışıyor fakat
“Pomodoro Tekniği İçin Hangisini Uygulayacaksınız” yazan kısım (self.yazialani) saniye bittikten sonra değişiyor.

5 Dakikaya bastım mesela.
Yazı hala aynı.
5Dk bitiyor ondan sonra yazı değişiyor.
Dediğiniz gibi self.yazialani kısmını QLabel değil de QMessageBox yaptım.
Ama hata verdi bu sefer de.

self.yazialani = QtWidgets.QMessageBox("Pomodoro Tekniği İçin Hangisini seçeceksin ")
TypeError: arguments did not match any overloaded call:
QMessageBox(parent: QWidget = None): argument 1 has unexpected type ‘str’
QMessageBox(QMessageBox.Icon, str, str, buttons: Union[QMessageBox.StandardButtons, QMessageBox.StandardButton] = QMessageBox.NoButton, parent: QWidget = None, flags: Union[Qt.WindowFlags, Qt.WindowType] = Qt.Dialog|Qt.MSWindowsFixedSizeDialogHint): argument 1 has unexpected type ‘str’

satırların son hali aşağıdaki gibi. Neden böyle bir hata verdi ?
Ya da QMessageBox kısmını ben mi yanlış kullandım ?

import sys
from PyQt5 import QtWidgets
import simpleaudio as sa
import time


class pencere(QtWidgets.QWidget):

    def __init__(self):
        
        super().__init__()
        self.init_ui()


    def init_ui(self):
        self.yazialani = QtWidgets.QMessageBox("Pomodoro Tekniği İçin Hangisini seçeceksin ")
        self.minute = 0
        self.button1 = QtWidgets.QPushButton("25 Dakika")
        self.button2 = QtWidgets.QPushButton("5 Dakika")
        self.button3 = QtWidgets.QPushButton("20 Dakika")
        self.stopbutton = QtWidgets.QPushButton("Stop Music")
        

        v_box = QtWidgets.QVBoxLayout()
        v_box.addWidget(self.button1)
        v_box.addWidget(self.button2)
        v_box.addWidget(self.button3) 
        v_box.addWidget(self.yazialani)
        v_box.addWidget(self.stopbutton)
        v_box.addStretch()

        h_box = QtWidgets.QHBoxLayout()
        h_box.addStretch()
        h_box.addLayout(v_box)
        h_box.addStretch()

        self.setLayout(h_box)

        self.button1.clicked.connect(self.click1)
        self.button2.clicked.connect(self.click2)
        self.button3.clicked.connect(self.click3)
        self.stopbutton.clicked.connect(self.click4)
        

        


    def click1(self):
        global wave_obj
        global play_obj
        self.minute += 25
        self.yazialani.setText("{} Dakika sonra alarm  çalacaktır".format(str(self.minute)))
        time.sleep(self.minute * 60)
        wave_obj = sa.WaveObject.from_wave_file("C:/Users/taylan öztürk/Desktop/NCS/Alan Walker/Wav/Force.wav")
        play_obj = wave_obj.play()
        
        

    def click2(self):
        global wave_obj
        global play_obj
        self.minute += 0
        self.yazialani.setText("{} Dakika sonra alarm  çalacaktır".format(str(self.minute)))
        time.sleep(self.minute * 60)
        wave_obj = sa.WaveObject.from_wave_file("C:/Users/taylan öztürk/Desktop/NCS/Alan Walker/Wav/Force.wav")
        play_obj = wave_obj.play()
        


    def click3(self):
        global wave_obj
        global play_obj
        self.minute += 20
        self.yazialani.setText("{} Dakika sonra alarm  çalacaktır".format(str(self.minute)))
        time.sleep(self.minute * 60)
        wave_obj = sa.WaveObject.from_wave_file("C:/Users/taylan öztürk/Desktop/NCS/Alan Walker/Wav/Force.wav")
        play_obj = wave_obj.play()
        


    def click4(self):
        play_obj.stop()
        


    


    


app = QtWidgets.QApplication(sys.argv)
window = pencere()
window.show()
sys.exit(app.exec_())





        


    


    


app = QtWidgets.QApplication(sys.argv)
window = pencere()
window.show()
sys.exit(app.exec_())

QMessageBox argüman almıyor. İçerisindeki text'i değiştirmek istiyorsanız setText() metodunu kullanmalısınız. Ardından da QMessageBox’ı exec() etmelisiniz. Ama bunlarla uğraşmayın size daha güzel bir yöntem önereyim. QMessageBox içerisinde tanımlanmış statik fonksiyonları kullanın. Bunlar hazır fonksiyonlar oldukları için arkada exec() edilmiş halde geliyorlar.

QMessageBox - Statik fonksiyonlar

Örneğin bir bilgilendirme mesajı mı göstermek istiyorsunuz, information metodunu kullanın.

self.yazialani = QMessageBox.information(self, "Pencere Başlığı", "Mesajınız")

Benim yazdığım kodları kullanın. Aynı kodlar üzerinden ilerlersek birbirimize daha iyi yardımcı olabiliriz.

sizin attıklarınızı kullandığımda bir sürü hata gösteriyor. Nedenini anlamadım.
Yüklenmemiş Kütüphaneler olabilir belki ancak QPushButton’larda bile hata gösteriyor.

Hata mesajlarını görebilir miyim?

From kısmı bu şekilde

widget da bu şekilde

QPushButton da bu şekilde