QLineEdit'e tıklanma durumunu tetikleyecek bir fonksiyon var mı?

QLineEdit’e tıklanma durumunu kontrol edecek bir fonksiyon var mı ? Clicked fonksiyonunu aradım ancak QLineEdit’lerin böyle bir fonksiyonu yok anlaşılan.

self.target_lineEdit.clicked.connect(self.funct)

def funct(self):
    .....

şöyle bir şey yapacağımı düşünmüştüm ancak clicked fonksiyonu olmayınca bir şey yapamadım.

QLineEdit sınıfının tıklanma durumunu kontrol eden bir fonksiyon bulunuyor mu ? Bulunuyorsa bunu connect ederek bir fonksiyona bağlayabiliyor muyuz ?

Bu çok nadir, belki de hiç ihtiyaç duyulmayacak bir işlem olduğu için böyle bir metod yazılmamış.

Maalesef bunun için bir metod Qt Api’da bulunmuyor. event’lardan yardım alabiliriz ama, neden böyle bir şeye ihtiyacınız var merak ettim?

1 Beğeni

Bir XOX oyunu projem var. Kutucuklara harfleri yazarak oynuyorduk ve kodların tamamını sıfırlayıp baştan yazmaya karar verdim. Artık kutucuklara (lineEditlere) tıklanarak harf koyulacak.
Olur da böyle bir şey bulamazsak kutucukların üzerine gizli bir buton yerleştirir öyle yaparım.

bu linki bulmuştum araştırma yaparken. Ancak anlayamadım. Bir de siz bakın derim

Bu kısım ile şurası:

aynı şeyi ifade ediyor. Sinyal üretip yayma ve sonra da yakalama ihtiyacı neden onu anlamadım?

En başta lineEdit’lere klavye aracılığıyla harf giriyorduk.
Şimdi yapmaya çalıştığım ise lineEdit’lere click atılınca harf girilmesi.

Biraz daha açmam lazımdı orayı kusura bakmayın :+1:

Google’a xox yazınca karşınıza xox oyunu çıkar. Buradaki gibi tıklanarak yapmaya karar verdim.
Öncekindeyse klavye aracılığıyla harf giriyorduk.

Umarım anlatabilmişimdir.

Evet, şimdi anlaşıldı.

1 Beğeni
import sys
from PySide2.QtWidgets import*
from PySide2.QtCore import*
from PySide2.QtGui import*

class Calculator(QMainWindow):
	def __init__(self):
		super().__init__()
		self.initUi()

	def initUi(self):
		self.resize(400, 300)
		self.setWindowTitle("Calculator")
		self.widget = QWidget()
		self.result = QLineEdit()
		self.result.setReadOnly(True)

		self.player = QComboBox()
		self.player.addItems(["X", "O"])

		self.layout = QVBoxLayout()

		self.layout.addWidget(self.player)
		self.layout.addWidget(self.result)
	
		self.widget.setLayout(self.layout)
		self.setCentralWidget(self.widget)

		self.result.mousePressEvent = self.selected

	def selected(self, event):
		self.result.setText(self.player.currentText())

if __name__ == "__main__":
	app = QApplication(sys.argv)
	window = Calculator()
	window.show()
	sys.exit(app.exec_())
1 Beğeni

bir de comboBox ile göstermişsiniz. Çok teşekkür ederim.

1 Beğeni

Mouse ile pencere üzerinde herhangi bir yere tıklandığında mousePressEvent fonksiyonuna bir QMouseEvent nesnesi gönderiliyor. Bu nesnenin, içerisinde hangi bilgileri içerdiğine şuradan bakabilirsiniz.

1 Beğeni
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import ttt_ui
import sys
import random

class window(QMainWindow,ttt_ui.Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.msgbox = QMessageBox
        self.timer = QTimer
        self.bot_right_block = self.bot_left_block_2
        self.player1_score = "0"
        self.player2_score = "0"
        self.label_4.setText(self.player1_score)
        self.label_6.setText(self.player2_score)
        
        # table
        self.table = [
            [self.left_top_block, self.top_middle_block, self.top_right_block],          # row 1
            [self.middle_left_block, self.middle_middle_block, self.middle_right_block], # row 2
            [self.bot_left_block, self.bot_middle_block, self.bot_right_block]           # row 3
        ]
        
        # setting "setReadOnly" function to whole table and appending elements to our list to use them for "mouseReleaseEvent"
        self.mouseReleaseEvent_list = list() 
        for i in self.table:
            for l in i:
                l.setReadOnly(True)
                self.mouseReleaseEvent_list.append(l)
                
        # Iterations to connecting table elements to "mouseReleaseEvent" functions
        iteration = iter(self.mouseReleaseEvent_list)
        
        element_1 = next(iteration)
        element_1_connection = element_1.mouseReleaseEvent = self.MRE_function1
        
        element_2 = next(iteration)
        element_2_connection = element_2.mouseReleaseEvent = self.MRE_function2
        
        element_3 = next(iteration)
        element_3_connection = element_3.mouseReleaseEvent = self.MRE_function3
        
        element_4 = next(iteration)
        element_4_connection = element_4.mouseReleaseEvent = self.MRE_function4
        
        element_5 = next(iteration)
        element_5_connection = element_5.mouseReleaseEvent = self.MRE_function5
        
        element_6 = next(iteration)
        element_6_connection = element_6.mouseReleaseEvent = self.MRE_function6
        
        element_7 = next(iteration)
        element_7_connection = element_7.mouseReleaseEvent = self.MRE_function7
        
        element_8 = next(iteration)
        element_8_connection = element_8.mouseReleaseEvent = self.MRE_function8
        
        element_9 = next(iteration)
        element_9_connection = element_9.mouseReleaseEvent = self.MRE_function9
       
        
            
    
        
        
    # MRE = mouseReleaseEvent    
    def MRE_function1(self, event):
        print("num1 has worked")
        
    def MRE_function2(self, event):
        print("num2 has worked")
        
    def MRE_function3(self, event):
        print("num3 has worked")
        
    def MRE_function4(self, event):
        print("num4 has worked")
        
    def MRE_function5(self, event):
        print("num5 has worked")
        
    def MRE_function6(self, event):
        print("num6 has worked")
        
    def MRE_function7(self, event):
        print("num7 has workeds")
        
    def MRE_function8(self, event): 
        print("num8 has worked")
        
    def MRE_function9(self, event): 
        print("num9 has worked")
        
    
            
                
                
        
        
                
        
               
               
        
                
        
        
        
        
    
        
        
        
    
    
        
        
        
    
        
        
        
app = QApplication(sys.argv)
pencere = window()
pencere.setWindowTitle("Tic Tac Toe")
pencere.setWindowIcon(QIcon("indir.png"))
pencere.show()
sys.exit(app.exec_())
        

Bir soru daha soracağım. Yeni bir konu açmak yerine buradan tekrar size yazmak istedim, doğru mu yaptım bilmiyorum ancak basit bir konu olduğu için buradan tekrar size yazmayı tercih ettim.

Projeye ufaktan başladım, yukarıdaki attığım kodlardan da göreceğiniz üzere.
Kodların Okunaklı olduğunu düşünüyor musunuz ? Ya da yorum satırları ve değişken isimleri uygun mudur ?
Bütün table öğelerine tek tek mouseReleaseEvent ekleyip bir fonksiyona bağlamak yerine Iterations kullanmayı tercih ettim. Doğru bir tercih midir ?

yani şunu mu yapmak daha kısa ve okunaklı olurdu ? :

self.table[0][0].mouseReleaseEvent = self.MRE_function1
self.table[0][1].mouseReleaseEvent = self.MRE_function2
...
...
...
...
...

yoksa şunu mu yapmak daha kısa ve okunaklı olurdu ?

# setting "setReadOnly" function to whole table and appending elements to our list to use them for "mouseReleaseEvent"
        self.mouseReleaseEvent_list = list() 
        for i in self.table:
            for l in i:
                l.setReadOnly(True)
                self.mouseReleaseEvent_list.append(l)
                
        # Iterations to connecting table elements to "mouseReleaseEvent" functions
        iteration = iter(self.mouseReleaseEvent_list)
        
        element_1 = next(iteration)
        element_1_connection = element_1.mouseReleaseEvent = self.MRE_function1
        
        element_2 = next(iteration)
        element_2_connection = element_2.mouseReleaseEvent = self.MRE_function2
        
        element_3 = next(iteration)
        element_3_connection = element_3.mouseReleaseEvent = self.MRE_function3
        
        element_4 = next(iteration)
        element_4_connection = element_4.mouseReleaseEvent = self.MRE_function4
        
        element_5 = next(iteration)
        element_5_connection = element_5.mouseReleaseEvent = self.MRE_function5
        
        element_6 = next(iteration)
        element_6_connection = element_6.mouseReleaseEvent = self.MRE_function6
        
        element_7 = next(iteration)
        element_7_connection = element_7.mouseReleaseEvent = self.MRE_function7
        
        element_8 = next(iteration)
        element_8_connection = element_8.mouseReleaseEvent = self.MRE_function8
        
        element_9 = next(iteration)
        element_9_connection = element_9.mouseReleaseEvent = self.MRE_function9
       

Bunun dışında daha doğru yazılabilecek yorum satırları veya değişken isimleri görüyor musunuz ?

Skorlar integer tipinde olsa iyi olur, rahatlıkla artırabilmeniz için. Display ederken string'e dönüştürmeniz yeterli.

Bunlar lineEdit’ler mi? Eğer öyle ise şurası hata vermeli:

Çünkü QLineEdit nesneleri iterable değiller.

Bu kısımda basit bir for döngüsünü elle yazmışsınız.

Bu kadar fonksiyona gerek yok. Sadece bir tane kontrol mekanizması olması yeterli, ki daha okunaklı bir kod olmasını da sağlar.

Değişken isimleri iyi, yalnızca self.table'ın ismini self.blocks olarak değiştirin. Çünkü liste içerisinde çok fazla block kelimesi kullanılmış. Yorum satırları iyi.

Tüm QLineEdit'leri bir fonksiyona bağlamak bir çok açıdan daha doğru olur:

for lineEdit in self.table:
	lineEdit.setReadOnly(True)
	lineEdit.mouseReleaseEvent = self.control # hamle yapıldı

def control(self):
	pass

Bunların dışında, tavsiye olarak;

Kullanacağınız algoritmayı düşünürken, projeye geniş bir çerçeveden bakın. Şimdiki durumu ve ileride yapacağınız eklemeleri düşünün. Sadece önünüzdeki probleme odaklanmayın, “bunu çözeyim de, sonrasına sonra bakarım” demeyin. Yeni bir özellik, öncesindeki ve sonrasındaki özelliklere zarar verebilir. Programın tutarsız, stabil çalışmaması ve çokca bug içermesi gayet olası.

1 Beğeni

Evet onlar lineEdit.
İterable değillerdir belki ancak sonuçta listenin içinde döndüğüm için hata vermiyordur bence.

Farkındayım çünkü tek bir for döngüsü yazmak hepsini aynı fonksiyona bağlayacaktı ancak ben öyle olmasını istemiyorum.

Dediğim gibi bir fonksiyona bağlamak istemiyorum. Bunun sebebi; eğer bir fonksiyona bağlarsam, lineEditlere tıklanma durumunu kontrol edemem.
Yani bir lineEdite tıklıyorum. Sadece tıklamış olduğum lineEdit’e X koyması lazım. Ancak hepsini tek bir fonksiyona bağlarsam olmaz çünkü tıklamış olduğum lineEdite X koyululduktan sonra diğer LineEditler de aynı fonksiyona bağlı olduğu için onlara da X koyulur.
Umarım anlatabilmişimdir :sweat_smile:

Fonksiyonu şöyle düşünüyorum bakınız :

Def MRE_funct(self, event) :
        self.table[0][0].setTexf("X")
        self.table[0][1].setText("X" )
       ..... 

Eğer bir tane lineEdite tıklarsam, bütün tıklanma durumları bu fonksiyona bağlı olduğu için bütün tıklanma durumları aynı işlevi gerçekleştirir dolayısıyla da bütün lineEditlere “X” stringi setText edilir. Neden? Çünkü bu fonksiyonun içinde bütün lineEditlere “X” koyulması gerektiği söyleniyor ve söylenilmesi de gerekli.

ayrı ayrı fonksiyon yazmak doğru bir tercih miydi? Yoksa bahsettiğim durum değiştirilebilir mi?
If bloklarıyla kontrol edilebilir mi ?

def MRE_funct(self, event) : 
    if self.table[0][0].triggered:
           self.table[0][0].setText("X")
    .........

Yani If bloklarıyla bunun gibi bir şey yapılır mı ? Ya da dediğim gibi başka bir şekilde bahsettiğim durumu değiştirmek mümkün mü ? Ben böyle bir şeyin mümkün olup olmadığını bilmediğim için ve üzerinde herhangi bir tahmin yürütemediğim için mümkün değil varsayarak ayrı ayrı fonksiyonlara bağlamayı tercih ettim.

Anlaşılamadıysam belirtin lütfen daha daha detaylı yazarım.

Edit :

Eğer böyle bir şey mümkün değilse, yaptığım iteration’u for döngüsüyle yapmak mümkün müdür ?
Ben en baştan iteratorler kullanarak yapmaya çabaladım çünkü dediğim gibi hepsi birbirinden farklı fonksiyonlara bağlanıyorlar. Az önce belki for döngüsüyle de yapılır diyerek bir şeyler denedim.

objects = [
            self.table[0][0], self.table[0][1], self.table[0][2], # row 1
            self.table[1][0], self.table[1][1], self.table[1][2], # row 2
            self.table[2][0], self.table[2][1], self.table[2][2]  # row 3
        ]
        
        MRE_Functions = [
            self.MRE_function1, self.MRE_function2, self.MRE_function3, 
            self.MRE_function4, self.MRE_function5, self.MRE_function6, 
            self.MRE_function7, self.MRE_function8, self.MRE_function9
        ]
        
        for objects in objects:
            for self.functs in MRE_Functions:
                objects.mouseReleaseEvent = self.functs

Burada da anlaşılır olacak şekilde yazmaya çalıştım. Yukarıdaki kodları yazdığım zaman gerçekten de fonksiyona bağlanılıyor ancak hangi lineEdit’e tıklarsam tıklayayım “num9 has worked” çıktısını veriyor. Sağ alttaki bloğa denk geliyor bu da. Yani table[2][2] öğesine. Sadece table[2][2] öğesinin çalışmasını beklememiştim açıkçası :thinking:

self.table[0][0].mouseReleaseEvent = self.MRE_function1
self.table[0][1].mouseReleaseEvent = self.MRE_function2 
self.table[0][2].mouseReleaseEvent = self.MRE_function3
....

Bu for döngüsünün bunu ifade edeceğini düşünmüştüm açıkçası.

Ben şöyle düşünmüştüm, tüm lineedit’lerin sinyalini kontrol fonksiyonuna bağlarız. Ordan da ‘sıra’ hangi oyuncuda ise (x,o) ona göre kutucuğa “X” veya “O” yazacaktık. Fakat üretilen sinyal bize sadece QMouseEvent nesnesini veriyor, bu nesne üzerinden de kısıtlı bilgilere erişebiliyoruz. Hangi butonla tıklandığı, mouse pozisyonu vs.

Dolayısıyla haklısınız, hangi lineedit’e tıklandığını bilemiyoruz. Şöyle bir yöntem düşündüm, acaba tıklanan koordinattaki nesneyi alabilir miyiz? Araştırınca, bunun mümkün olduğunu öğrendim;

QMainWindow.childAt(x,y)
Return type: QWidget

Uygulamaya geçirmeye çalıştığımda, tüm QLineEdit nesnelerinin etkilendiğini gördüm, doğal olarak. Çünkü bu metod eğer verilen pozisyonda bir QWidget nesnesi var ise nesneyi döndürüyor. event’dan gelen koordinatta centralWidget (merkezi/ana widget) var. lineEdit’lerimiz de bu widget üzerinde olduğu için hepsi etkileniyor. Doğrudan QLineEdit'i vermeye kalkışsak bu kez hiçbir şey elde edemeyiz, çünkü QLineEdit bir widget değil:

lineEdit = QLineEdit()
lineEdit.mouseReleaseEvent = self.selected

def selected(self, event):
	print(self.childAt(event.pos()))

Output: None

Belki QLineEdit'leri ayrı ayrı QWidget nesneleri üzerine yerleştirmek problemi çözebilir ama bende onu yapacak hal kalmadı :slight_smile: İsterseniz deneyip görün, ya da her kutucuk için ayrı fonksiyon yazın. Daha sonra, daha iyi bir fikir bulduğunuzda tekrar düzeltirsiniz.

İyi çalışmalar.

1 Beğeni

Uğraşınız için çok teşekkür ederim. lineEdit sınıfları centralWidget’ı miras aldıkları için hepsi etkileniyor. Onları farklı widgetlara koyarak

bu kodu kullanmamı istiyorsunuz doğru anlamışım değil mi ?

Kullanıcı her zaman X’i oynayacak. O’yu ise bilgisayar oynayacaktı.

bunun dışında

şu for döngüsü kullanımım doğru olmuş mu ? Neden sadece table[2][2] öğesi çalışıyor ? Kısaca cevaplayabilir misiniz ?
13. gönderimde biraz daha detaylı yazdım burayı

Evet, centralWidget'ı tamamen kaldırın, gerek yok.

Daha az kod demek.

Hayır. for objects in objects ilginç olmuş, döngü için (her iter'i temsil eden değişken olarak) sınıf niteliği kullanımını da ilk kez görüyorum: for self.functs in MRE_Functions

Emin değilim ama döngüyü dediğim gibi düzeltirseniz, problem belki çözülebilir. Problem çözülmezse tekrar bakalım.

sınıf niteliğinde yazdım çünkü bağlayacağım fonksiyonlar da sınıf niteliğinde.

Yanlış mı yapmışım ?

Bu şart değil, x isminde bir değişken de aynı işi yapabilir.

Evet yapıyormuş. Self’i çıkararak denedim ancak yine aynı sonucu verdi. (“num9 has worked”)

İsterseniz size ui ve main dosyasını atayım, kendiniz kurcalayarak incelersiniz. Sizi de yormak istemiyorum açıkçası. Bence ben bir süre bir şeyler deneyeyim. Hiç olmazsa size mesaj atarım olur mu ?